diff options
Diffstat (limited to 'poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View')
45 files changed, 12598 insertions, 0 deletions
diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/exception_stack_trace.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/exception_stack_trace.ctp new file mode 100644 index 0000000..b744c16 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/exception_stack_trace.ctp @@ -0,0 +1,75 @@ +<?php +/** + * Prints a stack trace for an exception + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Elements + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::uses('Debugger', 'Utility'); +?> +<h3>Stack Trace</h3> +<ul class="cake-stack-trace"> +<?php foreach ($error->getTrace() as $i => $stack): ?> + <li><?php + $excerpt = $arguments = ''; + $params = array(); + + if (isset($stack['file']) && isset($stack['line'])): + printf( + '<a href="#" onclick="traceToggle(event, \'file-excerpt-%s\')">%s line %s</a>', + $i, + Debugger::trimPath($stack['file']), + $stack['line'] + ); + $excerpt = sprintf('<div id="file-excerpt-%s" class="cake-code-dump" style="display:none;"><pre>', $i); + $excerpt .= implode("\n", Debugger::excerpt($stack['file'], $stack['line'] - 1, 2)); + $excerpt .= '</pre></div> '; + else: + echo '<a href="#">[internal function]</a>'; + endif; + echo ' → '; + if ($stack['function']): + $args = array(); + if (!empty($stack['args'])): + foreach ((array)$stack['args'] as $arg): + $args[] = Debugger::getType($arg); + $params[] = Debugger::exportVar($arg, 2); + endforeach; + endif; + + $called = isset($stack['class']) ? $stack['class'] . $stack['type'] . $stack['function'] : $stack['function']; + + printf( + '<a href="#" onclick="traceToggle(event, \'trace-args-%s\')">%s(%s)</a> ', + $i, + $called, + implode(', ', $args) + ); + $arguments = sprintf('<div id="trace-args-%s" class="cake-code-dump" style="display: none;"><pre>', $i); + $arguments .= implode("\n", $params); + $arguments .= '</pre></div>'; + endif; + echo $excerpt; + echo $arguments; + ?></li> +<?php endforeach; ?> +</ul> +<script type="text/javascript"> +function traceToggle(event, id) { + var el = document.getElementById(id); + el.style.display = (el.style.display == 'block') ? 'none' : 'block'; + event.preventDefault(); + return false; +} +</script> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/sql_dump.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/sql_dump.ctp new file mode 100644 index 0000000..c8e634d --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/sql_dump.ctp @@ -0,0 +1,74 @@ +<?php +/** + * SQL Dump element. Dumps out SQL log information + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Elements + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +if (!class_exists('ConnectionManager') || Configure::read('debug') < 2) { + return false; +} +$noLogs = !isset($logs); +if ($noLogs): + $sources = ConnectionManager::sourceList(); + + $logs = array(); + foreach ($sources as $source): + $db = ConnectionManager::getDataSource($source); + if (!method_exists($db, 'getLog')): + continue; + endif; + $logs[$source] = $db->getLog(); + endforeach; +endif; + +if ($noLogs || isset($_forced_from_dbo_)): + foreach ($logs as $source => $logInfo): + $text = $logInfo['count'] > 1 ? 'queries' : 'query'; + printf( + '<table class="cake-sql-log" id="cakeSqlLog_%s" summary="Cake SQL Log" cellspacing="0">', + preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true)) + ); + printf('<caption>(%s) %s %s took %s ms</caption>', $source, $logInfo['count'], $text, $logInfo['time']); + ?> + <thead> + <tr><th>Nr</th><th>Query</th><th>Error</th><th>Affected</th><th>Num. rows</th><th>Took (ms)</th></tr> + </thead> + <tbody> + <?php + foreach ($logInfo['log'] as $k => $i) : + $i += array('error' => ''); + if (!empty($i['params']) && is_array($i['params'])) { + $bindParam = $bindType = null; + if (preg_match('/.+ :.+/', $i['query'])) { + $bindType = true; + } + foreach ($i['params'] as $bindKey => $bindVal) { + if ($bindType === true) { + $bindParam .= h($bindKey) ." => " . h($bindVal) . ", "; + } else { + $bindParam .= h($bindVal) . ", "; + } + } + $i['query'] .= " , params[ " . rtrim($bindParam, ', ') . " ]"; + } + echo "<tr><td>" . ($k + 1) . "</td><td>" . h($i['query']) . "</td><td>{$i['error']}</td><td style = \"text-align: right\">{$i['affected']}</td><td style = \"text-align: right\">{$i['numRows']}</td><td style = \"text-align: right\">{$i['took']}</td></tr>\n"; + endforeach; + ?> + </tbody></table> + <?php + endforeach; +else: + echo '<p>Encountered unexpected $logs cannot generate SQL log</p>'; +endif; diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/fatal_error.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/fatal_error.ctp new file mode 100644 index 0000000..d7c6e76 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/fatal_error.ctp @@ -0,0 +1,35 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 2.2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Fatal Error'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo h($error->getMessage()); ?> + <br> + + <strong><?php echo __d('cake_dev', 'File'); ?>: </strong> + <?php echo h($error->getFile()); ?> + <br> + + <strong><?php echo __d('cake_dev', 'Line'); ?>: </strong> + <?php echo h($error->getLine()); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'fatal_error.ctp'); ?> +</p> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_action.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_action.ctp new file mode 100644 index 0000000..614933e --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_action.ctp @@ -0,0 +1,42 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Method in %s', $controller); ?></h2> <p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'The action %1$s is not defined in controller %2$s', '<em>' . $action . '</em>', '<em>' . $controller . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Create %1$s%2$s in file: %3$s.', '<em>' . $controller . '::</em>', '<em>' . $action . '()</em>', APP_DIR . DS . 'Controller' . DS . $controller . '.php'); ?> +</p> +<pre> +<?php +class <?php echo $controller; ?> extends AppController { + +<strong> + public function <?php echo $action; ?>() { + + } +</strong> +} +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_action.ctp'); ?> +</p> +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_behavior.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_behavior.ctp new file mode 100644 index 0000000..3bb8722 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_behavior.ctp @@ -0,0 +1,40 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +$pluginDot = empty($plugin) ? null : $plugin . '.'; +?> +<h2><?php echo __d('cake_dev', 'Missing Behavior'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s could not be found.', '<em>' . $pluginDot . $class . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Create the class %s below in file: %s', '<em>' . $class . '</em>', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'Model' . DS . 'Behavior' . DS . $class . '.php'); ?> +</p> +<pre> +<?php +class <?php echo $class; ?> extends ModelBehavior { + +} +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_behavior.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_component.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_component.ctp new file mode 100644 index 0000000..d0e6d23 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_component.ctp @@ -0,0 +1,40 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +$pluginDot = empty($plugin) ? null : $plugin . '.'; +?> +<h2><?php echo __d('cake_dev', 'Missing Component'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s could not be found.', '<em>' . $pluginDot . $class . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Create the class %s below in file: %s', '<em>' . $class . '</em>', (empty($plugin) ? APP_DIR : CakePlugin::path($plugin)) . DS . 'Controller' . DS . 'Component' . DS . $class . '.php'); ?> +</p> +<pre> +<?php +class <?php echo $class; ?> extends Component { + +} +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_component.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_connection.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_connection.ctp new file mode 100644 index 0000000..b29fb9f --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_connection.ctp @@ -0,0 +1,36 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Database Connection'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s requires a database connection', $class); ?> +</p> +<?php if (!$enabled) : ?> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s driver is NOT enabled', $class); ?> +</p> +<?php endif; ?> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s.', APP_DIR . DS . 'View' . DS . 'Errors' . DS . basename(__FILE__)); ?> +</p> + +<?php +echo $this->element('exception_stack_trace'); diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_controller.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_controller.ctp new file mode 100644 index 0000000..b4acb8e --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_controller.ctp @@ -0,0 +1,40 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +$pluginDot = empty($plugin) ? null : $plugin . '.'; +?> +<h2><?php echo __d('cake_dev', 'Missing Controller'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s could not be found.', '<em>' . $pluginDot . $class . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Create the class %s below in file: %s', '<em>' . $class . '</em>', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'Controller' . DS . $class . '.php'); ?> +</p> +<pre> +<?php +class <?php echo $class . ' extends ' . $plugin; ?>AppController { + +} +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_controller.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_database.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_database.ctp new file mode 100644 index 0000000..a8c892e --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_database.ctp @@ -0,0 +1,33 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Database Connection'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Scaffold requires a database connection'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Confirm you have created the file: %s', APP_DIR . DS . 'Config' . DS . 'database.php'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_database.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource.ctp new file mode 100644 index 0000000..d3df930 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource.ctp @@ -0,0 +1,30 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +$pluginDot = empty($plugin) ? null : $plugin . '.'; +?> +<h2><?php echo __d('cake_dev', 'Missing Datasource'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Datasource class %s could not be found.', '<em>' . $pluginDot . $class . '</em>'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_datasource.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource_config.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource_config.ctp new file mode 100644 index 0000000..3bc6ff7 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource_config.ctp @@ -0,0 +1,29 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Datasource Configuration'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'The datasource configuration %1$s was not found in database.php.', '<em>' . $config . '</em>'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_datasource_config.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_helper.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_helper.ctp new file mode 100644 index 0000000..62d7585 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_helper.ctp @@ -0,0 +1,40 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +$pluginDot = empty($plugin) ? null : $plugin . '.'; +?> +<h2><?php echo __d('cake_dev', 'Missing Helper'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s could not be found.', '<em>' . $pluginDot . $class . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Create the class %s below in file: %s', '<em>' . $class . '</em>', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'View' . DS . 'Helper' . DS . $class . '.php'); ?> +</p> +<pre> +<?php +class <?php echo $class; ?> extends AppHelper { + +} +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_helper.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_layout.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_layout.ctp new file mode 100644 index 0000000..f623b61 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_layout.ctp @@ -0,0 +1,33 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Layout'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'The layout file %s can not be found or does not exist.', '<em>' . $file . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Confirm you have created the file: %s', '<em>' . $file . '</em>'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_layout.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_plugin.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_plugin.ctp new file mode 100644 index 0000000..9d3f7ce --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_plugin.ctp @@ -0,0 +1,45 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Plugin'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'The application is trying to load a file from the %s plugin', '<em>' . $plugin . '</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Make sure your plugin %s is in the ' . APP_DIR . DS . 'Plugin directory and was loaded', $plugin); ?> +</p> +<pre> +<?php +CakePlugin::load('<?php echo $plugin?>'); + +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Loading all plugins'); ?>: </strong> + <?php echo __d('cake_dev', 'If you wish to load all plugins at once, use the following line in your ' . APP_DIR . DS . 'Config' . DS . 'bootstrap.php file'); ?> +</p> +<pre> +CakePlugin::loadAll(); +</pre> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_plugin.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_table.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_table.ctp new file mode 100644 index 0000000..6e65871 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_table.ctp @@ -0,0 +1,29 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing Database Table'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Table %1$s for model %2$s was not found in datasource %3$s.', '<em>' . $table . '</em>', '<em>' . $class . '</em>', '<em>' . $ds . '</em>'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_table.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_view.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_view.ctp new file mode 100644 index 0000000..c3b5920 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_view.ctp @@ -0,0 +1,33 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Missing View'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'The view for %1$s%2$s was not found.', '<em>' . Inflector::camelize($this->request->controller) . 'Controller::</em>', '<em>' . $this->request->action . '()</em>'); ?> +</p> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Confirm you have created the file: %s', $file); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'missing_view.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/pdo_error.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/pdo_error.ctp new file mode 100644 index 0000000..9aecee6 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/pdo_error.ctp @@ -0,0 +1,38 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Database Error'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo h($error->getMessage()); ?> +</p> +<?php if (!empty($error->queryString)) : ?> + <p class="notice"> + <strong><?php echo __d('cake_dev', 'SQL Query'); ?>: </strong> + <?php echo $error->queryString; ?> + </p> +<?php endif; ?> +<?php if (!empty($error->params)) : ?> + <strong><?php echo __d('cake_dev', 'SQL Query Params'); ?>: </strong> + <?php echo Debugger::dump($error->params); ?> +<?php endif; ?> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'pdo_error.ctp'); ?> +</p> +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/private_action.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/private_action.ctp new file mode 100644 index 0000000..74264a2 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/private_action.ctp @@ -0,0 +1,29 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Private Method in %s', $controller); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', '%s%s cannot be accessed directly.', '<em>' . $controller . '::</em>', '<em>' . $action . '()</em>'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'private_action.ctp'); ?> +</p> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/scaffold_error.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/scaffold_error.ctp new file mode 100644 index 0000000..492c561 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/scaffold_error.ctp @@ -0,0 +1,36 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Errors + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<h2><?php echo __d('cake_dev', 'Scaffold Error'); ?></h2> +<p class="error"> + <strong><?php echo __d('cake_dev', 'Error'); ?>: </strong> + <?php echo __d('cake_dev', 'Method _scaffoldError in was not found in the controller'); ?> +</p> +<p class="notice"> + <strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong> + <?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'scaffold_error.ctp'); ?> +</p> +<pre> +<?php +function _scaffoldError() {<br /> + +} + +</pre> + +<?php echo $this->element('exception_stack_trace'); ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper.php new file mode 100644 index 0000000..f6b17ac --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper.php @@ -0,0 +1,914 @@ +<?php +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since CakePHP(tm) v 0.2.9 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('Router', 'Routing'); + +/** + * Abstract base class for all other Helpers in CakePHP. + * Provides common methods and features. + * + * @package Cake.View + */ +class Helper extends Object { + +/** + * List of helpers used by this helper + * + * @var array + */ + public $helpers = array(); + +/** + * A helper lookup table used to lazy load helper objects. + * + * @var array + */ + protected $_helperMap = array(); + +/** + * The current theme name if any. + * + * @var string + */ + public $theme = null; + +/** + * Request object + * + * @var CakeRequest + */ + public $request = null; + +/** + * Plugin path + * + * @var string + */ + public $plugin = null; + +/** + * Holds the fields array('field_name' => array('type' => 'string', 'length' => 100), + * primaryKey and validates array('field_name') + * + * @var array + */ + public $fieldset = array(); + +/** + * Holds tag templates. + * + * @var array + */ + public $tags = array(); + +/** + * Holds the content to be cleaned. + * + * @var mixed + */ + protected $_tainted = null; + +/** + * Holds the cleaned content. + * + * @var mixed + */ + protected $_cleaned = null; + +/** + * The View instance this helper is attached to + * + * @var View + */ + protected $_View; + +/** + * A list of strings that should be treated as suffixes, or + * sub inputs for a parent input. This is used for date/time + * inputs primarily. + * + * @var array + */ + protected $_fieldSuffixes = array( + 'year', 'month', 'day', 'hour', 'min', 'second', 'meridian' + ); + +/** + * The name of the current model entities are in scope of. + * + * @see Helper::setEntity() + * @var string + */ + protected $_modelScope; + +/** + * The name of the current model association entities are in scope of. + * + * @see Helper::setEntity() + * @var string + */ + protected $_association; + +/** + * The dot separated list of elements the current field entity is for. + * + * @see Helper::setEntity() + * @var string + */ + protected $_entityPath; + +/** + * Minimized attributes + * + * @var array + */ + protected $_minimizedAttributes = array( + 'compact', 'checked', 'declare', 'readonly', 'disabled', 'selected', + 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize', + 'autoplay', 'controls', 'loop', 'muted' + ); + +/** + * Format to attribute + * + * @var string + */ + protected $_attributeFormat = '%s="%s"'; + +/** + * Format to attribute + * + * @var string + */ + protected $_minimizedAttributeFormat = '%s="%s"'; + +/** + * Default Constructor + * + * @param View $View The View this helper is being attached to. + * @param array $settings Configuration settings for the helper. + */ + public function __construct(View $View, $settings = array()) { + $this->_View = $View; + $this->request = $View->request; + if (!empty($this->helpers)) { + $this->_helperMap = ObjectCollection::normalizeObjectArray($this->helpers); + } + } + +/** + * Provide non fatal errors on missing method calls. + * + * @param string $method Method to invoke + * @param array $params Array of params for the method. + * @return void + */ + public function __call($method, $params) { + trigger_error(__d('cake_dev', 'Method %1$s::%2$s does not exist', get_class($this), $method), E_USER_WARNING); + } + +/** + * Lazy loads helpers. Provides access to deprecated request properties as well. + * + * @param string $name Name of the property being accessed. + * @return mixed Helper or property found at $name + */ + public function __get($name) { + if (isset($this->_helperMap[$name]) && !isset($this->{$name})) { + $settings = array_merge((array)$this->_helperMap[$name]['settings'], array('enabled' => false)); + $this->{$name} = $this->_View->loadHelper($this->_helperMap[$name]['class'], $settings); + } + if (isset($this->{$name})) { + return $this->{$name}; + } + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name}; + case 'action': + return isset($this->request->params['action']) ? $this->request->params['action'] : ''; + case 'params': + return $this->request; + } + } + +/** + * Provides backwards compatibility access for setting values to the request object. + * + * @param string $name Name of the property being accessed. + * @param mixed $value + * @return mixed Return the $value + */ + public function __set($name, $value) { + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name} = $value; + case 'action': + return $this->request->params['action'] = $value; + } + return $this->{$name} = $value; + } + +/** + * Finds URL for specified action. + * + * Returns a URL pointing at the provided parameters. + * + * @param string|array $url Either a relative string url like `/products/view/23` or + * an array of url parameters. Using an array for urls will allow you to leverage + * the reverse routing features of CakePHP. + * @param boolean $full If true, the full base URL will be prepended to the result + * @return string Full translated URL with base path. + * @link http://book.cakephp.org/2.0/en/views/helpers.html + */ + public function url($url = null, $full = false) { + return h(Router::url($url, $full)); + } + +/** + * Checks if a file exists when theme is used, if no file is found default location is returned + * + * @param string $file The file to create a webroot path to. + * @return string Web accessible path to file. + */ + public function webroot($file) { + $asset = explode('?', $file); + $asset[1] = isset($asset[1]) ? '?' . $asset[1] : null; + $webPath = "{$this->request->webroot}" . $asset[0]; + $file = $asset[0]; + + if (!empty($this->theme)) { + $file = trim($file, '/'); + $theme = $this->theme . '/'; + + if (DS === '\\') { + $file = str_replace('/', '\\', $file); + } + + if (file_exists(Configure::read('App.www_root') . 'theme' . DS . $this->theme . DS . $file)) { + $webPath = "{$this->request->webroot}theme/" . $theme . $asset[0]; + } else { + $themePath = App::themePath($this->theme); + $path = $themePath . 'webroot' . DS . $file; + if (file_exists($path)) { + $webPath = "{$this->request->webroot}theme/" . $theme . $asset[0]; + } + } + } + if (strpos($webPath, '//') !== false) { + return str_replace('//', '/', $webPath . $asset[1]); + } + return $webPath . $asset[1]; + } + +/** + * Generate url for given asset file. Depending on options passed provides full url with domain name. + * Also calls Helper::assetTimestamp() to add timestamp to local files + * + * @param string|array Path string or url array + * @param array $options Options array. Possible keys: + * `fullBase` Return full url with domain name + * `pathPrefix` Path prefix for relative urls + * `ext` Asset extension to append + * `plugin` False value will prevent parsing path as a plugin + * @return string Generated url + */ + public function assetUrl($path, $options = array()) { + if (is_array($path)) { + $path = $this->url($path, !empty($options['fullBase'])); + } elseif (strpos($path, '://') === false) { + if (!array_key_exists('plugin', $options) || $options['plugin'] !== false) { + list($plugin, $path) = $this->_View->pluginSplit($path, false); + } + if (!empty($options['pathPrefix']) && $path[0] !== '/') { + $path = $options['pathPrefix'] . $path; + } + if ( + !empty($options['ext']) && + strpos($path, '?') === false && + substr($path, -strlen($options['ext'])) !== $options['ext'] + ) { + $path .= $options['ext']; + } + if (isset($plugin)) { + $path = Inflector::underscore($plugin) . '/' . $path; + } + $path = h($this->assetTimestamp($this->webroot($path))); + + if (!empty($options['fullBase'])) { + $base = $this->url('/', true); + $len = strlen($this->request->webroot); + if ($len) { + $base = substr($base, 0, -$len); + } + $path = $base . $path; + } + } + + return $path; + } + +/** + * Adds a timestamp to a file based resource based on the value of `Asset.timestamp` in + * Configure. If Asset.timestamp is true and debug > 0, or Asset.timestamp == 'force' + * a timestamp will be added. + * + * @param string $path The file path to timestamp, the path must be inside WWW_ROOT + * @return string Path with a timestamp added, or not. + */ + public function assetTimestamp($path) { + $stamp = Configure::read('Asset.timestamp'); + $timestampEnabled = $stamp === 'force' || ($stamp === true && Configure::read('debug') > 0); + if ($timestampEnabled && strpos($path, '?') === false) { + $filepath = preg_replace('/^' . preg_quote($this->request->webroot, '/') . '/', '', $path); + $webrootPath = WWW_ROOT . str_replace('/', DS, $filepath); + if (file_exists($webrootPath)) { + return $path . '?' . @filemtime($webrootPath); + } + $segments = explode('/', ltrim($filepath, '/')); + if ($segments[0] === 'theme') { + $theme = $segments[1]; + unset($segments[0], $segments[1]); + $themePath = App::themePath($theme) . 'webroot' . DS . implode(DS, $segments); + return $path . '?' . @filemtime($themePath); + } else { + $plugin = Inflector::camelize($segments[0]); + if (CakePlugin::loaded($plugin)) { + unset($segments[0]); + $pluginPath = CakePlugin::path($plugin) . 'webroot' . DS . implode(DS, $segments); + return $path . '?' . @filemtime($pluginPath); + } + } + } + return $path; + } + +/** + * Used to remove harmful tags from content. Removes a number of well known XSS attacks + * from content. However, is not guaranteed to remove all possibilities. Escaping + * content is the best way to prevent all possible attacks. + * + * @param string|array $output Either an array of strings to clean or a single string to clean. + * @return string|array cleaned content for output + */ + public function clean($output) { + $this->_reset(); + if (empty($output)) { + return null; + } + if (is_array($output)) { + foreach ($output as $key => $value) { + $return[$key] = $this->clean($value); + } + return $return; + } + $this->_tainted = $output; + $this->_clean(); + return $this->_cleaned; + } + +/** + * Returns a space-delimited string with items of the $options array. If a + * key of $options array happens to be one of: + * + * - 'compact' + * - 'checked' + * - 'declare' + * - 'readonly' + * - 'disabled' + * - 'selected' + * - 'defer' + * - 'ismap' + * - 'nohref' + * - 'noshade' + * - 'nowrap' + * - 'multiple' + * - 'noresize' + * + * And its value is one of: + * + * - '1' (string) + * - 1 (integer) + * - true (boolean) + * - 'true' (string) + * + * Then the value will be reset to be identical with key's name. + * If the value is not one of these 3, the parameter is not output. + * + * 'escape' is a special option in that it controls the conversion of + * attributes to their html-entity encoded equivalents. Set to false to disable html-encoding. + * + * If value for any option key is set to `null` or `false`, that option will be excluded from output. + * + * @param array $options Array of options. + * @param array $exclude Array of options to be excluded, the options here will not be part of the return. + * @param string $insertBefore String to be inserted before options. + * @param string $insertAfter String to be inserted after options. + * @return string Composed attributes. + * @deprecated This method will be moved to HtmlHelper in 3.0 + */ + protected function _parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) { + if (!is_string($options)) { + $options = (array)$options + array('escape' => true); + + if (!is_array($exclude)) { + $exclude = array(); + } + + $exclude = array('escape' => true) + array_flip($exclude); + $escape = $options['escape']; + $attributes = array(); + + foreach ($options as $key => $value) { + if (!isset($exclude[$key]) && $value !== false && $value !== null) { + $attributes[] = $this->_formatAttribute($key, $value, $escape); + } + } + $out = implode(' ', $attributes); + } else { + $out = $options; + } + return $out ? $insertBefore . $out . $insertAfter : ''; + } + +/** + * Formats an individual attribute, and returns the string value of the composed attribute. + * Works with minimized attributes that have the same value as their name such as 'disabled' and 'checked' + * + * @param string $key The name of the attribute to create + * @param string $value The value of the attribute to create. + * @param boolean $escape Define if the value must be escaped + * @return string The composed attribute. + * @deprecated This method will be moved to HtmlHelper in 3.0 + */ + protected function _formatAttribute($key, $value, $escape = true) { + $attribute = ''; + if (is_array($value)) { + $value = implode(' ' , $value); + } + + if (is_numeric($key)) { + $attribute = sprintf($this->_minimizedAttributeFormat, $value, $value); + } elseif (in_array($key, $this->_minimizedAttributes)) { + if ($value === 1 || $value === true || $value === 'true' || $value === '1' || $value == $key) { + $attribute = sprintf($this->_minimizedAttributeFormat, $key, $key); + } + } else { + $attribute = sprintf($this->_attributeFormat, $key, ($escape ? h($value) : $value)); + } + return $attribute; + } + +/** + * Sets this helper's model and field properties to the dot-separated value-pair in $entity. + * + * @param string $entity A field name, like "ModelName.fieldName" or "ModelName.ID.fieldName" + * @param boolean $setScope Sets the view scope to the model specified in $tagValue + * @return void + */ + public function setEntity($entity, $setScope = false) { + if ($entity === null) { + $this->_modelScope = false; + } + if ($setScope === true) { + $this->_modelScope = $entity; + } + $parts = array_values(Hash::filter(explode('.', $entity))); + if (empty($parts)) { + return; + } + $count = count($parts); + $lastPart = isset($parts[$count - 1]) ? $parts[$count - 1] : null; + + // Either 'body' or 'date.month' type inputs. + if ( + ($count === 1 && $this->_modelScope && $setScope == false) || + ( + $count === 2 && + in_array($lastPart, $this->_fieldSuffixes) && + $this->_modelScope && + $parts[0] !== $this->_modelScope + ) + ) { + $entity = $this->_modelScope . '.' . $entity; + } + + // 0.name, 0.created.month style inputs. Excludes inputs with the modelScope in them. + if ( + $count >= 2 && + is_numeric($parts[0]) && + !is_numeric($parts[1]) && + $this->_modelScope && + strpos($entity, $this->_modelScope) === false + ) { + $entity = $this->_modelScope . '.' . $entity; + } + + $this->_association = null; + + $isHabtm = ( + isset($this->fieldset[$this->_modelScope]['fields'][$parts[0]]['type']) && + $this->fieldset[$this->_modelScope]['fields'][$parts[0]]['type'] === 'multiple' && + $count == 1 + ); + + // habtm models are special + if ($count == 1 && $isHabtm) { + $this->_association = $parts[0]; + $entity = $parts[0] . '.' . $parts[0]; + } else { + // check for associated model. + $reversed = array_reverse($parts); + foreach ($reversed as $i => $part) { + if ($i > 0 && preg_match('/^[A-Z]/', $part)) { + $this->_association = $part; + break; + } + } + } + $this->_entityPath = $entity; + } + +/** + * Returns the entity reference of the current context as an array of identity parts + * + * @return array An array containing the identity elements of an entity + */ + public function entity() { + return explode('.', $this->_entityPath); + } + +/** + * Gets the currently-used model of the rendering context. + * + * @return string + */ + public function model() { + if ($this->_association) { + return $this->_association; + } + return $this->_modelScope; + } + +/** + * Gets the currently-used model field of the rendering context. + * Strips off field suffixes such as year, month, day, hour, min, meridian + * when the current entity is longer than 2 elements. + * + * @return string + */ + public function field() { + $entity = $this->entity(); + $count = count($entity); + $last = $entity[$count - 1]; + if ($count > 2 && in_array($last, $this->_fieldSuffixes)) { + $last = isset($entity[$count - 2]) ? $entity[$count - 2] : null; + } + return $last; + } + +/** + * Generates a DOM ID for the selected element, if one is not set. + * Uses the current View::entity() settings to generate a CamelCased id attribute. + * + * @param array|string $options Either an array of html attributes to add $id into, or a string + * with a view entity path to get a domId for. + * @param string $id The name of the 'id' attribute. + * @return mixed If $options was an array, an array will be returned with $id set. If a string + * was supplied, a string will be returned. + * @todo Refactor this method to not have as many input/output options. + */ + public function domId($options = null, $id = 'id') { + if (is_array($options) && array_key_exists($id, $options) && $options[$id] === null) { + unset($options[$id]); + return $options; + } elseif (!is_array($options) && $options !== null) { + $this->setEntity($options); + return $this->domId(); + } + + $entity = $this->entity(); + $model = array_shift($entity); + $dom = $model . join('', array_map(array('Inflector', 'camelize'), $entity)); + + if (is_array($options) && !array_key_exists($id, $options)) { + $options[$id] = $dom; + } elseif ($options === null) { + return $dom; + } + return $options; + } + +/** + * Gets the input field name for the current tag. Creates input name attributes + * using CakePHP's data[Model][field] formatting. + * + * @param array|string $options If an array, should be an array of attributes that $key needs to be added to. + * If a string or null, will be used as the View entity. + * @param string $field + * @param string $key The name of the attribute to be set, defaults to 'name' + * @return mixed If an array was given for $options, an array with $key set will be returned. + * If a string was supplied a string will be returned. + * @todo Refactor this method to not have as many input/output options. + */ + protected function _name($options = array(), $field = null, $key = 'name') { + if ($options === null) { + $options = array(); + } elseif (is_string($options)) { + $field = $options; + $options = 0; + } + + if (!empty($field)) { + $this->setEntity($field); + } + + if (is_array($options) && array_key_exists($key, $options)) { + return $options; + } + + switch ($field) { + case '_method': + $name = $field; + break; + default: + $name = 'data[' . implode('][', $this->entity()) . ']'; + break; + } + + if (is_array($options)) { + $options[$key] = $name; + return $options; + } else { + return $name; + } + } + +/** + * Gets the data for the current tag + * + * @param array|string $options If an array, should be an array of attributes that $key needs to be added to. + * If a string or null, will be used as the View entity. + * @param string $field + * @param string $key The name of the attribute to be set, defaults to 'value' + * @return mixed If an array was given for $options, an array with $key set will be returned. + * If a string was supplied a string will be returned. + * @todo Refactor this method to not have as many input/output options. + */ + public function value($options = array(), $field = null, $key = 'value') { + if ($options === null) { + $options = array(); + } elseif (is_string($options)) { + $field = $options; + $options = 0; + } + + if (is_array($options) && isset($options[$key])) { + return $options; + } + + if (!empty($field)) { + $this->setEntity($field); + } + $result = null; + $data = $this->request->data; + + $entity = $this->entity(); + if (!empty($data) && !empty($entity)) { + $result = Hash::get($data, implode('.', $entity)); + } + + $habtmKey = $this->field(); + if (empty($result) && isset($data[$habtmKey][$habtmKey]) && is_array($data[$habtmKey])) { + $result = $data[$habtmKey][$habtmKey]; + } elseif (empty($result) && isset($data[$habtmKey]) && is_array($data[$habtmKey])) { + if (ClassRegistry::isKeySet($habtmKey)) { + $model = ClassRegistry::getObject($habtmKey); + $result = $this->_selectedArray($data[$habtmKey], $model->primaryKey); + } + } + + if (is_array($options)) { + if ($result === null && isset($options['default'])) { + $result = $options['default']; + } + unset($options['default']); + } + + if (is_array($options)) { + $options[$key] = $result; + return $options; + } else { + return $result; + } + } + +/** + * Sets the defaults for an input tag. Will set the + * name, value, and id attributes for an array of html attributes. Will also + * add a 'form-error' class if the field contains validation errors. + * + * @param string $field The field name to initialize. + * @param array $options Array of options to use while initializing an input field. + * @return array Array options for the form input. + */ + protected function _initInputField($field, $options = array()) { + if ($field !== null) { + $this->setEntity($field); + } + $options = (array)$options; + $options = $this->_name($options); + $options = $this->value($options); + $options = $this->domId($options); + return $options; + } + +/** + * Adds the given class to the element options + * + * @param array $options Array options/attributes to add a class to + * @param string $class The classname being added. + * @param string $key the key to use for class. + * @return array Array of options with $key set. + */ + public function addClass($options = array(), $class = null, $key = 'class') { + if (isset($options[$key]) && trim($options[$key]) != '') { + $options[$key] .= ' ' . $class; + } else { + $options[$key] = $class; + } + return $options; + } + +/** + * Returns a string generated by a helper method + * + * This method can be overridden in subclasses to do generalized output post-processing + * + * @param string $str String to be output. + * @return string + * @deprecated This method will be removed in future versions. + */ + public function output($str) { + return $str; + } + +/** + * Before render callback. beforeRender is called before the view file is rendered. + * + * Overridden in subclasses. + * + * @param string $viewFile The view file that is going to be rendered + * @return void + */ + public function beforeRender($viewFile) { + } + +/** + * After render callback. afterRender is called after the view file is rendered + * but before the layout has been rendered. + * + * Overridden in subclasses. + * + * @param string $viewFile The view file that was rendered. + * @return void + */ + public function afterRender($viewFile) { + } + +/** + * Before layout callback. beforeLayout is called before the layout is rendered. + * + * Overridden in subclasses. + * + * @param string $layoutFile The layout about to be rendered. + * @return void + */ + public function beforeLayout($layoutFile) { + } + +/** + * After layout callback. afterLayout is called after the layout has rendered. + * + * Overridden in subclasses. + * + * @param string $layoutFile The layout file that was rendered. + * @return void + */ + public function afterLayout($layoutFile) { + } + +/** + * Before render file callback. + * Called before any view fragment is rendered. + * + * Overridden in subclasses. + * + * @param string $viewFile The file about to be rendered. + * @return void + */ + public function beforeRenderFile($viewfile) { + } + +/** + * After render file callback. + * Called after any view fragment is rendered. + * + * Overridden in subclasses. + * + * @param string $viewFile The file just be rendered. + * @param string $content The content that was rendered. + * @return void + */ + public function afterRenderFile($viewfile, $content) { + } + +/** + * Transforms a recordset from a hasAndBelongsToMany association to a list of selected + * options for a multiple select element + * + * @param string|array $data + * @param string $key + * @return array + */ + protected function _selectedArray($data, $key = 'id') { + if (!is_array($data)) { + $model = $data; + if (!empty($this->request->data[$model][$model])) { + return $this->request->data[$model][$model]; + } + if (!empty($this->request->data[$model])) { + $data = $this->request->data[$model]; + } + } + $array = array(); + if (!empty($data)) { + foreach ($data as $row) { + if (isset($row[$key])) { + $array[$row[$key]] = $row[$key]; + } + } + } + return empty($array) ? null : $array; + } + +/** + * Resets the vars used by Helper::clean() to null + * + * @return void + */ + protected function _reset() { + $this->_tainted = null; + $this->_cleaned = null; + } + +/** + * Removes harmful content from output + * + * @return void + */ + protected function _clean() { + if (get_magic_quotes_gpc()) { + $this->_cleaned = stripslashes($this->_tainted); + } else { + $this->_cleaned = $this->_tainted; + } + + $this->_cleaned = str_replace(array("&", "<", ">"), array("&amp;", "&lt;", "&gt;"), $this->_cleaned); + $this->_cleaned = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $this->_cleaned); + $this->_cleaned = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $this->_cleaned); + $this->_cleaned = html_entity_decode($this->_cleaned, ENT_COMPAT, "UTF-8"); + $this->_cleaned = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $this->_cleaned); + $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); + $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); + $this->_cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=*([\'\"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#iUu', '$1=$2nomozbinding...', $this->_cleaned); + $this->_cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=([\'\"]*)[\x00-\x20]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $this->_cleaned); + $this->_cleaned = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*expression[\x00-\x20]*\([^>]*>#iU', "$1>", $this->_cleaned); + $this->_cleaned = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*behaviour[\x00-\x20]*\([^>]*>#iU', "$1>", $this->_cleaned); + $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); + $this->_cleaned = preg_replace('#</*\w+:\w[^>]*>#i', "", $this->_cleaned); + do { + $oldstring = $this->_cleaned; + $this->_cleaned = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $this->_cleaned); + } while ($oldstring != $this->_cleaned); + $this->_cleaned = str_replace(array("&", "<", ">"), array("&amp;", "&lt;", "&gt;"), $this->_cleaned); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/CacheHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/CacheHelper.php new file mode 100644 index 0000000..a480886 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/CacheHelper.php @@ -0,0 +1,321 @@ +<?php +/** + * CacheHelper helps create full page view caching. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.0.0.2277 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); + +/** + * CacheHelper helps create full page view caching. + * + * When using CacheHelper you don't call any of its methods, they are all automatically + * called by View, and use the $cacheAction settings set in the controller. + * + * @package Cake.View.Helper + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/cache.html + */ +class CacheHelper extends AppHelper { + +/** + * Array of strings replaced in cached views. + * The strings are found between `<!--nocache--><!--/nocache-->` in views + * + * @var array + */ + protected $_replace = array(); + +/** + * Array of string that are replace with there var replace above. + * The strings are any content inside `<!--nocache--><!--/nocache-->` and includes the tags in views + * + * @var array + */ + protected $_match = array(); + +/** + * Counter used for counting nocache section tags. + * + * @var integer + */ + protected $_counter = 0; + +/** + * Is CacheHelper enabled? should files + output be parsed. + * + * @return boolean + */ + protected function _enabled() { + return (($this->_View->cacheAction != false)) && (Configure::read('Cache.check') === true); + } + +/** + * Parses the view file and stores content for cache file building. + * + * @param string $viewFile + * @return void + */ + public function afterRenderFile($viewFile, $output) { + if ($this->_enabled()) { + return $this->_parseContent($viewFile, $output); + } + } + +/** + * Parses the layout file and stores content for cache file building. + * + * @param string $layoutFile + * @return void + */ + public function afterLayout($layoutFile) { + if ($this->_enabled()) { + $this->_View->output = $this->cache($layoutFile, $this->_View->output); + } + $this->_View->output = preg_replace('/<!--\/?nocache-->/', '', $this->_View->output); + } + +/** + * Parse a file + output. Matches nocache tags between the current output and the current file + * stores a reference of the file, so the generated can be swapped back with the file contents when + * writing the cache file. + * + * @param string $file The filename to process. + * @param string $out The output for the file. + * @return string Updated content. + */ + protected function _parseContent($file, $out) { + $out = preg_replace_callback('/<!--nocache-->/', array($this, '_replaceSection'), $out); + $this->_parseFile($file, $out); + return $out; + } + +/** + * Main method used to cache a view + * + * @param string $file File to cache + * @param string $out output to cache + * @return string view ouput + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/cache.html + */ + public function cache($file, $out) { + $cacheTime = 0; + $useCallbacks = false; + $cacheAction = $this->_View->cacheAction; + + if (is_array($cacheAction)) { + $keys = array_keys($cacheAction); + $index = null; + + foreach ($keys as $action) { + if ($action == $this->request->params['action']) { + $index = $action; + break; + } + } + + if (!isset($index) && $this->request->params['action'] == 'index') { + $index = 'index'; + } + + $options = $cacheAction; + if (isset($cacheAction[$index])) { + if (is_array($cacheAction[$index])) { + $options = array_merge(array('duration' => 0, 'callbacks' => false), $cacheAction[$index]); + } else { + $cacheTime = $cacheAction[$index]; + } + } + if (isset($options['duration'])) { + $cacheTime = $options['duration']; + } + if (isset($options['callbacks'])) { + $useCallbacks = $options['callbacks']; + } + } else { + $cacheTime = $cacheAction; + } + + if ($cacheTime != '' && $cacheTime > 0) { + $cached = $this->_parseOutput($out); + $this->_writeFile($cached, $cacheTime, $useCallbacks); + $out = $this->_stripTags($out); + } + return $out; + } + +/** + * Parse file searching for no cache tags + * + * @param string $file The filename that needs to be parsed. + * @param string $cache The cached content + * @return void + */ + protected function _parseFile($file, $cache) { + if (is_file($file)) { + $file = file_get_contents($file); + } elseif ($file = fileExistsInPath($file)) { + $file = file_get_contents($file); + } + preg_match_all('/(<!--nocache:\d{3}-->(?<=<!--nocache:\d{3}-->)[\\s\\S]*?(?=<!--\/nocache-->)<!--\/nocache-->)/i', $cache, $outputResult, PREG_PATTERN_ORDER); + preg_match_all('/(?<=<!--nocache-->)([\\s\\S]*?)(?=<!--\/nocache-->)/i', $file, $fileResult, PREG_PATTERN_ORDER); + $fileResult = $fileResult[0]; + $outputResult = $outputResult[0]; + + if (!empty($this->_replace)) { + foreach ($outputResult as $i => $element) { + $index = array_search($element, $this->_match); + if ($index !== false) { + unset($outputResult[$i]); + } + } + $outputResult = array_values($outputResult); + } + + if (!empty($fileResult)) { + $i = 0; + foreach ($fileResult as $cacheBlock) { + if (isset($outputResult[$i])) { + $this->_replace[] = $cacheBlock; + $this->_match[] = $outputResult[$i]; + } + $i++; + } + } + } + +/** + * Munges the output from a view with cache tags, and numbers the sections. + * This helps solve issues with empty/duplicate content. + * + * @return string The content with cake:nocache tags replaced. + */ + protected function _replaceSection() { + $this->_counter += 1; + return sprintf('<!--nocache:%03d-->', $this->_counter); + } + +/** + * Strip cake:nocache tags from a string. Since View::render() + * only removes un-numbered nocache tags, remove all the numbered ones. + * This is the complement to _replaceSection. + * + * @param string $content String to remove tags from. + * @return string String with tags removed. + */ + protected function _stripTags($content) { + return preg_replace('#<!--/?nocache(\:\d{3})?-->#', '', $content); + } + +/** + * Parse the output and replace cache tags + * + * @param string $cache Output to replace content in. + * @return string with all replacements made to <!--nocache--><!--nocache--> + */ + protected function _parseOutput($cache) { + $count = 0; + if (!empty($this->_match)) { + foreach ($this->_match as $found) { + $original = $cache; + $length = strlen($found); + $position = 0; + + for ($i = 1; $i <= 1; $i++) { + $position = strpos($cache, $found, $position); + + if ($position !== false) { + $cache = substr($original, 0, $position); + $cache .= $this->_replace[$count]; + $cache .= substr($original, $position + $length); + } else { + break; + } + } + $count++; + } + return $cache; + } + return $cache; + } + +/** + * Write a cached version of the file + * + * @param string $content view content to write to a cache file. + * @param string $timestamp Duration to set for cache file. + * @param boolean $useCallbacks + * @return boolean success of caching view. + */ + protected function _writeFile($content, $timestamp, $useCallbacks = false) { + $now = time(); + + if (is_numeric($timestamp)) { + $cacheTime = $now + $timestamp; + } else { + $cacheTime = strtotime($timestamp, $now); + } + $path = $this->request->here(); + if ($path == '/') { + $path = 'home'; + } + $cache = strtolower(Inflector::slug($path)); + + if (empty($cache)) { + return; + } + $cache = $cache . '.php'; + $file = '<!--cachetime:' . $cacheTime . '--><?php'; + + if (empty($this->_View->plugin)) { + $file .= " + App::uses('{$this->_View->name}Controller', 'Controller'); + "; + } else { + $file .= " + App::uses('{$this->_View->plugin}AppController', '{$this->_View->plugin}.Controller'); + App::uses('{$this->_View->name}Controller', '{$this->_View->plugin}.Controller'); + "; + } + + $file .= ' + $request = unserialize(base64_decode(\'' . base64_encode(serialize($this->request)) . '\')); + $response = new CakeResponse(array("charset" => Configure::read("App.encoding"))); + $controller = new ' . $this->_View->name . 'Controller($request, $response); + $controller->plugin = $this->plugin = \'' . $this->_View->plugin . '\'; + $controller->helpers = $this->helpers = unserialize(base64_decode(\'' . base64_encode(serialize($this->_View->helpers)) . '\')); + $controller->layout = $this->layout = \'' . $this->_View->layout . '\'; + $controller->theme = $this->theme = \'' . $this->_View->theme . '\'; + $controller->viewVars = unserialize(base64_decode(\'' . base64_encode(serialize($this->_View->viewVars)) . '\')); + Router::setRequestInfo($controller->request); + $this->request = $request;'; + + if ($useCallbacks == true) { + $file .= ' + $controller->constructClasses(); + $controller->startupProcess();'; + } + + $file .= ' + $this->viewVars = $controller->viewVars; + $this->loadHelpers(); + extract($this->viewVars, EXTR_SKIP); + ?>'; + $content = preg_replace("/(<\\?xml)/", "<?php echo '$1'; ?>", $content); + $file .= $content; + return cache('views' . DS . $cache, $file, $timestamp); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/FormHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/FormHelper.php new file mode 100644 index 0000000..e63614a --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/FormHelper.php @@ -0,0 +1,2604 @@ +<?php +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::uses('ClassRegistry', 'Utility'); +App::uses('AppHelper', 'View/Helper'); +App::uses('Hash', 'Utility'); + +/** + * Form helper library. + * + * Automatic generation of HTML FORMs from given data. + * + * @package Cake.View.Helper + * @property HtmlHelper $Html + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html + */ +class FormHelper extends AppHelper { + +/** + * Other helpers used by FormHelper + * + * @var array + */ + public $helpers = array('Html'); + +/** + * Options used by DateTime fields + * + * @var array + */ + protected $_options = array( + 'day' => array(), 'minute' => array(), 'hour' => array(), + 'month' => array(), 'year' => array(), 'meridian' => array() + ); + +/** + * List of fields created, used with secure forms. + * + * @var array + */ + public $fields = array(); + +/** + * Constant used internally to skip the securing process, + * and neither add the field to the hash or to the unlocked fields. + * + * @var string + */ + const SECURE_SKIP = 'skip'; + +/** + * Defines the type of form being created. Set by FormHelper::create(). + * + * @var string + */ + public $requestType = null; + +/** + * The default model being used for the current form. + * + * @var string + */ + public $defaultModel = null; + +/** + * Persistent default options used by input(). Set by FormHelper::create(). + * + * @var array + */ + protected $_inputDefaults = array(); + +/** + * An array of field names that have been excluded from + * the Token hash used by SecurityComponent's validatePost method + * + * @see FormHelper::_secure() + * @see SecurityComponent::validatePost() + * @var array + */ + protected $_unlockedFields = array(); + +/** + * Holds the model references already loaded by this helper + * product of trying to inspect them out of field names + * + * @var array + */ + protected $_models = array(); + +/** + * Holds all the validation errors for models loaded and inspected + * it can also be set manually to be able to display custom error messages + * in the any of the input fields generated by this helper + * + * @var array + */ + public $validationErrors = array(); + +/** + * Copies the validationErrors variable from the View object into this instance + * + * @param View $View The View this helper is being attached to. + * @param array $settings Configuration settings for the helper. + */ + public function __construct(View $View, $settings = array()) { + parent::__construct($View, $settings); + $this->validationErrors =& $View->validationErrors; + } + +/** + * Guess the location for a model based on its name and tries to create a new instance + * or get an already created instance of the model + * + * @param string $model + * @return Model model instance + */ + protected function _getModel($model) { + $object = null; + if (!$model || $model === 'Model') { + return $object; + } + + if (array_key_exists($model, $this->_models)) { + return $this->_models[$model]; + } + + if (ClassRegistry::isKeySet($model)) { + $object = ClassRegistry::getObject($model); + } elseif (isset($this->request->params['models'][$model])) { + $plugin = $this->request->params['models'][$model]['plugin']; + $plugin .= ($plugin) ? '.' : null; + $object = ClassRegistry::init(array( + 'class' => $plugin . $this->request->params['models'][$model]['className'], + 'alias' => $model + )); + } elseif (ClassRegistry::isKeySet($this->defaultModel)) { + $defaultObject = ClassRegistry::getObject($this->defaultModel); + if (in_array($model, array_keys($defaultObject->getAssociated()), true) && isset($defaultObject->{$model})) { + $object = $defaultObject->{$model}; + } + } else { + $object = ClassRegistry::init($model, true); + } + + $this->_models[$model] = $object; + if (!$object) { + return null; + } + + $this->fieldset[$model] = array('fields' => null, 'key' => $object->primaryKey, 'validates' => null); + return $object; + } + +/** + * Inspects the model properties to extract information from them. + * Currently it can extract information from the the fields, the primary key and required fields + * + * The $key parameter accepts the following list of values: + * + * - key: Returns the name of the primary key for the model + * - fields: Returns the model schema + * - validates: returns the list of fields that are required + * - errors: returns the list of validation errors + * + * If the $field parameter is passed if will return the information for that sole field. + * + * `$this->_introspectModel('Post', 'fields', 'title');` will return the schema information for title column + * + * @param string $model name of the model to extract information from + * @param string $key name of the special information key to obtain (key, fields, validates, errors) + * @param string $field name of the model field to get information from + * @return mixed information extracted for the special key and field in a model + */ + protected function _introspectModel($model, $key, $field = null) { + $object = $this->_getModel($model); + if (!$object) { + return; + } + + if ($key === 'key') { + return $this->fieldset[$model]['key'] = $object->primaryKey; + } + + if ($key === 'fields') { + if (!isset($this->fieldset[$model]['fields'])) { + $fields = $this->fieldset[$model]['fields'] = $object->schema(); + foreach ($object->hasAndBelongsToMany as $alias => $assocData) { + $this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple'); + } + } + if (empty($field)) { + return $this->fieldset[$model]['fields']; + } elseif (isset($this->fieldset[$model]['fields'][$field])) { + return $this->fieldset[$model]['fields'][$field]; + } else { + return isset($object->hasAndBelongsToMany[$field]) ? array('type' => 'multiple') : null; + } + } + + if ($key === 'errors' && !isset($this->validationErrors[$model])) { + $this->validationErrors[$model] =& $object->validationErrors; + return $this->validationErrors[$model]; + } elseif ($key === 'errors' && isset($this->validationErrors[$model])) { + return $this->validationErrors[$model]; + } + + if ($key === 'validates' && !isset($this->fieldset[$model]['validates'])) { + $validates = array(); + if (!empty($object->validate)) { + foreach ($object->validator() as $validateField => $validateProperties) { + if ($this->_isRequiredField($validateProperties)) { + $validates[$validateField] = true; + } + } + } + $this->fieldset[$model]['validates'] = $validates; + } + + if ($key === 'validates') { + if (empty($field)) { + return $this->fieldset[$model]['validates']; + } else { + return isset($this->fieldset[$model]['validates'][$field]) ? + $this->fieldset[$model]['validates'] : null; + } + } + } + +/** + * Returns if a field is required to be filled based on validation properties from the validating object. + * + * @param CakeValidationSet $validationRules + * @return boolean true if field is required to be filled, false otherwise + */ + protected function _isRequiredField($validationRules) { + foreach ($validationRules as $rule) { + $rule->isUpdate($this->requestType === 'put'); + if (!$rule->isEmptyAllowed()) { + return true; + } + } + return false; + } + +/** + * Returns false if given form field described by the current entity has no errors. + * Otherwise it returns the validation message + * + * @return mixed Either false when there or no errors, or an array of error + * strings. An error string could be ''. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid + */ + public function tagIsInvalid() { + $entity = $this->entity(); + $model = array_shift($entity); + $errors = array(); + if (!empty($entity) && isset($this->validationErrors[$model])) { + $errors = $this->validationErrors[$model]; + } + if (!empty($entity) && empty($errors)) { + $errors = $this->_introspectModel($model, 'errors'); + } + if (empty($errors)) { + return false; + } + $errors = Hash::get($errors, join('.', $entity)); + return $errors === null ? false : $errors; + } + +/** + * Returns an HTML FORM element. + * + * ### Options: + * + * - `type` Form method defaults to POST + * - `action` The controller action the form submits to, (optional). + * - `url` The url the form submits to. Can be a string or a url array. If you use 'url' + * you should leave 'action' undefined. + * - `default` Allows for the creation of Ajax forms. Set this to false to prevent the default event handler. + * Will create an onsubmit attribute if it doesn't not exist. If it does, default action suppression + * will be appended. + * - `onsubmit` Used in conjunction with 'default' to create ajax forms. + * - `inputDefaults` set the default $options for FormHelper::input(). Any options that would + * be set when using FormHelper::input() can be set here. Options set with `inputDefaults` + * can be overridden when calling input() + * - `encoding` Set the accept-charset encoding for the form. Defaults to `Configure::read('App.encoding')` + * + * @param string $model The model object which the form is being defined for. Should + * include the plugin name for plugin forms. e.g. `ContactManager.Contact`. + * @param array $options An array of html attributes and options. + * @return string An formatted opening FORM tag. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-create + */ + public function create($model = null, $options = array()) { + $created = $id = false; + $append = ''; + + if (is_array($model) && empty($options)) { + $options = $model; + $model = null; + } + + if (empty($model) && $model !== false && !empty($this->request->params['models'])) { + $model = key($this->request->params['models']); + } elseif (empty($model) && empty($this->request->params['models'])) { + $model = false; + } + $this->defaultModel = $model; + + $key = null; + if ($model !== false) { + $object = $this->_getModel($model); + $key = $this->_introspectModel($model, 'key'); + $this->setEntity($model, true); + } + + if ($model !== false && $key) { + $recordExists = ( + isset($this->request->data[$model]) && + !empty($this->request->data[$model][$key]) && + !is_array($this->request->data[$model][$key]) + ); + + if ($recordExists) { + $created = true; + $id = $this->request->data[$model][$key]; + } + } + + $options = array_merge(array( + 'type' => ($created && empty($options['action'])) ? 'put' : 'post', + 'action' => null, + 'url' => null, + 'default' => true, + 'encoding' => strtolower(Configure::read('App.encoding')), + 'inputDefaults' => array()), + $options); + $this->inputDefaults($options['inputDefaults']); + unset($options['inputDefaults']); + + if (!isset($options['id'])) { + $domId = isset($options['action']) ? $options['action'] : $this->request['action']; + $options['id'] = $this->domId($domId . 'Form'); + } + + if ($options['action'] === null && $options['url'] === null) { + $options['action'] = $this->request->here(false); + } elseif (empty($options['url']) || is_array($options['url'])) { + if (empty($options['url']['controller'])) { + if (!empty($model)) { + $options['url']['controller'] = Inflector::underscore(Inflector::pluralize($model)); + } elseif (!empty($this->request->params['controller'])) { + $options['url']['controller'] = Inflector::underscore($this->request->params['controller']); + } + } + if (empty($options['action'])) { + $options['action'] = $this->request->params['action']; + } + + $plugin = null; + if ($this->plugin) { + $plugin = Inflector::underscore($this->plugin); + } + $actionDefaults = array( + 'plugin' => $plugin, + 'controller' => $this->_View->viewPath, + 'action' => $options['action'], + ); + $options['action'] = array_merge($actionDefaults, (array)$options['url']); + if (empty($options['action'][0]) && !empty($id)) { + $options['action'][0] = $id; + } + } elseif (is_string($options['url'])) { + $options['action'] = $options['url']; + } + unset($options['url']); + + switch (strtolower($options['type'])) { + case 'get': + $htmlAttributes['method'] = 'get'; + break; + case 'file': + $htmlAttributes['enctype'] = 'multipart/form-data'; + $options['type'] = ($created) ? 'put' : 'post'; + case 'post': + case 'put': + case 'delete': + $append .= $this->hidden('_method', array( + 'name' => '_method', 'value' => strtoupper($options['type']), 'id' => null, + 'secure' => self::SECURE_SKIP + )); + default: + $htmlAttributes['method'] = 'post'; + break; + } + $this->requestType = strtolower($options['type']); + + $action = $this->url($options['action']); + unset($options['type'], $options['action']); + + if ($options['default'] == false) { + if (!isset($options['onsubmit'])) { + $options['onsubmit'] = ''; + } + $htmlAttributes['onsubmit'] = $options['onsubmit'] . 'event.returnValue = false; return false;'; + } + unset($options['default']); + + if (!empty($options['encoding'])) { + $htmlAttributes['accept-charset'] = $options['encoding']; + unset($options['encoding']); + } + + $htmlAttributes = array_merge($options, $htmlAttributes); + + $this->fields = array(); + $append .= $this->_csrfField(); + + if (!empty($append)) { + $append = $this->Html->useTag('block', ' style="display:none;"', $append); + } + + if ($model !== false) { + $this->setEntity($model, true); + $this->_introspectModel($model, 'fields'); + } + return $this->Html->useTag('form', $action, $htmlAttributes) . $append; + } + +/** + * Return a CSRF input if the _Token is present. + * Used to secure forms in conjunction with SecurityComponent + * + * @return string + */ + protected function _csrfField() { + if (empty($this->request->params['_Token'])) { + return ''; + } + if (!empty($this->request['_Token']['unlockedFields'])) { + foreach ((array)$this->request['_Token']['unlockedFields'] as $unlocked) { + $this->_unlockedFields[] = $unlocked; + } + } + return $this->hidden('_Token.key', array( + 'value' => $this->request->params['_Token']['key'], 'id' => 'Token' . mt_rand(), + 'secure' => self::SECURE_SKIP + )); + } + +/** + * Closes an HTML form, cleans up values set by FormHelper::create(), and writes hidden + * input fields where appropriate. + * + * If $options is set a form submit button will be created. Options can be either a string or an array. + * + * {{{ + * array usage: + * + * array('label' => 'save'); value="save" + * array('label' => 'save', 'name' => 'Whatever'); value="save" name="Whatever" + * array('name' => 'Whatever'); value="Submit" name="Whatever" + * array('label' => 'save', 'name' => 'Whatever', 'div' => 'good') <div class="good"> value="save" name="Whatever" + * array('label' => 'save', 'name' => 'Whatever', 'div' => array('class' => 'good')); <div class="good"> value="save" name="Whatever" + * }}} + * + * @param string|array $options as a string will use $options as the value of button, + * @return string a closing FORM tag optional submit button. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#closing-the-form + */ + public function end($options = null) { + $out = null; + $submit = null; + + if ($options !== null) { + $submitOptions = array(); + if (is_string($options)) { + $submit = $options; + } else { + if (isset($options['label'])) { + $submit = $options['label']; + unset($options['label']); + } + $submitOptions = $options; + } + $out .= $this->submit($submit, $submitOptions); + } + if (isset($this->request['_Token']) && !empty($this->request['_Token'])) { + $out .= $this->secure($this->fields); + $this->fields = array(); + } + $this->setEntity(null); + $out .= $this->Html->useTag('formend'); + + $this->_View->modelScope = false; + return $out; + } + +/** + * Generates a hidden field with a security hash based on the fields used in the form. + * + * @param array $fields The list of fields to use when generating the hash + * @return string A hidden input field with a security hash + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::secure + */ + public function secure($fields = array()) { + if (!isset($this->request['_Token']) || empty($this->request['_Token'])) { + return; + } + $locked = array(); + $unlockedFields = $this->_unlockedFields; + + foreach ($fields as $key => $value) { + if (!is_int($key)) { + $locked[$key] = $value; + unset($fields[$key]); + } + } + + sort($unlockedFields, SORT_STRING); + sort($fields, SORT_STRING); + ksort($locked, SORT_STRING); + $fields += $locked; + + $locked = implode(array_keys($locked), '|'); + $unlocked = implode($unlockedFields, '|'); + $fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt')); + + $out = $this->hidden('_Token.fields', array( + 'value' => urlencode($fields . ':' . $locked), + 'id' => 'TokenFields' . mt_rand() + )); + $out .= $this->hidden('_Token.unlocked', array( + 'value' => urlencode($unlocked), + 'id' => 'TokenUnlocked' . mt_rand() + )); + return $this->Html->useTag('block', ' style="display:none;"', $out); + } + +/** + * Add to or get the list of fields that are currently unlocked. + * Unlocked fields are not included in the field hash used by SecurityComponent + * unlocking a field once its been added to the list of secured fields will remove + * it from the list of fields. + * + * @param string $name The dot separated name for the field. + * @return mixed Either null, or the list of fields. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::unlockField + */ + public function unlockField($name = null) { + if ($name === null) { + return $this->_unlockedFields; + } + if (!in_array($name, $this->_unlockedFields)) { + $this->_unlockedFields[] = $name; + } + $index = array_search($name, $this->fields); + if ($index !== false) { + unset($this->fields[$index]); + } + unset($this->fields[$name]); + } + +/** + * Determine which fields of a form should be used for hash. + * Populates $this->fields + * + * @param boolean $lock Whether this field should be part of the validation + * or excluded as part of the unlockedFields. + * @param string|array $field Reference to field to be secured. Should be dot separated to indicate nesting. + * @param mixed $value Field value, if value should not be tampered with. + * @return void + */ + protected function _secure($lock, $field = null, $value = null) { + if (!$field) { + $field = $this->entity(); + } elseif (is_string($field)) { + $field = Hash::filter(explode('.', $field)); + } + + foreach ($this->_unlockedFields as $unlockField) { + $unlockParts = explode('.', $unlockField); + if (array_values(array_intersect($field, $unlockParts)) === $unlockParts) { + return; + } + } + + $field = implode('.', $field); + $field = preg_replace('/(\.\d+)+$/', '', $field); + + if ($lock) { + if (!in_array($field, $this->fields)) { + if ($value !== null) { + return $this->fields[$field] = $value; + } + $this->fields[] = $field; + } + } else { + $this->unlockField($field); + } + } + +/** + * Returns true if there is an error for the given field, otherwise false + * + * @param string $field This should be "Modelname.fieldname" + * @return boolean If there are errors this method returns true, else false. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::isFieldError + */ + public function isFieldError($field) { + $this->setEntity($field); + return (bool)$this->tagIsInvalid(); + } + +/** + * Returns a formatted error message for given FORM field, NULL if no errors. + * + * ### Options: + * + * - `escape` bool Whether or not to html escape the contents of the error. + * - `wrap` mixed Whether or not the error message should be wrapped in a div. If a + * string, will be used as the HTML tag to use. + * - `class` string The classname for the error message + * + * @param string $field A field name, like "Modelname.fieldname" + * @param string|array $text Error message as string or array of messages. + * If array contains `attributes` key it will be used as options for error container + * @param array $options Rendering options for <div /> wrapper tag + * @return string If there are errors this method returns an error message, otherwise null. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::error + */ + public function error($field, $text = null, $options = array()) { + $defaults = array('wrap' => true, 'class' => 'error-message', 'escape' => true); + $options = array_merge($defaults, $options); + $this->setEntity($field); + + $error = $this->tagIsInvalid(); + if ($error === false) { + return null; + } + if (is_array($text)) { + if (isset($text['attributes']) && is_array($text['attributes'])) { + $options = array_merge($options, $text['attributes']); + unset($text['attributes']); + } + $tmp = array(); + foreach ($error as &$e) { + if (isset($text[$e])) { + $tmp[] = $text[$e]; + } else { + $tmp[] = $e; + } + } + $text = $tmp; + } + + if ($text !== null) { + $error = $text; + } + if (is_array($error)) { + foreach ($error as &$e) { + if (is_numeric($e)) { + $e = __d('cake', 'Error in field %s', Inflector::humanize($this->field())); + } + } + } + if ($options['escape']) { + $error = h($error); + unset($options['escape']); + } + if (is_array($error)) { + if (count($error) > 1) { + $listParams = array(); + if (isset($options['listOptions'])) { + if (is_string($options['listOptions'])) { + $listParams[] = $options['listOptions']; + } else { + if (isset($options['listOptions']['itemOptions'])) { + $listParams[] = $options['listOptions']['itemOptions']; + unset($options['listOptions']['itemOptions']); + } else { + $listParams[] = array(); + } + if (isset($options['listOptions']['tag'])) { + $listParams[] = $options['listOptions']['tag']; + unset($options['listOptions']['tag']); + } + array_unshift($listParams, $options['listOptions']); + } + unset($options['listOptions']); + } + array_unshift($listParams, $error); + $error = call_user_func_array(array($this->Html, 'nestedList'), $listParams); + } else { + $error = array_pop($error); + } + } + if ($options['wrap']) { + $tag = is_string($options['wrap']) ? $options['wrap'] : 'div'; + unset($options['wrap']); + return $this->Html->tag($tag, $error, $options); + } else { + return $error; + } + } + +/** + * Returns a formatted LABEL element for HTML FORMs. Will automatically generate + * a for attribute if one is not provided. + * + * ### Options + * + * - `for` - Set the for attribute, if its not defined the for attribute + * will be generated from the $fieldName parameter using + * FormHelper::domId(). + * + * Examples: + * + * The text and for attribute are generated off of the fieldname + * + * {{{ + * echo $this->Form->label('Post.published'); + * <label for="PostPublished">Published</label> + * }}} + * + * Custom text: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish'); + * <label for="PostPublished">Publish</label> + * }}} + * + * Custom class name: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish', 'required'); + * <label for="PostPublished" class="required">Publish</label> + * }}} + * + * Custom attributes: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish', array( + * 'for' => 'post-publish' + * )); + * <label for="post-publish">Publish</label> + * }}} + * + * @param string $fieldName This should be "Modelname.fieldname" + * @param string $text Text that will appear in the label field. If + * $text is left undefined the text will be inflected from the + * fieldName. + * @param array|string $options An array of HTML attributes, or a string, to be used as a class name. + * @return string The formatted LABEL element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::label + */ + public function label($fieldName = null, $text = null, $options = array()) { + if (empty($fieldName)) { + $fieldName = implode('.', $this->entity()); + } + + if ($text === null) { + if (strpos($fieldName, '.') !== false) { + $fieldElements = explode('.', $fieldName); + $text = array_pop($fieldElements); + } else { + $text = $fieldName; + } + if (substr($text, -3) == '_id') { + $text = substr($text, 0, -3); + } + $text = __(Inflector::humanize(Inflector::underscore($text))); + } + + if (is_string($options)) { + $options = array('class' => $options); + } + + if (isset($options['for'])) { + $labelFor = $options['for']; + unset($options['for']); + } else { + $labelFor = $this->domId($fieldName); + } + + return $this->Html->useTag('label', $labelFor, $options, $text); + } + +/** + * Generate a set of inputs for `$fields`. If $fields is null the current model + * will be used. + * + * In addition to controller fields output, `$fields` can be used to control legend + * and fieldset rendering with the `fieldset` and `legend` keys. + * `$form->inputs(array('legend' => 'My legend'));` Would generate an input set with + * a custom legend. You can customize individual inputs through `$fields` as well. + * + * {{{ + * $form->inputs(array( + * 'name' => array('label' => 'custom label') + * )); + * }}} + * + * In addition to fields control, inputs() allows you to use a few additional options. + * + * - `fieldset` Set to false to disable the fieldset. If a string is supplied it will be used as + * the classname for the fieldset element. + * - `legend` Set to false to disable the legend for the generated input set. Or supply a string + * to customize the legend text. + * + * @param array $fields An array of fields to generate inputs for, or null. + * @param array $blacklist a simple array of fields to not create inputs for. + * @return string Completed form inputs. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::inputs + */ + public function inputs($fields = null, $blacklist = null) { + $fieldset = $legend = true; + $model = $this->model(); + if (is_array($fields)) { + if (array_key_exists('legend', $fields)) { + $legend = $fields['legend']; + unset($fields['legend']); + } + + if (isset($fields['fieldset'])) { + $fieldset = $fields['fieldset']; + unset($fields['fieldset']); + } + } elseif ($fields !== null) { + $fieldset = $legend = $fields; + if (!is_bool($fieldset)) { + $fieldset = true; + } + $fields = array(); + } + + if (empty($fields)) { + $fields = array_keys($this->_introspectModel($model, 'fields')); + } + + if ($legend === true) { + $actionName = __d('cake', 'New %s'); + $isEdit = ( + strpos($this->request->params['action'], 'update') !== false || + strpos($this->request->params['action'], 'edit') !== false + ); + if ($isEdit) { + $actionName = __d('cake', 'Edit %s'); + } + $modelName = Inflector::humanize(Inflector::underscore($model)); + $legend = sprintf($actionName, __($modelName)); + } + + $out = null; + foreach ($fields as $name => $options) { + if (is_numeric($name) && !is_array($options)) { + $name = $options; + $options = array(); + } + $entity = explode('.', $name); + $blacklisted = ( + is_array($blacklist) && + (in_array($name, $blacklist) || in_array(end($entity), $blacklist)) + ); + if ($blacklisted) { + continue; + } + $out .= $this->input($name, $options); + } + + if (is_string($fieldset)) { + $fieldsetClass = sprintf(' class="%s"', $fieldset); + } else { + $fieldsetClass = ''; + } + + if ($fieldset && $legend) { + return $this->Html->useTag('fieldset', $fieldsetClass, $this->Html->useTag('legend', $legend) . $out); + } elseif ($fieldset) { + return $this->Html->useTag('fieldset', $fieldsetClass, $out); + } else { + return $out; + } + } + +/** + * Generates a form input element complete with label and wrapper div + * + * ### Options + * + * See each field type method for more information. Any options that are part of + * $attributes or $options for the different **type** methods can be included in `$options` for input().i + * Additionally, any unknown keys that are not in the list below, or part of the selected type's options + * will be treated as a regular html attribute for the generated input. + * + * - `type` - Force the type of widget you want. e.g. `type => 'select'` + * - `label` - Either a string label, or an array of options for the label. See FormHelper::label() + * - `div` - Either `false` to disable the div, or an array of options for the div. + * See HtmlHelper::div() for more options. + * - `options` - for widgets that take options e.g. radio, select + * - `error` - control the error message that is produced + * - `empty` - String or boolean to enable empty select box options. + * - `before` - Content to place before the label + input. + * - `after` - Content to place after the label + input. + * - `between` - Content to place between the label + input. + * - `format` - format template for element order. Any element that is not in the array, will not be in the output. + * - Default input format order: array('before', 'label', 'between', 'input', 'after', 'error') + * - Default checkbox format order: array('before', 'input', 'between', 'label', 'after', 'error') + * - Hidden input will not be formatted + * - Radio buttons cannot have the order of input and label elements controlled with these settings. + * + * @param string $fieldName This should be "Modelname.fieldname" + * @param array $options Each type of input takes different options. + * @return string Completed form widget. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#creating-form-elements + */ + public function input($fieldName, $options = array()) { + $this->setEntity($fieldName); + + $options = array_merge( + array('before' => null, 'between' => null, 'after' => null, 'format' => null), + $this->_inputDefaults, + $options + ); + + $modelKey = $this->model(); + $fieldKey = $this->field(); + + if (!isset($options['type'])) { + $magicType = true; + $options['type'] = 'text'; + if (isset($options['options'])) { + $options['type'] = 'select'; + } elseif (in_array($fieldKey, array('psword', 'passwd', 'password'))) { + $options['type'] = 'password'; + } elseif (isset($options['checked'])) { + $options['type'] = 'checkbox'; + } elseif ($fieldDef = $this->_introspectModel($modelKey, 'fields', $fieldKey)) { + $type = $fieldDef['type']; + $primaryKey = $this->fieldset[$modelKey]['key']; + } + + if (isset($type)) { + $map = array( + 'string' => 'text', 'datetime' => 'datetime', + 'boolean' => 'checkbox', 'timestamp' => 'datetime', + 'text' => 'textarea', 'time' => 'time', + 'date' => 'date', 'float' => 'number', + 'integer' => 'number' + ); + + if (isset($this->map[$type])) { + $options['type'] = $this->map[$type]; + } elseif (isset($map[$type])) { + $options['type'] = $map[$type]; + } + if ($fieldKey == $primaryKey) { + $options['type'] = 'hidden'; + } + if ( + $options['type'] === 'number' && + $type === 'float' && + !isset($options['step']) + ) { + $options['step'] = 'any'; + } + } + if (preg_match('/_id$/', $fieldKey) && $options['type'] !== 'hidden') { + $options['type'] = 'select'; + } + + if ($modelKey === $fieldKey) { + $options['type'] = 'select'; + if (!isset($options['multiple'])) { + $options['multiple'] = 'multiple'; + } + } + } + $types = array('checkbox', 'radio', 'select'); + + if ( + (!isset($options['options']) && in_array($options['type'], $types)) || + (isset($magicType) && $options['type'] == 'text') + ) { + $varName = Inflector::variable( + Inflector::pluralize(preg_replace('/_id$/', '', $fieldKey)) + ); + $varOptions = $this->_View->getVar($varName); + if (is_array($varOptions)) { + if ($options['type'] !== 'radio') { + $options['type'] = 'select'; + } + $options['options'] = $varOptions; + } + } + + $autoLength = (!array_key_exists('maxlength', $options) && isset($fieldDef['length'])); + if ($autoLength && $options['type'] == 'text') { + $options['maxlength'] = $fieldDef['length']; + } + if ($autoLength && $fieldDef['type'] == 'float') { + $options['maxlength'] = array_sum(explode(',', $fieldDef['length'])) + 1; + } + + $divOptions = array(); + $div = $this->_extractOption('div', $options, true); + unset($options['div']); + + if (!empty($div)) { + $divOptions['class'] = 'input'; + $divOptions = $this->addClass($divOptions, $options['type']); + if (is_string($div)) { + $divOptions['class'] = $div; + } elseif (is_array($div)) { + $divOptions = array_merge($divOptions, $div); + } + if ($this->_introspectModel($modelKey, 'validates', $fieldKey)) { + $divOptions = $this->addClass($divOptions, 'required'); + } + if (!isset($divOptions['tag'])) { + $divOptions['tag'] = 'div'; + } + } + + $label = null; + if (isset($options['label']) && $options['type'] !== 'radio') { + $label = $options['label']; + unset($options['label']); + } + + if ($options['type'] === 'radio') { + $label = false; + if (isset($options['options'])) { + $radioOptions = (array)$options['options']; + unset($options['options']); + } + } + + if ($label !== false) { + $label = $this->_inputLabel($fieldName, $label, $options); + } + + $error = $this->_extractOption('error', $options, null); + unset($options['error']); + + $selected = $this->_extractOption('selected', $options, null); + unset($options['selected']); + + if (isset($options['rows']) || isset($options['cols'])) { + $options['type'] = 'textarea'; + } + + if ($options['type'] === 'datetime' || $options['type'] === 'date' || $options['type'] === 'time' || $options['type'] === 'select') { + $options += array('empty' => false); + } + if ($options['type'] === 'datetime' || $options['type'] === 'date' || $options['type'] === 'time') { + $dateFormat = $this->_extractOption('dateFormat', $options, 'MDY'); + $timeFormat = $this->_extractOption('timeFormat', $options, 12); + unset($options['dateFormat'], $options['timeFormat']); + } + + $type = $options['type']; + $out = array_merge( + array('before' => null, 'label' => null, 'between' => null, 'input' => null, 'after' => null, 'error' => null), + array('before' => $options['before'], 'label' => $label, 'between' => $options['between'], 'after' => $options['after']) + ); + $format = null; + if (is_array($options['format']) && in_array('input', $options['format'])) { + $format = $options['format']; + } + unset($options['type'], $options['before'], $options['between'], $options['after'], $options['format']); + + switch ($type) { + case 'hidden': + $input = $this->hidden($fieldName, $options); + $format = array('input'); + unset($divOptions); + break; + case 'checkbox': + $input = $this->checkbox($fieldName, $options); + $format = $format ? $format : array('before', 'input', 'between', 'label', 'after', 'error'); + break; + case 'radio': + if (isset($out['between'])) { + $options['between'] = $out['between']; + $out['between'] = null; + } + $input = $this->radio($fieldName, $radioOptions, $options); + break; + case 'file': + $input = $this->file($fieldName, $options); + break; + case 'select': + $options += array('options' => array(), 'value' => $selected); + $list = $options['options']; + unset($options['options']); + $input = $this->select($fieldName, $list, $options); + break; + case 'time': + $options['value'] = $selected; + $input = $this->dateTime($fieldName, null, $timeFormat, $options); + break; + case 'date': + $options['value'] = $selected; + $input = $this->dateTime($fieldName, $dateFormat, null, $options); + break; + case 'datetime': + $options['value'] = $selected; + $input = $this->dateTime($fieldName, $dateFormat, $timeFormat, $options); + break; + case 'textarea': + $input = $this->textarea($fieldName, $options + array('cols' => '30', 'rows' => '6')); + break; + case 'url': + $input = $this->text($fieldName, array('type' => 'url') + $options); + break; + default: + $input = $this->{$type}($fieldName, $options); + } + + if ($type != 'hidden' && $error !== false) { + $errMsg = $this->error($fieldName, $error); + if ($errMsg) { + $divOptions = $this->addClass($divOptions, 'error'); + $out['error'] = $errMsg; + } + } + + $out['input'] = $input; + $format = $format ? $format : array('before', 'label', 'between', 'input', 'after', 'error'); + $output = ''; + foreach ($format as $element) { + $output .= $out[$element]; + unset($out[$element]); + } + + if (!empty($divOptions['tag'])) { + $tag = $divOptions['tag']; + unset($divOptions['tag']); + $output = $this->Html->tag($tag, $output, $divOptions); + } + return $output; + } + +/** + * Extracts a single option from an options array. + * + * @param string $name The name of the option to pull out. + * @param array $options The array of options you want to extract. + * @param mixed $default The default option value + * @return mixed the contents of the option or default + */ + protected function _extractOption($name, $options, $default = null) { + if (array_key_exists($name, $options)) { + return $options[$name]; + } + return $default; + } + +/** + * Generate a label for an input() call. + * + * $options can contain a hash of id overrides. These overrides will be + * used instead of the generated values if present. + * + * @param string $fieldName + * @param string $label + * @param array $options Options for the label element. + * @return string Generated label element + * @deprecated 'NONE' option is deprecated and will be removed in 3.0 + */ + protected function _inputLabel($fieldName, $label, $options) { + $labelAttributes = $this->domId(array(), 'for'); + $idKey = null; + if ($options['type'] === 'date' || $options['type'] === 'datetime') { + $firstInput = 'M'; + if ( + array_key_exists('dateFormat', $options) && + ($options['dateFormat'] === null || $options['dateFormat'] === 'NONE') + ) { + $firstInput = 'H'; + } elseif (!empty($options['dateFormat'])) { + $firstInput = substr($options['dateFormat'], 0, 1); + } + switch ($firstInput) { + case 'D': + $idKey = 'day'; + $labelAttributes['for'] .= 'Day'; + break; + case 'Y': + $idKey = 'year'; + $labelAttributes['for'] .= 'Year'; + break; + case 'M': + $idKey = 'month'; + $labelAttributes['for'] .= 'Month'; + break; + case 'H': + $idKey = 'hour'; + $labelAttributes['for'] .= 'Hour'; + } + } + if ($options['type'] === 'time') { + $labelAttributes['for'] .= 'Hour'; + $idKey = 'hour'; + } + if (isset($idKey) && isset($options['id']) && isset($options['id'][$idKey])) { + $labelAttributes['for'] = $options['id'][$idKey]; + } + + if (is_array($label)) { + $labelText = null; + if (isset($label['text'])) { + $labelText = $label['text']; + unset($label['text']); + } + $labelAttributes = array_merge($labelAttributes, $label); + } else { + $labelText = $label; + } + + if (isset($options['id']) && is_string($options['id'])) { + $labelAttributes = array_merge($labelAttributes, array('for' => $options['id'])); + } + return $this->label($fieldName, $labelText, $labelAttributes); + } + +/** + * Creates a checkbox input widget. + * + * ### Options: + * + * - `value` - the value of the checkbox + * - `checked` - boolean indicate that this checkbox is checked. + * - `hiddenField` - boolean to indicate if you want the results of checkbox() to include + * a hidden input with a value of ''. + * - `disabled` - create a disabled input. + * - `default` - Set the default value for the checkbox. This allows you to start checkboxes + * as checked, without having to check the POST data. A matching POST data value, will overwrite + * the default value. + * + * @param string $fieldName Name of a field, like this "Modelname.fieldname" + * @param array $options Array of HTML attributes. + * @return string An HTML text input element. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs + */ + public function checkbox($fieldName, $options = array()) { + $valueOptions = array(); + if (isset($options['default'])) { + $valueOptions['default'] = $options['default']; + unset($options['default']); + } + + $options = $this->_initInputField($fieldName, $options) + array('hiddenField' => true); + $value = current($this->value($valueOptions)); + $output = ""; + + if (empty($options['value'])) { + $options['value'] = 1; + } + if ( + (!isset($options['checked']) && !empty($value) && $value == $options['value']) || + !empty($options['checked']) + ) { + $options['checked'] = 'checked'; + } + if ($options['hiddenField']) { + $hiddenOptions = array( + 'id' => $options['id'] . '_', + 'name' => $options['name'], + 'value' => ($options['hiddenField'] !== true ? $options['hiddenField'] : '0'), + 'secure' => false + ); + if (isset($options['disabled']) && $options['disabled'] == true) { + $hiddenOptions['disabled'] = 'disabled'; + } + $output = $this->hidden($fieldName, $hiddenOptions); + } + unset($options['hiddenField']); + + return $output . $this->Html->useTag('checkbox', $options['name'], array_diff_key($options, array('name' => ''))); + } + +/** + * Creates a set of radio widgets. Will create a legend and fieldset + * by default. Use $options to control this + * + * ### Attributes: + * + * - `separator` - define the string in between the radio buttons + * - `between` - the string between legend and input set + * - `legend` - control whether or not the widget set has a fieldset & legend + * - `value` - indicate a value that is should be checked + * - `label` - boolean to indicate whether or not labels for widgets show be displayed + * - `hiddenField` - boolean to indicate if you want the results of radio() to include + * a hidden input with a value of ''. This is useful for creating radio sets that non-continuous + * - `disabled` - Set to `true` or `disabled` to disable all the radio buttons. + * - `empty` - Set to `true` to create a input with the value '' as the first option. When `true` + * the radio label will be 'empty'. Set this option to a string to control the label value. + * + * @param string $fieldName Name of a field, like this "Modelname.fieldname" + * @param array $options Radio button options array. + * @param array $attributes Array of HTML attributes, and special attributes above. + * @return string Completed radio widget set. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs + */ + public function radio($fieldName, $options = array(), $attributes = array()) { + $attributes = $this->_initInputField($fieldName, $attributes); + + $showEmpty = $this->_extractOption('empty', $attributes); + if ($showEmpty) { + $showEmpty = ($showEmpty === true) ? __('empty') : $showEmpty; + $options = array('' => $showEmpty) + $options; + } + unset($attributes['empty']); + + $legend = false; + if (isset($attributes['legend'])) { + $legend = $attributes['legend']; + unset($attributes['legend']); + } elseif (count($options) > 1) { + $legend = __(Inflector::humanize($this->field())); + } + + $label = true; + if (isset($attributes['label'])) { + $label = $attributes['label']; + unset($attributes['label']); + } + + $separator = null; + if (isset($attributes['separator'])) { + $separator = $attributes['separator']; + unset($attributes['separator']); + } + + $between = null; + if (isset($attributes['between'])) { + $between = $attributes['between']; + unset($attributes['between']); + } + + $value = null; + if (isset($attributes['value'])) { + $value = $attributes['value']; + } else { + $value = $this->value($fieldName); + } + + $disabled = array(); + if (isset($attributes['disabled'])) { + $disabled = $attributes['disabled']; + } + + $out = array(); + + $hiddenField = isset($attributes['hiddenField']) ? $attributes['hiddenField'] : true; + unset($attributes['hiddenField']); + + foreach ($options as $optValue => $optTitle) { + $optionsHere = array('value' => $optValue); + + if (isset($value) && $optValue == $value) { + $optionsHere['checked'] = 'checked'; + } + if ($disabled && (!is_array($disabled) || in_array($optValue, $disabled))) { + $optionsHere['disabled'] = true; + } + $tagName = Inflector::camelize( + $attributes['id'] . '_' . Inflector::slug($optValue) + ); + + if ($label) { + $optTitle = $this->Html->useTag('label', $tagName, '', $optTitle); + } + $allOptions = array_merge($attributes, $optionsHere); + $out[] = $this->Html->useTag('radio', $attributes['name'], $tagName, + array_diff_key($allOptions, array('name' => '', 'type' => '', 'id' => '')), + $optTitle + ); + } + $hidden = null; + + if ($hiddenField) { + if (!isset($value) || $value === '') { + $hidden = $this->hidden($fieldName, array( + 'id' => $attributes['id'] . '_', 'value' => '', 'name' => $attributes['name'] + )); + } + } + $out = $hidden . implode($separator, $out); + + if ($legend) { + $out = $this->Html->useTag('fieldset', '', $this->Html->useTag('legend', $legend) . $between . $out); + } + return $out; + } + +/** + * Missing method handler - implements various simple input types. Is used to create inputs + * of various types. e.g. `$this->Form->text();` will create `<input type="text" />` while + * `$this->Form->range();` will create `<input type="range" />` + * + * ### Usage + * + * `$this->Form->search('User.query', array('value' => 'test'));` + * + * Will make an input like: + * + * `<input type="search" id="UserQuery" name="data[User][query]" value="test" />` + * + * The first argument to an input type should always be the fieldname, in `Model.field` format. + * The second argument should always be an array of attributes for the input. + * + * @param string $method Method name / input type to make. + * @param array $params Parameters for the method call + * @return string Formatted input method. + * @throws CakeException When there are no params for the method call. + */ + public function __call($method, $params) { + $options = array(); + if (empty($params)) { + throw new CakeException(__d('cake_dev', 'Missing field name for FormHelper::%s', $method)); + } + if (isset($params[1])) { + $options = $params[1]; + } + if (!isset($options['type'])) { + $options['type'] = $method; + } + $options = $this->_initInputField($params[0], $options); + return $this->Html->useTag('input', $options['name'], array_diff_key($options, array('name' => ''))); + } + +/** + * Creates a textarea widget. + * + * ### Options: + * + * - `escape` - Whether or not the contents of the textarea should be escaped. Defaults to true. + * + * @param string $fieldName Name of a field, in the form "Modelname.fieldname" + * @param array $options Array of HTML attributes, and special options above. + * @return string A generated HTML text input element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::textarea + */ + public function textarea($fieldName, $options = array()) { + $options = $this->_initInputField($fieldName, $options); + $value = null; + + if (array_key_exists('value', $options)) { + $value = $options['value']; + if (!array_key_exists('escape', $options) || $options['escape'] !== false) { + $value = h($value); + } + unset($options['value']); + } + return $this->Html->useTag('textarea', $options['name'], array_diff_key($options, array('type' => '', 'name' => '')), $value); + } + +/** + * Creates a hidden input field. + * + * @param string $fieldName Name of a field, in the form of "Modelname.fieldname" + * @param array $options Array of HTML attributes. + * @return string A generated hidden input + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::hidden + */ + public function hidden($fieldName, $options = array()) { + $secure = true; + + if (isset($options['secure'])) { + $secure = $options['secure']; + unset($options['secure']); + } + $options = $this->_initInputField($fieldName, array_merge( + $options, array('secure' => self::SECURE_SKIP) + )); + + if ($secure && $secure !== self::SECURE_SKIP) { + $this->_secure(true, null, '' . $options['value']); + } + + return $this->Html->useTag('hidden', $options['name'], array_diff_key($options, array('name' => ''))); + } + +/** + * Creates file input widget. + * + * @param string $fieldName Name of a field, in the form "Modelname.fieldname" + * @param array $options Array of HTML attributes. + * @return string A generated file input. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::file + */ + public function file($fieldName, $options = array()) { + $options += array('secure' => true); + $secure = $options['secure']; + $options['secure'] = self::SECURE_SKIP; + + $options = $this->_initInputField($fieldName, $options); + $field = $this->entity(); + + foreach (array('name', 'type', 'tmp_name', 'error', 'size') as $suffix) { + $this->_secure($secure, array_merge($field, array($suffix))); + } + + return $this->Html->useTag('file', $options['name'], array_diff_key($options, array('name' => ''))); + } + +/** + * Creates a `<button>` tag. The type attribute defaults to `type="submit"` + * You can change it to a different value by using `$options['type']`. + * + * ### Options: + * + * - `escape` - HTML entity encode the $title of the button. Defaults to false. + * + * @param string $title The button's caption. Not automatically HTML encoded + * @param array $options Array of options and HTML attributes. + * @return string A HTML button tag. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::button + */ + public function button($title, $options = array()) { + $options += array('type' => 'submit', 'escape' => false, 'secure' => false); + if ($options['escape']) { + $title = h($title); + } + if (isset($options['name'])) { + $name = str_replace(array('[', ']'), array('.', ''), $options['name']); + $this->_secure($options['secure'], $name); + } + return $this->Html->useTag('button', $options, $title); + } + +/** + * Create a `<button>` tag with a surrounding `<form>` that submits via POST. + * + * This method creates a `<form>` element. So do not use this method in an already opened form. + * Instead use FormHelper::submit() or FormHelper::button() to create buttons inside opened forms. + * + * ### Options: + * + * - `data` - Array with key/value to pass in input hidden + * - Other options is the same of button method. + * + * @param string $title The button's caption. Not automatically HTML encoded + * @param string|array $url URL as string or array + * @param array $options Array of options and HTML attributes. + * @return string A HTML button tag. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::postButton + */ + public function postButton($title, $url, $options = array()) { + $out = $this->create(false, array('id' => false, 'url' => $url)); + if (isset($options['data']) && is_array($options['data'])) { + foreach ($options['data'] as $key => $value) { + $out .= $this->hidden($key, array('value' => $value, 'id' => false)); + } + unset($options['data']); + } + $out .= $this->button($title, $options); + $out .= $this->end(); + return $out; + } + +/** + * Creates an HTML link, but access the url using method POST. + * Requires javascript to be enabled in browser. + * + * This method creates a `<form>` element. So do not use this method inside an existing form. + * Instead you should add a submit button using FormHelper::submit() + * + * ### Options: + * + * - `data` - Array with key/value to pass in input hidden + * - `confirm` - Can be used instead of $confirmMessage. + * - Other options is the same of HtmlHelper::link() method. + * - The option `onclick` will be replaced. + * + * @param string $title The content to be wrapped by <a> tags. + * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://) + * @param array $options Array of HTML attributes. + * @param string $confirmMessage JavaScript confirmation message. + * @return string An `<a />` element. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::postLink + */ + public function postLink($title, $url = null, $options = array(), $confirmMessage = false) { + if (!empty($options['confirm'])) { + $confirmMessage = $options['confirm']; + unset($options['confirm']); + } + + $formName = uniqid('post_'); + $formUrl = $this->url($url); + $out = $this->Html->useTag('form', $formUrl, array('name' => $formName, 'id' => $formName, 'style' => 'display:none;', 'method' => 'post')); + $out .= $this->Html->useTag('hidden', '_method', ' value="POST"'); + $out .= $this->_csrfField(); + + $fields = array(); + if (isset($options['data']) && is_array($options['data'])) { + foreach ($options['data'] as $key => $value) { + $fields[$key] = $value; + $out .= $this->hidden($key, array('value' => $value, 'id' => false)); + } + unset($options['data']); + } + $out .= $this->secure($fields); + $out .= $this->Html->useTag('formend'); + + $url = '#'; + $onClick = 'document.' . $formName . '.submit();'; + if ($confirmMessage) { + $confirmMessage = str_replace(array("'", '"'), array("\'", '\"'), $confirmMessage); + $options['onclick'] = "if (confirm('{$confirmMessage}')) { {$onClick} }"; + } else { + $options['onclick'] = $onClick; + } + $options['onclick'] .= ' event.returnValue = false; return false;'; + + $out .= $this->Html->link($title, $url, $options); + return $out; + } + +/** + * Creates a submit button element. This method will generate `<input />` elements that + * can be used to submit, and reset forms by using $options. image submits can be created by supplying an + * image path for $caption. + * + * ### Options + * + * - `div` - Include a wrapping div? Defaults to true. Accepts sub options similar to + * FormHelper::input(). + * - `before` - Content to include before the input. + * - `after` - Content to include after the input. + * - `type` - Set to 'reset' for reset inputs. Defaults to 'submit' + * - Other attributes will be assigned to the input element. + * + * ### Options + * + * - `div` - Include a wrapping div? Defaults to true. Accepts sub options similar to + * FormHelper::input(). + * - Other attributes will be assigned to the input element. + * + * @param string $caption The label appearing on the button OR if string contains :// or the + * extension .jpg, .jpe, .jpeg, .gif, .png use an image if the extension + * exists, AND the first character is /, image is relative to webroot, + * OR if the first character is not /, image is relative to webroot/img. + * @param array $options Array of options. See above. + * @return string A HTML submit button + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::submit + */ + public function submit($caption = null, $options = array()) { + if (!is_string($caption) && empty($caption)) { + $caption = __d('cake', 'Submit'); + } + $out = null; + $div = true; + + if (isset($options['div'])) { + $div = $options['div']; + unset($options['div']); + } + $options += array('type' => 'submit', 'before' => null, 'after' => null, 'secure' => false); + $divOptions = array('tag' => 'div'); + + if ($div === true) { + $divOptions['class'] = 'submit'; + } elseif ($div === false) { + unset($divOptions); + } elseif (is_string($div)) { + $divOptions['class'] = $div; + } elseif (is_array($div)) { + $divOptions = array_merge(array('class' => 'submit', 'tag' => 'div'), $div); + } + + if (isset($options['name'])) { + $name = str_replace(array('[', ']'), array('.', ''), $options['name']); + $this->_secure($options['secure'], $name); + } + unset($options['secure']); + + $before = $options['before']; + $after = $options['after']; + unset($options['before'], $options['after']); + + $isUrl = strpos($caption, '://') !== false; + $isImage = preg_match('/\.(jpg|jpe|jpeg|gif|png|ico)$/', $caption); + + if ($isUrl || $isImage) { + $unlockFields = array('x', 'y'); + if (isset($options['name'])) { + $unlockFields = array( + $options['name'] . '_x', $options['name'] . '_y' + ); + } + foreach ($unlockFields as $ignore) { + $this->unlockField($ignore); + } + } + + if ($isUrl) { + unset($options['type']); + $tag = $this->Html->useTag('submitimage', $caption, $options); + } elseif ($isImage) { + unset($options['type']); + if ($caption{0} !== '/') { + $url = $this->webroot(IMAGES_URL . $caption); + } else { + $url = $this->webroot(trim($caption, '/')); + } + $url = $this->assetTimestamp($url); + $tag = $this->Html->useTag('submitimage', $url, $options); + } else { + $options['value'] = $caption; + $tag = $this->Html->useTag('submit', $options); + } + $out = $before . $tag . $after; + + if (isset($divOptions)) { + $tag = $divOptions['tag']; + unset($divOptions['tag']); + $out = $this->Html->tag($tag, $out, $divOptions); + } + return $out; + } + +/** + * Returns a formatted SELECT element. + * + * ### Attributes: + * + * - `showParents` - If included in the array and set to true, an additional option element + * will be added for the parent of each option group. You can set an option with the same name + * and it's key will be used for the value of the option. + * - `multiple` - show a multiple select box. If set to 'checkbox' multiple checkboxes will be + * created instead. + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `escape` - If true contents of options will be HTML entity encoded. Defaults to true. + * - `value` The selected value of the input. + * - `class` - When using multiple = checkbox the classname to apply to the divs. Defaults to 'checkbox'. + * + * ### Using options + * + * A simple array will create normal options: + * + * {{{ + * $options = array(1 => 'one', 2 => 'two); + * $this->Form->select('Model.field', $options)); + * }}} + * + * While a nested options array will create optgroups with options inside them. + * {{{ + * $options = array( + * 1 => 'bill', + * 'fred' => array( + * 2 => 'fred', + * 3 => 'fred jr.' + * ) + * ); + * $this->Form->select('Model.field', $options); + * }}} + * + * In the above `2 => 'fred'` will not generate an option element. You should enable the `showParents` + * attribute to show the fred option. + * + * If you have multiple options that need to have the same value attribute, you can + * use an array of arrays to express this: + * + * {{{ + * $options = array( + * array('name' => 'United states', 'value' => 'USA'), + * array('name' => 'USA', 'value' => 'USA'), + * ); + * }}} + * + * @param string $fieldName Name attribute of the SELECT + * @param array $options Array of the OPTION elements (as 'value'=>'Text' pairs) to be used in the + * SELECT element + * @param array $attributes The HTML attributes of the select element. + * @return string Formatted SELECT element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs + */ + public function select($fieldName, $options = array(), $attributes = array()) { + $select = array(); + $style = null; + $tag = null; + $attributes += array( + 'class' => null, + 'escape' => true, + 'secure' => true, + 'empty' => '', + 'showParents' => false, + 'hiddenField' => true + ); + + $escapeOptions = $this->_extractOption('escape', $attributes); + $secure = $this->_extractOption('secure', $attributes); + $showEmpty = $this->_extractOption('empty', $attributes); + $showParents = $this->_extractOption('showParents', $attributes); + $hiddenField = $this->_extractOption('hiddenField', $attributes); + unset($attributes['escape'], $attributes['secure'], $attributes['empty'], $attributes['showParents'], $attributes['hiddenField']); + $id = $this->_extractOption('id', $attributes); + + $attributes = $this->_initInputField($fieldName, array_merge( + (array)$attributes, array('secure' => self::SECURE_SKIP) + )); + + if (is_string($options) && isset($this->_options[$options])) { + $options = $this->_generateOptions($options); + } elseif (!is_array($options)) { + $options = array(); + } + if (isset($attributes['type'])) { + unset($attributes['type']); + } + + if (!empty($attributes['multiple'])) { + $style = ($attributes['multiple'] === 'checkbox') ? 'checkbox' : null; + $template = ($style) ? 'checkboxmultiplestart' : 'selectmultiplestart'; + $tag = $template; + if ($hiddenField) { + $hiddenAttributes = array( + 'value' => '', + 'id' => $attributes['id'] . ($style ? '' : '_'), + 'secure' => false, + 'name' => $attributes['name'] + ); + $select[] = $this->hidden(null, $hiddenAttributes); + } + } else { + $tag = 'selectstart'; + } + + if (!empty($tag) || isset($template)) { + if ((!isset($secure) || $secure == true) && empty($attributes['disabled'])) { + $this->_secure(true); + } + $select[] = $this->Html->useTag($tag, $attributes['name'], array_diff_key($attributes, array('name' => '', 'value' => ''))); + } + $emptyMulti = ( + $showEmpty !== null && $showEmpty !== false && !( + empty($showEmpty) && (isset($attributes) && + array_key_exists('multiple', $attributes)) + ) + ); + + if ($emptyMulti) { + $showEmpty = ($showEmpty === true) ? '' : $showEmpty; + $options = array('' => $showEmpty) + $options; + } + + if (!$id) { + $attributes['id'] = Inflector::camelize($attributes['id']); + } + + $select = array_merge($select, $this->_selectOptions( + array_reverse($options, true), + array(), + $showParents, + array( + 'escape' => $escapeOptions, + 'style' => $style, + 'name' => $attributes['name'], + 'value' => $attributes['value'], + 'class' => $attributes['class'], + 'id' => $attributes['id'] + ) + )); + + $template = ($style == 'checkbox') ? 'checkboxmultipleend' : 'selectend'; + $select[] = $this->Html->useTag($template); + return implode("\n", $select); + } + +/** + * Returns a SELECT element for days. + * + * ### Attributes: + * + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param array $attributes HTML attributes for the select element + * @return string A generated day select box. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::day + */ + public function day($fieldName = null, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + $attributes = $this->_dateTimeSelected('day', $fieldName, $attributes); + + if (strlen($attributes['value']) > 2) { + $attributes['value'] = date('d', strtotime($attributes['value'])); + } elseif ($attributes['value'] === false) { + $attributes['value'] = null; + } + return $this->select($fieldName . ".day", $this->_generateOptions('day'), $attributes); + } + +/** + * Returns a SELECT element for years + * + * ### Attributes: + * + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `orderYear` - Ordering of year values in select options. + * Possible values 'asc', 'desc'. Default 'desc' + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param integer $minYear First year in sequence + * @param integer $maxYear Last year in sequence + * @param array $attributes Attribute array for the select elements. + * @return string Completed year select input + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::year + */ + public function year($fieldName, $minYear = null, $maxYear = null, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + if ((empty($attributes['value']) || $attributes['value'] === true) && $value = $this->value($fieldName)) { + if (is_array($value)) { + extract($value); + $attributes['value'] = $year; + } else { + if (empty($value)) { + if (!$attributes['empty'] && !$maxYear) { + $attributes['value'] = 'now'; + + } elseif (!$attributes['empty'] && $maxYear && !$attributes['value']) { + $attributes['value'] = $maxYear; + } + } else { + $attributes['value'] = $value; + } + } + } + + if (strlen($attributes['value']) > 4 || $attributes['value'] === 'now') { + $attributes['value'] = date('Y', strtotime($attributes['value'])); + } elseif ($attributes['value'] === false) { + $attributes['value'] = null; + } + $yearOptions = array('min' => $minYear, 'max' => $maxYear, 'order' => 'desc'); + if (isset($attributes['orderYear'])) { + $yearOptions['order'] = $attributes['orderYear']; + unset($attributes['orderYear']); + } + return $this->select( + $fieldName . '.year', $this->_generateOptions('year', $yearOptions), + $attributes + ); + } + +/** + * Returns a SELECT element for months. + * + * ### Attributes: + * + * - `monthNames` - If false, 2 digit numbers will be used instead of text. + * If a array, the given array will be used. + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param array $attributes Attributes for the select element + * @return string A generated month select dropdown. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::month + */ + public function month($fieldName, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + $attributes = $this->_dateTimeSelected('month', $fieldName, $attributes); + + if (strlen($attributes['value']) > 2) { + $attributes['value'] = date('m', strtotime($attributes['value'])); + } elseif ($attributes['value'] === false) { + $attributes['value'] = null; + } + $defaults = array('monthNames' => true); + $attributes = array_merge($defaults, (array)$attributes); + $monthNames = $attributes['monthNames']; + unset($attributes['monthNames']); + + return $this->select( + $fieldName . ".month", + $this->_generateOptions('month', array('monthNames' => $monthNames)), + $attributes + ); + } + +/** + * Returns a SELECT element for hours. + * + * ### Attributes: + * + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param boolean $format24Hours True for 24 hours format + * @param array $attributes List of HTML attributes + * @return string Completed hour select input + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::hour + */ + public function hour($fieldName, $format24Hours = false, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + $attributes = $this->_dateTimeSelected('hour', $fieldName, $attributes); + + if (strlen($attributes['value']) > 2) { + if ($format24Hours) { + $attributes['value'] = date('H', strtotime($attributes['value'])); + } else { + $attributes['value'] = date('g', strtotime($attributes['value'])); + } + } elseif ($attributes['value'] === false) { + $attributes['value'] = null; + } + return $this->select( + $fieldName . ".hour", + $this->_generateOptions($format24Hours ? 'hour24' : 'hour'), + $attributes + ); + } + +/** + * Returns a SELECT element for minutes. + * + * ### Attributes: + * + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param string $attributes Array of Attributes + * @return string Completed minute select input. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::minute + */ + public function minute($fieldName, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + $attributes = $this->_dateTimeSelected('min', $fieldName, $attributes); + + if (strlen($attributes['value']) > 2) { + $attributes['value'] = date('i', strtotime($attributes['value'])); + } elseif ($attributes['value'] === false) { + $attributes['value'] = null; + } + $minuteOptions = array(); + + if (isset($attributes['interval'])) { + $minuteOptions['interval'] = $attributes['interval']; + unset($attributes['interval']); + } + return $this->select( + $fieldName . ".min", $this->_generateOptions('minute', $minuteOptions), + $attributes + ); + } + +/** + * Selects values for dateTime selects. + * + * @param string $select Name of element field. ex. 'day' + * @param string $fieldName Name of fieldName being generated ex. Model.created + * @param array $attributes Array of attributes, must contain 'empty' key. + * @return array Attributes array with currently selected value. + */ + protected function _dateTimeSelected($select, $fieldName, $attributes) { + if ((empty($attributes['value']) || $attributes['value'] === true) && $value = $this->value($fieldName)) { + if (is_array($value) && isset($value[$select])) { + $attributes['value'] = $value[$select]; + } else { + if (empty($value)) { + if (!$attributes['empty']) { + $attributes['value'] = 'now'; + } + } else { + $attributes['value'] = $value; + } + } + } + return $attributes; + } + +/** + * Returns a SELECT element for AM or PM. + * + * ### Attributes: + * + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` The selected value of the input. + * + * @param string $fieldName Prefix name for the SELECT element + * @param string $attributes Array of Attributes + * @return string Completed meridian select input + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::meridian + */ + public function meridian($fieldName, $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + if ((empty($attributes['value']) || $attributes['value'] === true) && $value = $this->value($fieldName)) { + if (is_array($value)) { + extract($value); + $attributes['value'] = $meridian; + } else { + if (empty($value)) { + if (!$attributes['empty']) { + $attributes['value'] = date('a'); + } + } else { + $attributes['value'] = date('a', strtotime($value)); + } + } + } + + if ($attributes['value'] === false) { + $attributes['value'] = null; + } + return $this->select( + $fieldName . ".meridian", $this->_generateOptions('meridian'), + $attributes + ); + } + +/** + * Returns a set of SELECT elements for a full datetime setup: day, month and year, and then time. + * + * ### Attributes: + * + * - `monthNames` If false, 2 digit numbers will be used instead of text. + * If a array, the given array will be used. + * - `minYear` The lowest year to use in the year select + * - `maxYear` The maximum year to use in the year select + * - `interval` The interval for the minutes select. Defaults to 1 + * - `separator` The contents of the string between select elements. Defaults to '-' + * - `empty` - If true, the empty select option is shown. If a string, + * that string is displayed as the empty element. + * - `value` | `default` The default value to be used by the input. A value in `$this->data` + * matching the field name will override this value. If no default is provided `time()` will be used. + * + * @param string $fieldName Prefix name for the SELECT element + * @param string $dateFormat DMY, MDY, YMD, or null to not generate date inputs. + * @param string $timeFormat 12, 24, or null to not generate time inputs. + * @param string $attributes array of Attributes + * @return string Generated set of select boxes for the date and time formats chosen. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::dateTime + */ + public function dateTime($fieldName, $dateFormat = 'DMY', $timeFormat = '12', $attributes = array()) { + $attributes += array('empty' => true, 'value' => null); + $year = $month = $day = $hour = $min = $meridian = null; + + if (empty($attributes['value'])) { + $attributes = $this->value($attributes, $fieldName); + } + + if ($attributes['value'] === null && $attributes['empty'] != true) { + $attributes['value'] = time(); + } + + if (!empty($attributes['value'])) { + if (is_array($attributes['value'])) { + extract($attributes['value']); + } else { + if (is_numeric($attributes['value'])) { + $attributes['value'] = strftime('%Y-%m-%d %H:%M:%S', $attributes['value']); + } + $meridian = 'am'; + $pos = strpos($attributes['value'], '-'); + if ($pos !== false) { + $date = explode('-', $attributes['value']); + $days = explode(' ', $date[2]); + $day = $days[0]; + $month = $date[1]; + $year = $date[0]; + } else { + $days[1] = $attributes['value']; + } + + if (!empty($timeFormat)) { + $time = explode(':', $days[1]); + + if (($time[0] > 12) && $timeFormat == '12') { + $time[0] = $time[0] - 12; + $meridian = 'pm'; + } elseif ($time[0] == '12' && $timeFormat == '12') { + $meridian = 'pm'; + } elseif ($time[0] == '00' && $timeFormat == '12') { + $time[0] = 12; + } elseif ($time[0] >= 12) { + $meridian = 'pm'; + } + if ($time[0] == 0 && $timeFormat == '12') { + $time[0] = 12; + } + $hour = $min = null; + if (isset($time[1])) { + $hour = $time[0]; + $min = $time[1]; + } + } + } + } + + $elements = array('Day', 'Month', 'Year', 'Hour', 'Minute', 'Meridian'); + $defaults = array( + 'minYear' => null, 'maxYear' => null, 'separator' => '-', + 'interval' => 1, 'monthNames' => true + ); + $attributes = array_merge($defaults, (array)$attributes); + if (isset($attributes['minuteInterval'])) { + $attributes['interval'] = $attributes['minuteInterval']; + unset($attributes['minuteInterval']); + } + $minYear = $attributes['minYear']; + $maxYear = $attributes['maxYear']; + $separator = $attributes['separator']; + $interval = $attributes['interval']; + $monthNames = $attributes['monthNames']; + $attributes = array_diff_key($attributes, $defaults); + + if (isset($attributes['id'])) { + if (is_string($attributes['id'])) { + // build out an array version + foreach ($elements as $element) { + $selectAttrName = 'select' . $element . 'Attr'; + ${$selectAttrName} = $attributes; + ${$selectAttrName}['id'] = $attributes['id'] . $element; + } + } elseif (is_array($attributes['id'])) { + // check for missing ones and build selectAttr for each element + $attributes['id'] += array( + 'month' => '', 'year' => '', 'day' => '', + 'hour' => '', 'minute' => '', 'meridian' => '' + ); + foreach ($elements as $element) { + $selectAttrName = 'select' . $element . 'Attr'; + ${$selectAttrName} = $attributes; + ${$selectAttrName}['id'] = $attributes['id'][strtolower($element)]; + } + } + } else { + // build the selectAttrName with empty id's to pass + foreach ($elements as $element) { + $selectAttrName = 'select' . $element . 'Attr'; + ${$selectAttrName} = $attributes; + } + } + + $selects = array(); + foreach (preg_split('//', $dateFormat, -1, PREG_SPLIT_NO_EMPTY) as $char) { + switch ($char) { + case 'Y': + $selectYearAttr['value'] = $year; + $selects[] = $this->year( + $fieldName, $minYear, $maxYear, $selectYearAttr + ); + break; + case 'M': + $selectMonthAttr['value'] = $month; + $selectMonthAttr['monthNames'] = $monthNames; + $selects[] = $this->month($fieldName, $selectMonthAttr); + break; + case 'D': + $selectDayAttr['value'] = $day; + $selects[] = $this->day($fieldName, $selectDayAttr); + break; + } + } + $opt = implode($separator, $selects); + + if (!empty($interval) && $interval > 1 && !empty($min)) { + $min = round($min * (1 / $interval)) * $interval; + } + $selectMinuteAttr['interval'] = $interval; + switch ($timeFormat) { + case '24': + $selectHourAttr['value'] = $hour; + $selectMinuteAttr['value'] = $min; + $opt .= $this->hour($fieldName, true, $selectHourAttr) . ':' . + $this->minute($fieldName, $selectMinuteAttr); + break; + case '12': + $selectHourAttr['value'] = $hour; + $selectMinuteAttr['value'] = $min; + $selectMeridianAttr['value'] = $meridian; + $opt .= $this->hour($fieldName, false, $selectHourAttr) . ':' . + $this->minute($fieldName, $selectMinuteAttr) . ' ' . + $this->meridian($fieldName, $selectMeridianAttr); + break; + default: + $opt .= ''; + break; + } + return $opt; + } + +/** + * Gets the input field name for the current tag + * + * @param array $options + * @param string $field + * @param string $key + * @return array + */ + protected function _name($options = array(), $field = null, $key = 'name') { + if ($this->requestType == 'get') { + if ($options === null) { + $options = array(); + } elseif (is_string($options)) { + $field = $options; + $options = 0; + } + + if (!empty($field)) { + $this->setEntity($field); + } + + if (is_array($options) && isset($options[$key])) { + return $options; + } + + $entity = $this->entity(); + $model = $this->model(); + $name = $model === $entity[0] && isset($entity[1]) ? $entity[1] : $entity[0]; + $last = $entity[count($entity) - 1]; + if (in_array($last, $this->_fieldSuffixes)) { + $name .= '[' . $last . ']'; + } + + if (is_array($options)) { + $options[$key] = $name; + return $options; + } else { + return $name; + } + } + return parent::_name($options, $field, $key); + } + +/** + * Returns an array of formatted OPTION/OPTGROUP elements + * + * @param array $elements + * @param array $parents + * @param boolean $showParents + * @param array $attributes + * @return array + */ + protected function _selectOptions($elements = array(), $parents = array(), $showParents = null, $attributes = array()) { + $select = array(); + $attributes = array_merge( + array('escape' => true, 'style' => null, 'value' => null, 'class' => null), + $attributes + ); + $selectedIsEmpty = ($attributes['value'] === '' || $attributes['value'] === null); + $selectedIsArray = is_array($attributes['value']); + + foreach ($elements as $name => $title) { + $htmlOptions = array(); + if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) { + if (!empty($name)) { + if ($attributes['style'] === 'checkbox') { + $select[] = $this->Html->useTag('fieldsetend'); + } else { + $select[] = $this->Html->useTag('optiongroupend'); + } + $parents[] = $name; + } + $select = array_merge($select, $this->_selectOptions( + $title, $parents, $showParents, $attributes + )); + + if (!empty($name)) { + $name = $attributes['escape'] ? h($name) : $name; + if ($attributes['style'] === 'checkbox') { + $select[] = $this->Html->useTag('fieldsetstart', $name); + } else { + $select[] = $this->Html->useTag('optiongroup', $name, ''); + } + } + $name = null; + } elseif (is_array($title)) { + $htmlOptions = $title; + $name = $title['value']; + $title = $title['name']; + unset($htmlOptions['name'], $htmlOptions['value']); + } + + if ($name !== null) { + if ( + (!$selectedIsArray && !$selectedIsEmpty && (string)$attributes['value'] == (string)$name) || + ($selectedIsArray && in_array($name, $attributes['value'])) + ) { + if ($attributes['style'] === 'checkbox') { + $htmlOptions['checked'] = true; + } else { + $htmlOptions['selected'] = 'selected'; + } + } + + if ($showParents || (!in_array($title, $parents))) { + $title = ($attributes['escape']) ? h($title) : $title; + + if ($attributes['style'] === 'checkbox') { + $htmlOptions['value'] = $name; + + $tagName = $attributes['id'] . Inflector::camelize(Inflector::slug($name)); + $htmlOptions['id'] = $tagName; + $label = array('for' => $tagName); + + if (isset($htmlOptions['checked']) && $htmlOptions['checked'] === true) { + $label['class'] = 'selected'; + } + + $name = $attributes['name']; + + if (empty($attributes['class'])) { + $attributes['class'] = 'checkbox'; + } elseif ($attributes['class'] === 'form-error') { + $attributes['class'] = 'checkbox ' . $attributes['class']; + } + $label = $this->label(null, $title, $label); + $item = $this->Html->useTag('checkboxmultiple', $name, $htmlOptions); + $select[] = $this->Html->div($attributes['class'], $item . $label); + } else { + $select[] = $this->Html->useTag('selectoption', $name, $htmlOptions, $title); + } + } + } + } + + return array_reverse($select, true); + } + +/** + * Generates option lists for common <select /> menus + * + * @param string $name + * @param array $options + * @return array + */ + protected function _generateOptions($name, $options = array()) { + if (!empty($this->options[$name])) { + return $this->options[$name]; + } + $data = array(); + + switch ($name) { + case 'minute': + if (isset($options['interval'])) { + $interval = $options['interval']; + } else { + $interval = 1; + } + $i = 0; + while ($i < 60) { + $data[sprintf('%02d', $i)] = sprintf('%02d', $i); + $i += $interval; + } + break; + case 'hour': + for ($i = 1; $i <= 12; $i++) { + $data[sprintf('%02d', $i)] = $i; + } + break; + case 'hour24': + for ($i = 0; $i <= 23; $i++) { + $data[sprintf('%02d', $i)] = $i; + } + break; + case 'meridian': + $data = array('am' => 'am', 'pm' => 'pm'); + break; + case 'day': + $min = 1; + $max = 31; + + if (isset($options['min'])) { + $min = $options['min']; + } + if (isset($options['max'])) { + $max = $options['max']; + } + + for ($i = $min; $i <= $max; $i++) { + $data[sprintf('%02d', $i)] = $i; + } + break; + case 'month': + if ($options['monthNames'] === true) { + $data['01'] = __d('cake', 'January'); + $data['02'] = __d('cake', 'February'); + $data['03'] = __d('cake', 'March'); + $data['04'] = __d('cake', 'April'); + $data['05'] = __d('cake', 'May'); + $data['06'] = __d('cake', 'June'); + $data['07'] = __d('cake', 'July'); + $data['08'] = __d('cake', 'August'); + $data['09'] = __d('cake', 'September'); + $data['10'] = __d('cake', 'October'); + $data['11'] = __d('cake', 'November'); + $data['12'] = __d('cake', 'December'); + } elseif (is_array($options['monthNames'])) { + $data = $options['monthNames']; + } else { + for ($m = 1; $m <= 12; $m++) { + $data[sprintf("%02s", $m)] = strftime("%m", mktime(1, 1, 1, $m, 1, 1999)); + } + } + break; + case 'year': + $current = intval(date('Y')); + + $min = !isset($options['min']) ? $current - 20 : (int)$options['min']; + $max = !isset($options['max']) ? $current + 20 : (int)$options['max']; + + if ($min > $max) { + list($min, $max) = array($max, $min); + } + for ($i = $min; $i <= $max; $i++) { + $data[$i] = $i; + } + if ($options['order'] != 'asc') { + $data = array_reverse($data, true); + } + break; + } + $this->_options[$name] = $data; + return $this->_options[$name]; + } + +/** + * Sets field defaults and adds field to form security input hash + * + * ### Options + * + * - `secure` - boolean whether or not the field should be added to the security fields. + * Disabling the field using the `disabled` option, will also omit the field from being + * part of the hashed key. + * + * @param string $field Name of the field to initialize options for. + * @param array $options Array of options to append options into. + * @return array Array of options for the input. + */ + protected function _initInputField($field, $options = array()) { + if (isset($options['secure'])) { + $secure = $options['secure']; + unset($options['secure']); + } else { + $secure = (isset($this->request['_Token']) && !empty($this->request['_Token'])); + } + + $result = parent::_initInputField($field, $options); + if ($this->tagIsInvalid() !== false) { + $result = $this->addClass($result, 'form-error'); + } + if (!empty($result['disabled']) || $secure === self::SECURE_SKIP) { + return $result; + } + + $fieldName = null; + if (!empty($options['name'])) { + preg_match_all('/\[(.*?)\]/', $options['name'], $matches); + if (isset($matches[1])) { + $fieldName = $matches[1]; + } + } + + $this->_secure($secure, $fieldName); + return $result; + } + +/** + * Set/Get inputDefaults for form elements + * + * @param array $defaults New default values + * @param boolean Merge with current defaults + * @return array inputDefaults + */ + public function inputDefaults($defaults = null, $merge = false) { + if (!is_null($defaults)) { + if ($merge) { + $this->_inputDefaults = array_merge($this->_inputDefaults, (array)$defaults); + } else { + $this->_inputDefaults = (array)$defaults; + } + } + return $this->_inputDefaults; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/HtmlHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/HtmlHelper.php new file mode 100644 index 0000000..fb53cf3 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/HtmlHelper.php @@ -0,0 +1,1214 @@ +<?php +/** + * Html Helper class file. + * + * Simplifies the construction of HTML elements. + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 0.9.1 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); +App::uses('CakeResponse', 'Network'); + +/** + * Html Helper class for easy use of HTML widgets. + * + * HtmlHelper encloses all methods needed while working with HTML pages. + * + * @package Cake.View.Helper + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html + */ +class HtmlHelper extends AppHelper { + +/** + * Reference to the Response object + * + * @var CakeResponse + */ + public $response; + +/** + * html tags used by this helper. + * + * @var array + */ + protected $_tags = array( + 'meta' => '<meta%s/>', + 'metalink' => '<link href="%s"%s/>', + 'link' => '<a href="%s"%s>%s</a>', + 'mailto' => '<a href="mailto:%s" %s>%s</a>', + 'form' => '<form action="%s"%s>', + 'formend' => '</form>', + 'input' => '<input name="%s"%s/>', + 'textarea' => '<textarea name="%s"%s>%s</textarea>', + 'hidden' => '<input type="hidden" name="%s"%s/>', + 'checkbox' => '<input type="checkbox" name="%s" %s/>', + 'checkboxmultiple' => '<input type="checkbox" name="%s[]"%s />', + 'radio' => '<input type="radio" name="%s" id="%s"%s />%s', + 'selectstart' => '<select name="%s"%s>', + 'selectmultiplestart' => '<select name="%s[]"%s>', + 'selectempty' => '<option value=""%s> </option>', + 'selectoption' => '<option value="%s"%s>%s</option>', + 'selectend' => '</select>', + 'optiongroup' => '<optgroup label="%s"%s>', + 'optiongroupend' => '</optgroup>', + 'checkboxmultiplestart' => '', + 'checkboxmultipleend' => '', + 'password' => '<input type="password" name="%s" %s/>', + 'file' => '<input type="file" name="%s" %s/>', + 'file_no_model' => '<input type="file" name="%s" %s/>', + 'submit' => '<input %s/>', + 'submitimage' => '<input type="image" src="%s" %s/>', + 'button' => '<button%s>%s</button>', + 'image' => '<img src="%s" %s/>', + 'tableheader' => '<th%s>%s</th>', + 'tableheaderrow' => '<tr%s>%s</tr>', + 'tablecell' => '<td%s>%s</td>', + 'tablerow' => '<tr%s>%s</tr>', + 'block' => '<div%s>%s</div>', + 'blockstart' => '<div%s>', + 'blockend' => '</div>', + 'tag' => '<%s%s>%s</%s>', + 'tagstart' => '<%s%s>', + 'tagend' => '</%s>', + 'tagselfclosing' => '<%s%s/>', + 'para' => '<p%s>%s</p>', + 'parastart' => '<p%s>', + 'label' => '<label for="%s"%s>%s</label>', + 'fieldset' => '<fieldset%s>%s</fieldset>', + 'fieldsetstart' => '<fieldset><legend>%s</legend>', + 'fieldsetend' => '</fieldset>', + 'legend' => '<legend>%s</legend>', + 'css' => '<link rel="%s" type="text/css" href="%s" %s/>', + 'style' => '<style type="text/css"%s>%s</style>', + 'charset' => '<meta http-equiv="Content-Type" content="text/html; charset=%s" />', + 'ul' => '<ul%s>%s</ul>', + 'ol' => '<ol%s>%s</ol>', + 'li' => '<li%s>%s</li>', + 'error' => '<div%s>%s</div>', + 'javascriptblock' => '<script type="text/javascript"%s>%s</script>', + 'javascriptstart' => '<script type="text/javascript">', + 'javascriptlink' => '<script type="text/javascript" src="%s"%s></script>', + 'javascriptend' => '</script>' + ); + +/** + * Breadcrumbs. + * + * @var array + */ + protected $_crumbs = array(); + +/** + * Names of script files that have been included once + * + * @var array + */ + protected $_includedScripts = array(); + +/** + * Options for the currently opened script block buffer if any. + * + * @var array + */ + protected $_scriptBlockOptions = array(); + +/** + * Document type definitions + * + * @var array + */ + protected $_docTypes = array( + 'html4-strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', + 'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', + 'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">', + 'html5' => '<!DOCTYPE html>', + 'xhtml-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', + 'xhtml-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', + 'xhtml-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">', + 'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' + ); + +/** + * Constructor + * + * ### Settings + * + * - `configFile` A file containing an array of tags you wish to redefine. + * + * ### Customizing tag sets + * + * Using the `configFile` option you can redefine the tag HtmlHelper will use. + * The file named should be compatible with HtmlHelper::loadConfig(). + * + * @param View $View The View this helper is being attached to. + * @param array $settings Configuration settings for the helper. + */ + public function __construct(View $View, $settings = array()) { + parent::__construct($View, $settings); + if (is_object($this->_View->response)) { + $this->response = $this->_View->response; + } else { + $this->response = new CakeResponse(array('charset' => Configure::read('App.encoding'))); + } + if (!empty($settings['configFile'])) { + $this->loadConfig($settings['configFile']); + } + } + +/** + * Adds a link to the breadcrumbs array. + * + * @param string $name Text for link + * @param string $link URL for link (if empty it won't be a link) + * @param string|array $options Link attributes e.g. array('id' => 'selected') + * @return void + * @see HtmlHelper::link() for details on $options that can be used. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper + */ + public function addCrumb($name, $link = null, $options = null) { + $this->_crumbs[] = array($name, $link, $options); + } + +/** + * Returns a doctype string. + * + * Possible doctypes: + * + * - html4-strict: HTML4 Strict. + * - html4-trans: HTML4 Transitional. + * - html4-frame: HTML4 Frameset. + * - html5: HTML5. Default value. + * - xhtml-strict: XHTML1 Strict. + * - xhtml-trans: XHTML1 Transitional. + * - xhtml-frame: XHTML1 Frameset. + * - xhtml11: XHTML1.1. + * + * @param string $type Doctype to use. + * @return string Doctype string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::docType + */ + public function docType($type = 'html5') { + if (isset($this->_docTypes[$type])) { + return $this->_docTypes[$type]; + } + return null; + } + +/** + * Creates a link to an external resource and handles basic meta tags + * + * Create a meta tag that is output inline: + * + * `$this->Html->meta('icon', 'favicon.ico'); + * + * Append the meta tag to `$scripts_for_layout`: + * + * `$this->Html->meta('description', 'A great page', array('inline' => false));` + * + * Append the meta tag to custom view block: + * + * `$this->Html->meta('description', 'A great page', array('block' => 'metaTags'));` + * + * ### Options + * + * - `inline` Whether or not the link element should be output inline. Set to false to + * have the meta tag included in `$scripts_for_layout`, and appended to the 'meta' view block. + * - `block` Choose a custom block to append the meta tag to. Using this option + * will override the inline option. + * + * @param string $type The title of the external resource + * @param string|array $url The address of the external resource or string for content attribute + * @param array $options Other attributes for the generated tag. If the type attribute is html, + * rss, atom, or icon, the mime-type is returned. + * @return string A completed `<link />` element. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::meta + */ + public function meta($type, $url = null, $options = array()) { + $options += array('inline' => true, 'block' => null); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } + unset($options['inline']); + + if (!is_array($type)) { + $types = array( + 'rss' => array('type' => 'application/rss+xml', 'rel' => 'alternate', 'title' => $type, 'link' => $url), + 'atom' => array('type' => 'application/atom+xml', 'title' => $type, 'link' => $url), + 'icon' => array('type' => 'image/x-icon', 'rel' => 'icon', 'link' => $url), + 'keywords' => array('name' => 'keywords', 'content' => $url), + 'description' => array('name' => 'description', 'content' => $url), + ); + + if ($type === 'icon' && $url === null) { + $types['icon']['link'] = $this->webroot('favicon.ico'); + } + + if (isset($types[$type])) { + $type = $types[$type]; + } elseif (!isset($options['type']) && $url !== null) { + if (is_array($url) && isset($url['ext'])) { + $type = $types[$url['ext']]; + } else { + $type = $types['rss']; + } + } elseif (isset($options['type']) && isset($types[$options['type']])) { + $type = $types[$options['type']]; + unset($options['type']); + } else { + $type = array(); + } + } elseif ($url !== null) { + $inline = $url; + } + $options = array_merge($type, $options); + $out = null; + + if (isset($options['link'])) { + if (isset($options['rel']) && $options['rel'] === 'icon') { + $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'), ' ', ' ')); + $options['rel'] = 'shortcut icon'; + } else { + $options['link'] = $this->url($options['link'], true); + } + $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'), ' ', ' ')); + } else { + $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('block', 'type'), ' ', ' ')); + } + + if (empty($options['block'])) { + return $out; + } else { + $this->_View->append($options['block'], $out); + } + } + +/** + * Returns a charset META-tag. + * + * @param string $charset The character set to be used in the meta tag. If empty, + * The App.encoding value will be used. Example: "utf-8". + * @return string A meta tag containing the specified character set. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::charset + */ + public function charset($charset = null) { + if (empty($charset)) { + $charset = strtolower(Configure::read('App.encoding')); + } + return sprintf($this->_tags['charset'], (!empty($charset) ? $charset : 'utf-8')); + } + +/** + * Creates an HTML link. + * + * If $url starts with "http://" this is treated as an external link. Else, + * it is treated as a path to controller/action and parsed with the + * HtmlHelper::url() method. + * + * If the $url is empty, $title is used instead. + * + * ### Options + * + * - `escape` Set to false to disable escaping of title and attributes. + * - `confirm` JavaScript confirmation message. + * + * @param string $title The content to be wrapped by <a> tags. + * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://) + * @param array $options Array of HTML attributes. + * @param string $confirmMessage JavaScript confirmation message. + * @return string An `<a />` element. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::link + */ + public function link($title, $url = null, $options = array(), $confirmMessage = false) { + $escapeTitle = true; + if ($url !== null) { + $url = $this->url($url); + } else { + $url = $this->url($title); + $title = htmlspecialchars_decode($url, ENT_QUOTES); + $title = h(urldecode($title)); + $escapeTitle = false; + } + + if (isset($options['escape'])) { + $escapeTitle = $options['escape']; + } + + if ($escapeTitle === true) { + $title = h($title); + } elseif (is_string($escapeTitle)) { + $title = htmlentities($title, ENT_QUOTES, $escapeTitle); + } + + if (!empty($options['confirm'])) { + $confirmMessage = $options['confirm']; + unset($options['confirm']); + } + if ($confirmMessage) { + $confirmMessage = str_replace("'", "\'", $confirmMessage); + $confirmMessage = str_replace('"', '\"', $confirmMessage); + $options['onclick'] = "return confirm('{$confirmMessage}');"; + } elseif (isset($options['default']) && $options['default'] == false) { + if (isset($options['onclick'])) { + $options['onclick'] .= ' event.returnValue = false; return false;'; + } else { + $options['onclick'] = 'event.returnValue = false; return false;'; + } + unset($options['default']); + } + return sprintf($this->_tags['link'], $url, $this->_parseAttributes($options), $title); + } + +/** + * Creates a link element for CSS stylesheets. + * + * ### Usage + * + * Include one CSS file: + * + * `echo $this->Html->css('styles.css');` + * + * Include multiple CSS files: + * + * `echo $this->Html->css(array('one.css', 'two.css'));` + * + * Add the stylesheet to the `$scripts_for_layout` layout var: + * + * `$this->Html->css('styles.css', null, array('inline' => false));` + * + * Add the stylesheet to a custom block: + * + * `$this->Html->css('styles.css', null, array('block' => 'layoutCss'));` + * + * ### Options + * + * - `inline` If set to false, the generated tag will be appended to the 'css' block, + * and included in the `$scripts_for_layout` layout variable. Defaults to true. + * - `block` Set the name of the block link/style tag will be appended to. This overrides the `inline` + * option. + * - `plugin` False value will prevent parsing path as a plugin + * + * @param string|array $path The name of a CSS style sheet or an array containing names of + * CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot + * of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css. + * @param string $rel Rel attribute. Defaults to "stylesheet". If equal to 'import' the stylesheet will be imported. + * @param array $options Array of HTML attributes. + * @return string CSS <link /> or <style /> tag, depending on the type of link. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::css + */ + public function css($path, $rel = null, $options = array()) { + $options += array('block' => null, 'inline' => true); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } + unset($options['inline']); + + if (is_array($path)) { + $out = ''; + foreach ($path as $i) { + $out .= "\n\t" . $this->css($i, $rel, $options); + } + if (empty($options['block'])) { + return $out . "\n"; + } + return; + } + + if (strpos($path, '//') !== false) { + $url = $path; + } else { + $url = $this->assetUrl($path, $options + array('pathPrefix' => CSS_URL, 'ext' => '.css')); + + if (Configure::read('Asset.filter.css')) { + $pos = strpos($url, CSS_URL); + if ($pos !== false) { + $url = substr($url, 0, $pos) . 'ccss/' . substr($url, $pos + strlen(CSS_URL)); + } + } + } + + if ($rel == 'import') { + $out = sprintf($this->_tags['style'], $this->_parseAttributes($options, array('inline', 'block'), '', ' '), '@import url(' . $url . ');'); + } else { + if ($rel == null) { + $rel = 'stylesheet'; + } + $out = sprintf($this->_tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline', 'block'), '', ' ')); + } + + if (empty($options['block'])) { + return $out; + } else { + $this->_View->append($options['block'], $out); + } + } + +/** + * Returns one or many `<script>` tags depending on the number of scripts given. + * + * If the filename is prefixed with "/", the path will be relative to the base path of your + * application. Otherwise, the path will be relative to your JavaScript path, usually webroot/js. + * + * + * ### Usage + * + * Include one script file: + * + * `echo $this->Html->script('styles.js');` + * + * Include multiple script files: + * + * `echo $this->Html->script(array('one.js', 'two.js'));` + * + * Add the script file to the `$scripts_for_layout` layout var: + * + * `$this->Html->script('styles.js', array('inline' => false));` + * + * Add the script file to a custom block: + * + * `$this->Html->script('styles.js', null, array('block' => 'bodyScript'));` + * + * ### Options + * + * - `inline` Whether script should be output inline or into `$scripts_for_layout`. When set to false, + * the script tag will be appended to the 'script' view block as well as `$scripts_for_layout`. + * - `block` The name of the block you want the script appended to. Leave undefined to output inline. + * Using this option will override the inline option. + * - `once` Whether or not the script should be checked for uniqueness. If true scripts will only be + * included once, use false to allow the same script to be included more than once per request. + * - `plugin` False value will prevent parsing path as a plugin + * + * @param string|array $url String or array of javascript files to include + * @param array|boolean $options Array of options, and html attributes see above. If boolean sets $options['inline'] = value + * @return mixed String of `<script />` tags or null if $inline is false or if $once is true and the file has been + * included before. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::script + */ + public function script($url, $options = array()) { + if (is_bool($options)) { + list($inline, $options) = array($options, array()); + $options['inline'] = $inline; + } + $options = array_merge(array('block' => null, 'inline' => true, 'once' => true), $options); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } + unset($options['inline']); + + if (is_array($url)) { + $out = ''; + foreach ($url as $i) { + $out .= "\n\t" . $this->script($i, $options); + } + if (empty($options['block'])) { + return $out . "\n"; + } + return null; + } + if ($options['once'] && isset($this->_includedScripts[$url])) { + return null; + } + $this->_includedScripts[$url] = true; + + if (strpos($url, '//') === false) { + $url = $this->assetUrl($url, $options + array('pathPrefix' => JS_URL, 'ext' => '.js')); + + if (Configure::read('Asset.filter.js')) { + $url = str_replace(JS_URL, 'cjs/', $url); + } + } + $attributes = $this->_parseAttributes($options, array('block', 'once'), ' '); + $out = sprintf($this->_tags['javascriptlink'], $url, $attributes); + + if (empty($options['block'])) { + return $out; + } else { + $this->_View->append($options['block'], $out); + } + } + +/** + * Wrap $script in a script tag. + * + * ### Options + * + * - `safe` (boolean) Whether or not the $script should be wrapped in <![CDATA[ ]]> + * - `inline` (boolean) Whether or not the $script should be added to + * `$scripts_for_layout` / `script` block, or output inline. (Deprecated, use `block` instead) + * - `block` Which block you want this script block appended to. + * Defaults to `script`. + * + * @param string $script The script to wrap + * @param array $options The options to use. Options not listed above will be + * treated as HTML attributes. + * @return mixed string or null depending on the value of `$options['block']` + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptBlock + */ + public function scriptBlock($script, $options = array()) { + $options += array('safe' => true, 'inline' => true); + if ($options['safe']) { + $script = "\n" . '//<![CDATA[' . "\n" . $script . "\n" . '//]]>' . "\n"; + } + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = 'script'; + } + unset($options['inline'], $options['safe']); + + $attributes = $this->_parseAttributes($options, array('block'), ' '); + $out = sprintf($this->_tags['javascriptblock'], $attributes, $script); + + if (empty($options['block'])) { + return $out; + } else { + $this->_View->append($options['block'], $out); + } + } + +/** + * Begin a script block that captures output until HtmlHelper::scriptEnd() + * is called. This capturing block will capture all output between the methods + * and create a scriptBlock from it. + * + * ### Options + * + * - `safe` Whether the code block should contain a CDATA + * - `inline` Should the generated script tag be output inline or in `$scripts_for_layout` + * + * @param array $options Options for the code block. + * @return void + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptStart + */ + public function scriptStart($options = array()) { + $options += array('safe' => true, 'inline' => true); + $this->_scriptBlockOptions = $options; + ob_start(); + return null; + } + +/** + * End a Buffered section of Javascript capturing. + * Generates a script tag inline or in `$scripts_for_layout` depending on the settings + * used when the scriptBlock was started + * + * @return mixed depending on the settings of scriptStart() either a script tag or null + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptEnd + */ + public function scriptEnd() { + $buffer = ob_get_clean(); + $options = $this->_scriptBlockOptions; + $this->_scriptBlockOptions = array(); + return $this->scriptBlock($buffer, $options); + } + +/** + * Builds CSS style data from an array of CSS properties + * + * ### Usage: + * + * {{{ + * echo $html->style(array('margin' => '10px', 'padding' => '10px'), true); + * + * // creates + * 'margin:10px;padding:10px;' + * }}} + * + * @param array $data Style data array, keys will be used as property names, values as property values. + * @param boolean $oneline Whether or not the style block should be displayed on one line. + * @return string CSS styling data + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::style + */ + public function style($data, $oneline = true) { + if (!is_array($data)) { + return $data; + } + $out = array(); + foreach ($data as $key => $value) { + $out[] = $key . ':' . $value . ';'; + } + if ($oneline) { + return join(' ', $out); + } + return implode("\n", $out); + } + +/** + * Returns the breadcrumb trail as a sequence of »-separated links. + * + * If `$startText` is an array, the accepted keys are: + * + * - `text` Define the text/content for the link. + * - `url` Define the target of the created link. + * + * All other keys will be passed to HtmlHelper::link() as the `$options` parameter. + * + * @param string $separator Text to separate crumbs. + * @param string|array|boolean $startText This will be the first crumb, if false it defaults to first crumb in array. Can + * also be an array, see above for details. + * @return string Composed bread crumbs + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper + */ + public function getCrumbs($separator = '»', $startText = false) { + $crumbs = $this->_prepareCrumbs($startText); + if (!empty($crumbs)) { + $out = array(); + foreach ($crumbs as $crumb) { + if (!empty($crumb[1])) { + $out[] = $this->link($crumb[0], $crumb[1], $crumb[2]); + } else { + $out[] = $crumb[0]; + } + } + return join($separator, $out); + } else { + return null; + } + } + +/** + * Returns breadcrumbs as a (x)html list + * + * This method uses HtmlHelper::tag() to generate list and its elements. Works + * similar to HtmlHelper::getCrumbs(), so it uses options which every + * crumb was added with. + * + * @param array $options Array of html attributes to apply to the generated list elements. + * @param string|array|boolean $startText This will be the first crumb, if false it defaults to first crumb in array. Can + * also be an array, see `HtmlHelper::getCrumbs` for details. + * @return string breadcrumbs html list + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper + */ + public function getCrumbList($options = array(), $startText = false) { + $crumbs = $this->_prepareCrumbs($startText); + if (!empty($crumbs)) { + $result = ''; + $crumbCount = count($crumbs); + $ulOptions = $options; + foreach ($crumbs as $which => $crumb) { + $options = array(); + if (empty($crumb[1])) { + $elementContent = $crumb[0]; + } else { + $elementContent = $this->link($crumb[0], $crumb[1], $crumb[2]); + } + if ($which == 0) { + $options['class'] = 'first'; + } elseif ($which == $crumbCount - 1) { + $options['class'] = 'last'; + } + $result .= $this->tag('li', $elementContent, $options); + } + return $this->tag('ul', $result, $ulOptions); + } else { + return null; + } + } + +/** + * Prepends startText to crumbs array if set + * + * @param $startText + * @return array Crumb list including startText (if provided) + */ + protected function _prepareCrumbs($startText) { + $crumbs = $this->_crumbs; + if ($startText) { + if (!is_array($startText)) { + $startText = array( + 'url' => '/', + 'text' => $startText + ); + } + $startText += array('url' => '/', 'text' => __('Home')); + list($url, $text) = array($startText['url'], $startText['text']); + unset($startText['url'], $startText['text']); + array_unshift($crumbs, array($text, $url, $startText)); + } + return $crumbs; + } + +/** + * Creates a formatted IMG element. + * + * This method will set an empty alt attribute if one is not supplied. + * + * ### Usage: + * + * Create a regular image: + * + * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP'));` + * + * Create an image link: + * + * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));` + * + * ### Options: + * + * - `url` If provided an image link will be generated and the link will point at + * `$options['url']`. + * - `fullBase` If true the src attribute will get a full address for the image file. + * - `plugin` False value will prevent parsing path as a plugin + * + * @param string $path Path to the image file, relative to the app/webroot/img/ directory. + * @param array $options Array of HTML attributes. See above for special options. + * @return string completed img tag + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::image + */ + public function image($path, $options = array()) { + $path = $this->assetUrl($path, $options + array('pathPrefix' => IMAGES_URL)); + $options = array_diff_key($options, array('fullBase' => '', 'pathPrefix' => '')); + + if (!isset($options['alt'])) { + $options['alt'] = ''; + } + + $url = false; + if (!empty($options['url'])) { + $url = $options['url']; + unset($options['url']); + } + + $image = sprintf($this->_tags['image'], $path, $this->_parseAttributes($options, null, '', ' ')); + + if ($url) { + return sprintf($this->_tags['link'], $this->url($url), null, $image); + } + return $image; + } + +/** + * Returns a row of formatted and named TABLE headers. + * + * @param array $names Array of tablenames. Each tablename also can be a key that points to an array with a set + * of attributes to its specific tag + * @param array $trOptions HTML options for TR elements. + * @param array $thOptions HTML options for TH elements. + * @return string Completed table headers + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableHeaders + */ + public function tableHeaders($names, $trOptions = null, $thOptions = null) { + $out = array(); + foreach ($names as $arg) { + if (!is_array($arg)) { + $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes($thOptions), $arg); + } else { + $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes(current($arg)), key($arg)); + } + } + return sprintf($this->_tags['tablerow'], $this->_parseAttributes($trOptions), join(' ', $out)); + } + +/** + * Returns a formatted string of table rows (TR's with TD's in them). + * + * @param array $data Array of table data + * @param array $oddTrOptions HTML options for odd TR elements if true useCount is used + * @param array $evenTrOptions HTML options for even TR elements + * @param boolean $useCount adds class "column-$i" + * @param boolean $continueOddEven If false, will use a non-static $count variable, + * so that the odd/even count is reset to zero just for that call. + * @return string Formatted HTML + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableCells + */ + public function tableCells($data, $oddTrOptions = null, $evenTrOptions = null, $useCount = false, $continueOddEven = true) { + if (empty($data[0]) || !is_array($data[0])) { + $data = array($data); + } + + if ($oddTrOptions === true) { + $useCount = true; + $oddTrOptions = null; + } + + if ($evenTrOptions === false) { + $continueOddEven = false; + $evenTrOptions = null; + } + + if ($continueOddEven) { + static $count = 0; + } else { + $count = 0; + } + + foreach ($data as $line) { + $count++; + $cellsOut = array(); + $i = 0; + foreach ($line as $cell) { + $cellOptions = array(); + + if (is_array($cell)) { + $cellOptions = $cell[1]; + $cell = $cell[0]; + } elseif ($useCount) { + $cellOptions['class'] = 'column-' . ++$i; + } + $cellsOut[] = sprintf($this->_tags['tablecell'], $this->_parseAttributes($cellOptions), $cell); + } + $options = $this->_parseAttributes($count % 2 ? $oddTrOptions : $evenTrOptions); + $out[] = sprintf($this->_tags['tablerow'], $options, implode(' ', $cellsOut)); + } + return implode("\n", $out); + } + +/** + * Returns a formatted block tag, i.e DIV, SPAN, P. + * + * ### Options + * + * - `escape` Whether or not the contents should be html_entity escaped. + * + * @param string $name Tag name. + * @param string $text String content that will appear inside the div element. + * If null, only a start tag will be printed + * @param array $options Additional HTML attributes of the DIV tag, see above. + * @return string The formatted tag element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tag + */ + public function tag($name, $text = null, $options = array()) { + if (is_array($options) && isset($options['escape']) && $options['escape']) { + $text = h($text); + unset($options['escape']); + } + if (!is_array($options)) { + $options = array('class' => $options); + } + if ($text === null) { + $tag = 'tagstart'; + } else { + $tag = 'tag'; + } + return sprintf($this->_tags[$tag], $name, $this->_parseAttributes($options, null, ' ', ''), $text, $name); + } + +/** + * Returns a formatted existent block of $tags + * + * @param string $tag Tag name + * @return string Formatted block + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::useTag + */ + public function useTag($tag) { + if (!isset($this->_tags[$tag])) { + return ''; + } + $args = func_get_args(); + array_shift($args); + foreach ($args as &$arg) { + if (is_array($arg)) { + $arg = $this->_parseAttributes($arg, null, ' ', ''); + } + } + return vsprintf($this->_tags[$tag], $args); + } + +/** + * Returns a formatted DIV tag for HTML FORMs. + * + * ### Options + * + * - `escape` Whether or not the contents should be html_entity escaped. + * + * @param string $class CSS class name of the div element. + * @param string $text String content that will appear inside the div element. + * If null, only a start tag will be printed + * @param array $options Additional HTML attributes of the DIV tag + * @return string The formatted DIV element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::div + */ + public function div($class = null, $text = null, $options = array()) { + if (!empty($class)) { + $options['class'] = $class; + } + return $this->tag('div', $text, $options); + } + +/** + * Returns a formatted P tag. + * + * ### Options + * + * - `escape` Whether or not the contents should be html_entity escaped. + * + * @param string $class CSS class name of the p element. + * @param string $text String content that will appear inside the p element. + * @param array $options Additional HTML attributes of the P tag + * @return string The formatted P element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::para + */ + public function para($class, $text, $options = array()) { + if (isset($options['escape'])) { + $text = h($text); + } + if ($class != null && !empty($class)) { + $options['class'] = $class; + } + if ($text === null) { + $tag = 'parastart'; + } else { + $tag = 'para'; + } + return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text); + } + +/** + * Returns an audio/video element + * + * ### Usage + * + * Using an audio file: + * + * `echo $this->Html->media('audio.mp3', array('fullBase' => true));` + * + * Outputs: + * + * `<video src="http://www.somehost.com/files/audio.mp3">Fallback text</video>` + * + * Using a video file: + * + * `echo $this->Html->media('video.mp4', array('text' => 'Fallback text'));` + * + * Outputs: + * + * `<video src="/files/video.mp4">Fallback text</video>` + * + * Using multiple video files: + * + * {{{ + * echo $this->Html->media( + * array('video.mp4', array('src' => 'video.ogv', 'type' => "video/ogg; codecs='theora, vorbis'")), + * array('tag' => 'video', 'autoplay') + * ); + * }}} + * + * Outputs: + * + * {{{ + * <video autoplay="autoplay"> + * <source src="/files/video.mp4" type="video/mp4"/> + * <source src="/files/video.ogv" type="video/ogv; codecs='theora, vorbis'"/> + * </video> + * }}} + * + * ### Options + * + * - `tag` Type of media element to generate, either "audio" or "video". + * If tag is not provided it's guessed based on file's mime type. + * - `text` Text to include inside the audio/video tag + * - `pathPrefix` Path prefix to use for relative urls, defaults to 'files/' + * - `fullBase` If provided the src attribute will get a full address including domain name + * + * @param string|array $path Path to the video file, relative to the webroot/{$options['pathPrefix']} directory. + * Or an array where each item itself can be a path string or an associate array containing keys `src` and `type` + * @param array $options Array of HTML attributes, and special options above. + * @return string Generated media element + */ + public function media($path, $options = array()) { + $options += array( + 'tag' => null, + 'pathPrefix' => 'files/', + 'text' => '' + ); + + if (!empty($options['tag'])) { + $tag = $options['tag']; + } else { + $tag = null; + } + + if (is_array($path)) { + $sourceTags = ''; + foreach ($path as &$source) { + if (is_string($source)) { + $source = array( + 'src' => $source, + ); + } + if (!isset($source['type'])) { + $ext = pathinfo($source['src'], PATHINFO_EXTENSION); + $source['type'] = $this->response->getMimeType($ext); + } + $source['src'] = $this->assetUrl($source['src'], $options); + $sourceTags .= $this->useTag('tagselfclosing', 'source', $source); + } + unset($source); + $options['text'] = $sourceTags . $options['text']; + unset($options['fullBase']); + } else { + if (empty($path) && !empty($options['src'])) { + $path = $options['src']; + } + $options['src'] = $this->assetUrl($path, $options); + } + + if ($tag === null) { + if (is_array($path)) { + $mimeType = $path[0]['type']; + } else { + $mimeType = $this->response->getMimeType(pathinfo($path, PATHINFO_EXTENSION)); + } + if (preg_match('#^video/#', $mimeType)) { + $tag = 'video'; + } else { + $tag = 'audio'; + } + } + + if (isset($options['poster'])) { + $options['poster'] = $this->assetUrl($options['poster'], array('pathPrefix' => IMAGES_URL) + $options); + } + $text = $options['text']; + + $options = array_diff_key($options, array( + 'tag' => '', + 'fullBase' => '', + 'pathPrefix' => '', + 'text' => '' + )); + return $this->tag($tag, $text, $options); + } + +/** + * Build a nested list (UL/OL) out of an associative array. + * + * @param array $list Set of elements to list + * @param array $options Additional HTML attributes of the list (ol/ul) tag or if ul/ol use that as tag + * @param array $itemOptions Additional HTML attributes of the list item (LI) tag + * @param string $tag Type of list tag to use (ol/ul) + * @return string The nested list + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::nestedList + */ + public function nestedList($list, $options = array(), $itemOptions = array(), $tag = 'ul') { + if (is_string($options)) { + $tag = $options; + $options = array(); + } + $items = $this->_nestedListItem($list, $options, $itemOptions, $tag); + return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $items); + } + +/** + * Internal function to build a nested list (UL/OL) out of an associative array. + * + * @param array $items Set of elements to list + * @param array $options Additional HTML attributes of the list (ol/ul) tag + * @param array $itemOptions Additional HTML attributes of the list item (LI) tag + * @param string $tag Type of list tag to use (ol/ul) + * @return string The nested list element + * @see HtmlHelper::nestedList() + */ + protected function _nestedListItem($items, $options, $itemOptions, $tag) { + $out = ''; + + $index = 1; + foreach ($items as $key => $item) { + if (is_array($item)) { + $item = $key . $this->nestedList($item, $options, $itemOptions, $tag); + } + if (isset($itemOptions['even']) && $index % 2 == 0) { + $itemOptions['class'] = $itemOptions['even']; + } elseif (isset($itemOptions['odd']) && $index % 2 != 0) { + $itemOptions['class'] = $itemOptions['odd']; + } + $out .= sprintf($this->_tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd'), ' ', ''), $item); + $index++; + } + return $out; + } + +/** + * Load Html tag configuration. + * + * Loads a file from APP/Config that contains tag data. By default the file is expected + * to be compatible with PhpReader: + * + * `$this->Html->loadConfig('tags.php');` + * + * tags.php could look like: + * + * {{{ + * $tags = array( + * 'meta' => '<meta %s>' + * ); + * }}} + * + * If you wish to store tag definitions in another format you can give an array + * containing the file name, and reader class name: + * + * `$this->Html->loadConfig(array('tags.ini', 'ini'));` + * + * Its expected that the `tags` index will exist from any configuration file that is read. + * You can also specify the path to read the configuration file from, if APP/Config is not + * where the file is. + * + * `$this->Html->loadConfig('tags.php', APP . 'Lib' . DS);` + * + * Configuration files can define the following sections: + * + * - `tags` The tags to replace. + * - `minimizedAttributes` The attributes that are represented like `disabled="disabled"` + * - `docTypes` Additional doctypes to use. + * - `attributeFormat` Format for long attributes e.g. `'%s="%s"'` + * - `minimizedAttributeFormat` Format for minimized attributes e.g. `'%s="%s"'` + * + * @param string|array $configFile String with the config file (load using PhpReader) or an array with file and reader name + * @param string $path Path with config file + * @return mixed False to error or loaded configs + * @throws ConfigureException + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#changing-the-tags-output-by-htmlhelper + */ + public function loadConfig($configFile, $path = null) { + if (!$path) { + $path = APP . 'Config' . DS; + } + $file = null; + $reader = 'php'; + + if (!is_array($configFile)) { + $file = $configFile; + } elseif (isset($configFile[0])) { + $file = $configFile[0]; + if (isset($configFile[1])) { + $reader = $configFile[1]; + } + } else { + throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Wrong "configFile" configuration.')); + } + + $readerClass = Inflector::camelize($reader) . 'Reader'; + App::uses($readerClass, 'Configure'); + if (!class_exists($readerClass)) { + throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Unknown reader.')); + } + + $readerObj = new $readerClass($path); + $configs = $readerObj->read($file); + if (isset($configs['tags']) && is_array($configs['tags'])) { + $this->_tags = array_merge($this->_tags, $configs['tags']); + } + if (isset($configs['minimizedAttributes']) && is_array($configs['minimizedAttributes'])) { + $this->_minimizedAttributes = array_merge($this->_minimizedAttributes, $configs['minimizedAttributes']); + } + if (isset($configs['docTypes']) && is_array($configs['docTypes'])) { + $this->_docTypes = array_merge($this->_docTypes, $configs['docTypes']); + } + if (isset($configs['attributeFormat'])) { + $this->_attributeFormat = $configs['attributeFormat']; + } + if (isset($configs['minimizedAttributeFormat'])) { + $this->_minimizedAttributeFormat = $configs['minimizedAttributeFormat']; + } + return $configs; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JqueryEngineHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JqueryEngineHelper.php new file mode 100644 index 0000000..d79a8ef --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JqueryEngineHelper.php @@ -0,0 +1,361 @@ +<?php +/** + * jQuery Engine Helper for JsHelper + * + * Provides jQuery specific Javascript for JsHelper. + * + * Implements the JsHelper interface for jQuery. All $options arrays + * support all options found in the JsHelper, as well as those in the jQuery + * documentation. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); +App::uses('JsBaseEngineHelper', 'View/Helper'); + +/** + * jQuery Engine Helper for JsHelper + * + * Provides jQuery specific Javascript for JsHelper. + * + * Implements the JsHelper interface for jQuery. All $options arrays + * support all options found in the JsHelper, as well as those in the jQuery + * documentation. + * + * @package Cake.View.Helper + */ +class JqueryEngineHelper extends JsBaseEngineHelper { + +/** + * Option mappings for jQuery + * + * @var array + */ + protected $_optionMap = array( + 'request' => array( + 'type' => 'dataType', + 'before' => 'beforeSend', + 'method' => 'type', + ), + 'sortable' => array( + 'complete' => 'stop', + ), + 'drag' => array( + 'snapGrid' => 'grid', + 'container' => 'containment', + ), + 'drop' => array( + 'leave' => 'out', + 'hover' => 'over' + ), + 'slider' => array( + 'complete' => 'stop', + 'direction' => 'orientation' + ) + ); + +/** + * Callback arguments lists + * + * @var string + */ + protected $_callbackArguments = array( + 'slider' => array( + 'start' => 'event, ui', + 'slide' => 'event, ui', + 'change' => 'event, ui', + 'stop' => 'event, ui' + ), + 'sortable' => array( + 'start' => 'event, ui', + 'sort' => 'event, ui', + 'change' => 'event, ui', + 'beforeStop' => 'event, ui', + 'stop' => 'event, ui', + 'update' => 'event, ui', + 'receive' => 'event, ui', + 'remove' => 'event, ui', + 'over' => 'event, ui', + 'out' => 'event, ui', + 'activate' => 'event, ui', + 'deactivate' => 'event, ui' + ), + 'drag' => array( + 'start' => 'event, ui', + 'drag' => 'event, ui', + 'stop' => 'event, ui', + ), + 'drop' => array( + 'activate' => 'event, ui', + 'deactivate' => 'event, ui', + 'over' => 'event, ui', + 'out' => 'event, ui', + 'drop' => 'event, ui' + ), + 'request' => array( + 'beforeSend' => 'XMLHttpRequest', + 'error' => 'XMLHttpRequest, textStatus, errorThrown', + 'success' => 'data, textStatus', + 'complete' => 'XMLHttpRequest, textStatus', + 'xhr' => '' + ) + ); + +/** + * The variable name of the jQuery Object, useful + * when jQuery is put into noConflict() mode. + * + * @var string + */ + public $jQueryObject = '$'; + +/** + * Helper function to wrap repetitive simple method templating. + * + * @param string $method The method name being generated. + * @param string $template The method template + * @param array $options Array of options for method + * @param array $extraSafeKeys Extra safe keys + * @return string Composed method string + */ + protected function _methodTemplate($method, $template, $options, $extraSafeKeys = array()) { + $options = $this->_mapOptions($method, $options); + $options = $this->_prepareCallbacks($method, $options); + $callbacks = array_keys($this->_callbackArguments[$method]); + if (!empty($extraSafeKeys)) { + $callbacks = array_merge($callbacks, $extraSafeKeys); + } + $options = $this->_parseOptions($options, $callbacks); + return sprintf($template, $this->selection, $options); + } + +/** + * Create javascript selector for a CSS rule + * + * @param string $selector The selector that is targeted + * @return JqueryEngineHelper instance of $this. Allows chained methods. + */ + public function get($selector) { + if ($selector == 'window' || $selector == 'document') { + $this->selection = $this->jQueryObject . '(' . $selector . ')'; + } else { + $this->selection = $this->jQueryObject . '("' . $selector . '")'; + } + return $this; + } + +/** + * Add an event to the script cache. Operates on the currently selected elements. + * + * ### Options + * + * - 'wrap' - Whether you want the callback wrapped in an anonymous function. (defaults true) + * - 'stop' - Whether you want the event to stopped. (defaults true) + * + * @param string $type Type of event to bind to the current dom id + * @param string $callback The Javascript function you wish to trigger or the function literal + * @param array $options Options for the event. + * @return string completed event handler + */ + public function event($type, $callback, $options = array()) { + $defaults = array('wrap' => true, 'stop' => true); + $options = array_merge($defaults, $options); + + $function = 'function (event) {%s}'; + if ($options['wrap'] && $options['stop']) { + $callback .= "\nreturn false;"; + } + if ($options['wrap']) { + $callback = sprintf($function, $callback); + } + return sprintf('%s.bind("%s", %s);', $this->selection, $type, $callback); + } + +/** + * Create a domReady event. For jQuery. This method does not + * bind a 'traditional event' as `$(document).bind('ready', fn)` + * Works in an entirely different fashion than `$(document).ready()` + * The first will not run the function when eval()'d as part of a response + * The second will. Because of the way that ajax pagination is done + * `$().ready()` is used. + * + * @param string $functionBody The code to run on domReady + * @return string completed domReady method + */ + public function domReady($functionBody) { + return $this->jQueryObject . '(document).ready(function () {' . $functionBody . '});'; + } + +/** + * Create an iteration over the current selection result. + * + * @param string $callback The function body you wish to apply during the iteration. + * @return string completed iteration + */ + public function each($callback) { + return $this->selection . '.each(function () {' . $callback . '});'; + } + +/** + * Trigger an Effect. + * + * @param string $name The name of the effect to trigger. + * @param array $options Array of options for the effect. + * @return string completed string with effect. + * @see JsBaseEngineHelper::effect() + */ + public function effect($name, $options = array()) { + $speed = null; + if (isset($options['speed']) && in_array($options['speed'], array('fast', 'slow'))) { + $speed = $this->value($options['speed']); + } + $effect = ''; + switch ($name) { + case 'slideIn': + case 'slideOut': + $name = ($name == 'slideIn') ? 'slideDown' : 'slideUp'; + case 'hide': + case 'show': + case 'fadeIn': + case 'fadeOut': + case 'slideDown': + case 'slideUp': + $effect = ".$name($speed);"; + break; + } + return $this->selection . $effect; + } + +/** + * Create an $.ajax() call. + * + * If the 'update' key is set, success callback will be overridden. + * + * @param string|array $url + * @param array $options See JsHelper::request() for options. + * @return string The completed ajax call. + * @see JsBaseEngineHelper::request() for options list. + */ + public function request($url, $options = array()) { + $url = $this->url($url); + $options = $this->_mapOptions('request', $options); + if (isset($options['data']) && is_array($options['data'])) { + $options['data'] = $this->_toQuerystring($options['data']); + } + $options['url'] = $url; + if (isset($options['update'])) { + $wrapCallbacks = isset($options['wrapCallbacks']) ? $options['wrapCallbacks'] : true; + $success = ''; + if (isset($options['success']) && !empty($options['success'])) { + $success .= $options['success']; + } + $success .= $this->jQueryObject . '("' . $options['update'] . '").html(data);'; + if (!$wrapCallbacks) { + $success = 'function (data, textStatus) {' . $success . '}'; + } + $options['dataType'] = 'html'; + $options['success'] = $success; + unset($options['update']); + } + $callbacks = array('success', 'error', 'beforeSend', 'complete'); + if (!empty($options['dataExpression'])) { + $callbacks[] = 'data'; + unset($options['dataExpression']); + } + $options = $this->_prepareCallbacks('request', $options); + $options = $this->_parseOptions($options, $callbacks); + return $this->jQueryObject . '.ajax({' . $options . '});'; + } + +/** + * Create a sortable element. + * + * Requires both Ui.Core and Ui.Sortables to be loaded. + * + * @param array $options Array of options for the sortable. + * @return string Completed sortable script. + * @see JsBaseEngineHelper::sortable() for options list. + */ + public function sortable($options = array()) { + $template = '%s.sortable({%s});'; + return $this->_methodTemplate('sortable', $template, $options); + } + +/** + * Create a Draggable element + * + * Requires both Ui.Core and Ui.Draggable to be loaded. + * + * @param array $options Array of options for the draggable element. + * @return string Completed Draggable script. + * @see JsBaseEngineHelper::drag() for options list. + */ + public function drag($options = array()) { + $template = '%s.draggable({%s});'; + return $this->_methodTemplate('drag', $template, $options); + } + +/** + * Create a Droppable element + * + * Requires both Ui.Core and Ui.Droppable to be loaded. + * + * @param array $options Array of options for the droppable element. + * @return string Completed Droppable script. + * @see JsBaseEngineHelper::drop() for options list. + */ + public function drop($options = array()) { + $template = '%s.droppable({%s});'; + return $this->_methodTemplate('drop', $template, $options); + } + +/** + * Create a Slider element + * + * Requires both Ui.Core and Ui.Slider to be loaded. + * + * @param array $options Array of options for the droppable element. + * @return string Completed Slider script. + * @see JsBaseEngineHelper::slider() for options list. + */ + public function slider($options = array()) { + $callbacks = array('start', 'change', 'slide', 'stop'); + $template = '%s.slider({%s});'; + return $this->_methodTemplate('slider', $template, $options, $callbacks); + } + +/** + * Serialize a form attached to $selector. If the current selection is not an input or + * form, errors will be created in the Javascript. + * + * @param array $options Options for the serialization + * @return string completed form serialization script. + * @see JsBaseEngineHelper::serializeForm() for option list. + */ + public function serializeForm($options = array()) { + $options = array_merge(array('isForm' => false, 'inline' => false), $options); + $selector = $this->selection; + if (!$options['isForm']) { + $selector = $this->selection . '.closest("form")'; + } + $method = '.serialize()'; + if (!$options['inline']) { + $method .= ';'; + } + return $selector . $method; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsBaseEngineHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsBaseEngineHelper.php new file mode 100644 index 0000000..b3a293a --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsBaseEngineHelper.php @@ -0,0 +1,592 @@ +<?php +/** + * CakePHP : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); + +/** + * JsEngineBaseClass + * + * Abstract Base Class for All JsEngines to extend. Provides generic methods. + * + * @package Cake.View.Helper + */ +abstract class JsBaseEngineHelper extends AppHelper { + +/** + * The js snippet for the current selection. + * + * @var string + */ + public $selection; + +/** + * Collection of option maps. Option maps allow other helpers to use generic names for engine + * callbacks and options. Allowing uniform code access for all engine types. Their use is optional + * for end user use though. + * + * @var array + */ + protected $_optionMap = array(); + +/** + * An array of lowercase method names in the Engine that are buffered unless otherwise disabled. + * This allows specific 'end point' methods to be automatically buffered by the JsHelper. + * + * @var array + */ + public $bufferedMethods = array('event', 'sortable', 'drag', 'drop', 'slider'); + +/** + * Contains a list of callback names -> default arguments. + * + * @var array + */ + protected $_callbackArguments = array(); + +/** + * Create an `alert()` message in Javascript + * + * @param string $message Message you want to alter. + * @return string completed alert() + */ + public function alert($message) { + return 'alert("' . $this->escape($message) . '");'; + } + +/** + * Redirects to a URL. Creates a window.location modification snippet + * that can be used to trigger 'redirects' from Javascript. + * + * @param string|array $url + * @param array $options + * @return string completed redirect in javascript + */ + public function redirect($url = null) { + return 'window.location = "' . Router::url($url) . '";'; + } + +/** + * Create a `confirm()` message + * + * @param string $message Message you want confirmed. + * @return string completed confirm() + */ + public function confirm($message) { + return 'confirm("' . $this->escape($message) . '");'; + } + +/** + * Generate a confirm snippet that returns false from the current + * function scope. + * + * @param string $message Message to use in the confirm dialog. + * @return string completed confirm with return script + */ + public function confirmReturn($message) { + $out = 'var _confirm = ' . $this->confirm($message); + $out .= "if (!_confirm) {\n\treturn false;\n}"; + return $out; + } + +/** + * Create a `prompt()` Javascript function + * + * @param string $message Message you want to prompt. + * @param string $default Default message + * @return string completed prompt() + */ + public function prompt($message, $default = '') { + return 'prompt("' . $this->escape($message) . '", "' . $this->escape($default) . '");'; + } + +/** + * Generates a JavaScript object in JavaScript Object Notation (JSON) + * from an array. Will use native JSON encode method if available, and $useNative == true + * + * ### Options: + * + * - `prefix` - String prepended to the returned data. + * - `postfix` - String appended to the returned data. + * + * @param array $data Data to be converted. + * @param array $options Set of options, see above. + * @return string A JSON code block + */ + public function object($data = array(), $options = array()) { + $defaultOptions = array( + 'prefix' => '', 'postfix' => '', + ); + $options = array_merge($defaultOptions, $options); + + return $options['prefix'] . json_encode($data) . $options['postfix']; + } + +/** + * Converts a PHP-native variable of any type to a JSON-equivalent representation + * + * @param mixed $val A PHP variable to be converted to JSON + * @param boolean $quoteString If false, leaves string values unquoted + * @return string a JavaScript-safe/JSON representation of $val + */ + public function value($val = array(), $quoteString = null, $key = 'value') { + if ($quoteString === null) { + $quoteString = true; + } + switch (true) { + case (is_array($val) || is_object($val)): + $val = $this->object($val); + break; + case ($val === null): + $val = 'null'; + break; + case (is_bool($val)): + $val = ($val === true) ? 'true' : 'false'; + break; + case (is_int($val)): + $val = $val; + break; + case (is_float($val)): + $val = sprintf("%.11f", $val); + break; + default: + $val = $this->escape($val); + if ($quoteString) { + $val = '"' . $val . '"'; + } + break; + } + return $val; + } + +/** + * Escape a string to be JSON friendly. + * + * List of escaped elements: + * + * - "\r" => '\n' + * - "\n" => '\n' + * - '"' => '\"' + * + * @param string $string String that needs to get escaped. + * @return string Escaped string. + */ + public function escape($string) { + return $this->_utf8ToHex($string); + } + +/** + * Encode a string into JSON. Converts and escapes necessary characters. + * + * @param string $string The string that needs to be utf8->hex encoded + * @return void + */ + protected function _utf8ToHex($string) { + $length = strlen($string); + $return = ''; + for ($i = 0; $i < $length; ++$i) { + $ord = ord($string{$i}); + switch (true) { + case $ord == 0x08: + $return .= '\b'; + break; + case $ord == 0x09: + $return .= '\t'; + break; + case $ord == 0x0A: + $return .= '\n'; + break; + case $ord == 0x0C: + $return .= '\f'; + break; + case $ord == 0x0D: + $return .= '\r'; + break; + case $ord == 0x22: + case $ord == 0x2F: + case $ord == 0x5C: + $return .= '\\' . $string{$i}; + break; + case (($ord >= 0x20) && ($ord <= 0x7F)): + $return .= $string{$i}; + break; + case (($ord & 0xE0) == 0xC0): + if ($i + 1 >= $length) { + $i += 1; + $return .= '?'; + break; + } + $charbits = $string{$i} . $string{$i + 1}; + $char = Multibyte::utf8($charbits); + $return .= sprintf('\u%04s', dechex($char[0])); + $i += 1; + break; + case (($ord & 0xF0) == 0xE0): + if ($i + 2 >= $length) { + $i += 2; + $return .= '?'; + break; + } + $charbits = $string{$i} . $string{$i + 1} . $string{$i + 2}; + $char = Multibyte::utf8($charbits); + $return .= sprintf('\u%04s', dechex($char[0])); + $i += 2; + break; + case (($ord & 0xF8) == 0xF0): + if ($i + 3 >= $length) { + $i += 3; + $return .= '?'; + break; + } + $charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3}; + $char = Multibyte::utf8($charbits); + $return .= sprintf('\u%04s', dechex($char[0])); + $i += 3; + break; + case (($ord & 0xFC) == 0xF8): + if ($i + 4 >= $length) { + $i += 4; + $return .= '?'; + break; + } + $charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4}; + $char = Multibyte::utf8($charbits); + $return .= sprintf('\u%04s', dechex($char[0])); + $i += 4; + break; + case (($ord & 0xFE) == 0xFC): + if ($i + 5 >= $length) { + $i += 5; + $return .= '?'; + break; + } + $charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4} . $string{$i + 5}; + $char = Multibyte::utf8($charbits); + $return .= sprintf('\u%04s', dechex($char[0])); + $i += 5; + break; + } + } + return $return; + } + +/** + * Create javascript selector for a CSS rule + * + * @param string $selector The selector that is targeted + * @return JsBaseEngineHelper instance of $this. Allows chained methods. + */ + abstract public function get($selector); + +/** + * Add an event to the script cache. Operates on the currently selected elements. + * + * ### Options + * + * - `wrap` - Whether you want the callback wrapped in an anonymous function. (defaults to true) + * - `stop` - Whether you want the event to stopped. (defaults to true) + * + * @param string $type Type of event to bind to the current dom id + * @param string $callback The Javascript function you wish to trigger or the function literal + * @param array $options Options for the event. + * @return string completed event handler + */ + abstract public function event($type, $callback, $options = array()); + +/** + * Create a domReady event. This is a special event in many libraries + * + * @param string $functionBody The code to run on domReady + * @return string completed domReady method + */ + abstract public function domReady($functionBody); + +/** + * Create an iteration over the current selection result. + * + * @param string $callback The function body you wish to apply during the iteration. + * @return string completed iteration + */ + abstract public function each($callback); + +/** + * Trigger an Effect. + * + * ### Supported Effects + * + * The following effects are supported by all core JsEngines + * + * - `show` - reveal an element. + * - `hide` - hide an element. + * - `fadeIn` - Fade in an element. + * - `fadeOut` - Fade out an element. + * - `slideIn` - Slide an element in. + * - `slideOut` - Slide an element out. + * + * ### Options + * + * - `speed` - Speed at which the animation should occur. Accepted values are 'slow', 'fast'. Not all effects use + * the speed option. + * + * @param string $name The name of the effect to trigger. + * @param array $options Array of options for the effect. + * @return string completed string with effect. + */ + abstract public function effect($name, $options = array()); + +/** + * Make an XHR request + * + * ### Event Options + * + * - `complete` - Callback to fire on complete. + * - `success` - Callback to fire on success. + * - `before` - Callback to fire on request initialization. + * - `error` - Callback to fire on request failure. + * + * ### Options + * + * - `method` - The method to make the request with defaults to GET in more libraries + * - `async` - Whether or not you want an asynchronous request. + * - `data` - Additional data to send. + * - `update` - Dom id to update with the content of the request. + * - `type` - Data type for response. 'json' and 'html' are supported. Default is html for most libraries. + * - `evalScripts` - Whether or not <script> tags should be eval'ed. + * - `dataExpression` - Should the `data` key be treated as a callback. Useful for supplying `$options['data']` as + * another Javascript expression. + * + * @param string|array $url Array or String URL to target with the request. + * @param array $options Array of options. See above for cross library supported options + * @return string XHR request. + */ + abstract public function request($url, $options = array()); + +/** + * Create a draggable element. Works on the currently selected element. + * Additional options may be supported by the library implementation. + * + * ### Options + * + * - `handle` - selector to the handle element. + * - `snapGrid` - The pixel grid that movement snaps to, an array(x, y) + * - `container` - The element that acts as a bounding box for the draggable element. + * + * ### Event Options + * + * - `start` - Event fired when the drag starts + * - `drag` - Event fired on every step of the drag + * - `stop` - Event fired when dragging stops (mouse release) + * + * @param array $options Options array see above. + * @return string Completed drag script + */ + abstract public function drag($options = array()); + +/** + * Create a droppable element. Allows for draggable elements to be dropped on it. + * Additional options may be supported by the library implementation. + * + * ### Options + * + * - `accept` - Selector for elements this droppable will accept. + * - `hoverclass` - Class to add to droppable when a draggable is over. + * + * ### Event Options + * + * - `drop` - Event fired when an element is dropped into the drop zone. + * - `hover` - Event fired when a drag enters a drop zone. + * - `leave` - Event fired when a drag is removed from a drop zone without being dropped. + * + * @param array $options Array of options for the drop. See above. + * @return string Completed drop script + */ + abstract public function drop($options = array()); + +/** + * Create a sortable element. + * Additional options may be supported by the library implementation. + * + * ### Options + * + * - `containment` - Container for move action + * - `handle` - Selector to handle element. Only this element will start sort action. + * - `revert` - Whether or not to use an effect to move sortable into final position. + * - `opacity` - Opacity of the placeholder + * - `distance` - Distance a sortable must be dragged before sorting starts. + * + * ### Event Options + * + * - `start` - Event fired when sorting starts + * - `sort` - Event fired during sorting + * - `complete` - Event fired when sorting completes. + * + * @param array $options Array of options for the sortable. See above. + * @return string Completed sortable script. + */ + abstract public function sortable($options = array()); + +/** + * Create a slider UI widget. Comprised of a track and knob. + * Additional options may be supported by the library implementation. + * + * ### Options + * + * - `handle` - The id of the element used in sliding. + * - `direction` - The direction of the slider either 'vertical' or 'horizontal' + * - `min` - The min value for the slider. + * - `max` - The max value for the slider. + * - `step` - The number of steps or ticks the slider will have. + * - `value` - The initial offset of the slider. + * + * ### Events + * + * - `change` - Fired when the slider's value is updated + * - `complete` - Fired when the user stops sliding the handle + * + * @param array $options Array of options for the slider. See above. + * @return string Completed slider script + */ + abstract public function slider($options = array()); + +/** + * Serialize the form attached to $selector. + * Pass `true` for $isForm if the current selection is a form element. + * Converts the form or the form element attached to the current selection into a string/json object + * (depending on the library implementation) for use with XHR operations. + * + * ### Options + * + * - `isForm` - is the current selection a form, or an input? (defaults to false) + * - `inline` - is the rendered statement going to be used inside another JS statement? (defaults to false) + * + * @param array $options options for serialization generation. + * @return string completed form serialization script + */ + abstract public function serializeForm($options = array()); + +/** + * Parse an options assoc array into an Javascript object literal. + * Similar to object() but treats any non-integer value as a string, + * does not include `{ }` + * + * @param array $options Options to be converted + * @param array $safeKeys Keys that should not be escaped. + * @return string Parsed JSON options without enclosing { }. + */ + protected function _parseOptions($options, $safeKeys = array()) { + $out = array(); + $safeKeys = array_flip($safeKeys); + foreach ($options as $key => $value) { + if (!is_int($value) && !isset($safeKeys[$key])) { + $value = $this->value($value); + } + $out[] = $key . ':' . $value; + } + sort($out); + return join(', ', $out); + } + +/** + * Maps Abstract options to engine specific option names. + * If attributes are missing from the map, they are not changed. + * + * @param string $method Name of method whose options are being worked with. + * @param array $options Array of options to map. + * @return array Array of mapped options. + */ + protected function _mapOptions($method, $options) { + if (!isset($this->_optionMap[$method])) { + return $options; + } + foreach ($this->_optionMap[$method] as $abstract => $concrete) { + if (isset($options[$abstract])) { + $options[$concrete] = $options[$abstract]; + unset($options[$abstract]); + } + } + return $options; + } + +/** + * Prepare callbacks and wrap them with function ([args]) { } as defined in + * _callbackArgs array. + * + * @param string $method Name of the method you are preparing callbacks for. + * @param array $options Array of options being parsed + * @param array $callbacks Additional Keys that contain callbacks + * @return array Array of options with callbacks added. + */ + protected function _prepareCallbacks($method, $options, $callbacks = array()) { + $wrapCallbacks = true; + if (isset($options['wrapCallbacks'])) { + $wrapCallbacks = $options['wrapCallbacks']; + } + unset($options['wrapCallbacks']); + if (!$wrapCallbacks) { + return $options; + } + $callbackOptions = array(); + if (isset($this->_callbackArguments[$method])) { + $callbackOptions = $this->_callbackArguments[$method]; + } + $callbacks = array_unique(array_merge(array_keys($callbackOptions), (array)$callbacks)); + + foreach ($callbacks as $callback) { + if (empty($options[$callback])) { + continue; + } + $args = null; + if (!empty($callbackOptions[$callback])) { + $args = $callbackOptions[$callback]; + } + $options[$callback] = 'function (' . $args . ') {' . $options[$callback] . '}'; + } + return $options; + } + +/** + * Convenience wrapper method for all common option processing steps. + * Runs _mapOptions, _prepareCallbacks, and _parseOptions in order. + * + * @param string $method Name of method processing options for. + * @param array $options Array of options to process. + * @return string Parsed options string. + */ + protected function _processOptions($method, $options) { + $options = $this->_mapOptions($method, $options); + $options = $this->_prepareCallbacks($method, $options); + $options = $this->_parseOptions($options, array_keys($this->_callbackArguments[$method])); + return $options; + } + +/** + * Convert an array of data into a query string + * + * @param array $parameters Array of parameters to convert to a query string + * @return string Querystring fragment + */ + protected function _toQuerystring($parameters) { + $out = ''; + $keys = array_keys($parameters); + $count = count($parameters); + for ($i = 0; $i < $count; $i++) { + $out .= $keys[$i] . '=' . $parameters[$keys[$i]]; + if ($i < $count - 1) { + $out .= '&'; + } + } + return $out; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsHelper.php new file mode 100644 index 0000000..5490fbb --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsHelper.php @@ -0,0 +1,434 @@ +<?php +/** + * Javascript Generator class file. + * + * PHP 5 + * + * CakePHP : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.2 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); +App::uses('JsBaseEngineHelper', 'View/Helper'); +App::uses('Multibyte', 'I18n'); + +/** + * Javascript Generator helper class for easy use of JavaScript. + * + * JsHelper provides an abstract interface for authoring JavaScript with a + * given client-side library. + * + * @package Cake.View.Helper + * @property HtmlHelper $Html + * @property FormHelper $Form + */ +class JsHelper extends AppHelper { + +/** + * Whether or not you want scripts to be buffered or output. + * + * @var boolean + */ + public $bufferScripts = true; + +/** + * Helper dependencies + * + * @var array + */ + public $helpers = array('Html', 'Form'); + +/** + * Variables to pass to Javascript. + * + * @var array + * @see JsHelper::set() + */ + protected $_jsVars = array(); + +/** + * Scripts that are queued for output + * + * @var array + * @see JsHelper::buffer() + */ + protected $_bufferedScripts = array(); + +/** + * Current Javascript Engine that is being used + * + * @var string + */ + protected $_engineName; + +/** + * The javascript variable created by set() variables. + * + * @var string + */ + public $setVariable = 'app'; + +/** + * Constructor - determines engine helper + * + * @param View $View the view object the helper is attached to. + * @param array $settings Settings array contains name of engine helper. + */ + public function __construct(View $View, $settings = array()) { + $className = 'Jquery'; + if (is_array($settings) && isset($settings[0])) { + $className = $settings[0]; + } elseif (is_string($settings)) { + $className = $settings; + } + $engineName = $className; + list($plugin, $className) = pluginSplit($className); + + $this->_engineName = $className . 'Engine'; + $engineClass = $engineName . 'Engine'; + $this->helpers[] = $engineClass; + parent::__construct($View, $settings); + } + +/** + * call__ Allows for dispatching of methods to the Engine Helper. + * methods in the Engines bufferedMethods list will be automatically buffered. + * You can control buffering with the buffer param as well. By setting the last parameter to + * any engine method to a boolean you can force or disable buffering. + * + * e.g. `$js->get('#foo')->effect('fadeIn', array('speed' => 'slow'), true);` + * + * Will force buffering for the effect method. If the method takes an options array you may also add + * a 'buffer' param to the options array and control buffering there as well. + * + * e.g. `$js->get('#foo')->event('click', $functionContents, array('buffer' => true));` + * + * The buffer parameter will not be passed onto the EngineHelper. + * + * @param string $method Method to be called + * @param array $params Parameters for the method being called. + * @return mixed Depends on the return of the dispatched method, or it could be an instance of the EngineHelper + */ + public function __call($method, $params) { + if ($this->{$this->_engineName} && method_exists($this->{$this->_engineName}, $method)) { + $buffer = false; + $engineHelper = $this->{$this->_engineName}; + if (in_array(strtolower($method), $engineHelper->bufferedMethods)) { + $buffer = true; + } + if (count($params) > 0) { + $lastParam = $params[count($params) - 1]; + $hasBufferParam = (is_bool($lastParam) || is_array($lastParam) && isset($lastParam['buffer'])); + if ($hasBufferParam && is_bool($lastParam)) { + $buffer = $lastParam; + unset($params[count($params) - 1]); + } elseif ($hasBufferParam && is_array($lastParam)) { + $buffer = $lastParam['buffer']; + unset($params['buffer']); + } + } + + $out = call_user_func_array(array(&$engineHelper, $method), $params); + if ($this->bufferScripts && $buffer && is_string($out)) { + $this->buffer($out); + return null; + } + if (is_object($out) && is_a($out, 'JsBaseEngineHelper')) { + return $this; + } + return $out; + } + if (method_exists($this, $method . '_')) { + return call_user_func(array(&$this, $method . '_'), $params); + } + trigger_error(__d('cake_dev', 'JsHelper:: Missing Method %s is undefined', $method), E_USER_WARNING); + } + +/** + * Overwrite inherited Helper::value() + * See JsBaseEngineHelper::value() for more information on this method. + * + * @param mixed $val A PHP variable to be converted to JSON + * @param boolean $quoteString If false, leaves string values unquoted + * @return string a JavaScript-safe/JSON representation of $val + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::value + **/ + public function value($val = array(), $quoteString = null, $key = 'value') { + if ($quoteString === null) { + $quoteString = true; + } + return $this->{$this->_engineName}->value($val, $quoteString); + } + +/** + * Writes all Javascript generated so far to a code block or + * caches them to a file and returns a linked script. If no scripts have been + * buffered this method will return null. If the request is an XHR(ajax) request + * onDomReady will be set to false. As the dom is already 'ready'. + * + * ### Options + * + * - `inline` - Set to true to have scripts output as a script block inline + * if `cache` is also true, a script link tag will be generated. (default true) + * - `cache` - Set to true to have scripts cached to a file and linked in (default false) + * - `clear` - Set to false to prevent script cache from being cleared (default true) + * - `onDomReady` - wrap cached scripts in domready event (default true) + * - `safe` - if an inline block is generated should it be wrapped in <![CDATA[ ... ]]> (default true) + * + * @param array $options options for the code block + * @return mixed Completed javascript tag if there are scripts, if there are no buffered + * scripts null will be returned. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::writeBuffer + */ + public function writeBuffer($options = array()) { + $domReady = !$this->request->is('ajax'); + $defaults = array( + 'onDomReady' => $domReady, 'inline' => true, + 'cache' => false, 'clear' => true, 'safe' => true + ); + $options = array_merge($defaults, $options); + $script = implode("\n", $this->getBuffer($options['clear'])); + + if (empty($script)) { + return null; + } + + if ($options['onDomReady']) { + $script = $this->{$this->_engineName}->domReady($script); + } + $opts = $options; + unset($opts['onDomReady'], $opts['cache'], $opts['clear']); + + if (!$options['cache'] && $options['inline']) { + return $this->Html->scriptBlock($script, $opts); + } + + if ($options['cache'] && $options['inline']) { + $filename = md5($script); + if (!file_exists(JS . $filename . '.js')) { + cache(str_replace(WWW_ROOT, '', JS) . $filename . '.js', $script, '+999 days', 'public'); + } + return $this->Html->script($filename); + } + $this->Html->scriptBlock($script, $opts); + return null; + } + +/** + * Write a script to the buffered scripts. + * + * @param string $script Script string to add to the buffer. + * @param boolean $top If true the script will be added to the top of the + * buffered scripts array. If false the bottom. + * @return void + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::buffer + */ + public function buffer($script, $top = false) { + if ($top) { + array_unshift($this->_bufferedScripts, $script); + } else { + $this->_bufferedScripts[] = $script; + } + } + +/** + * Get all the buffered scripts + * + * @param boolean $clear Whether or not to clear the script caches (default true) + * @return array Array of scripts added to the request. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::getBuffer + */ + public function getBuffer($clear = true) { + $this->_createVars(); + $scripts = $this->_bufferedScripts; + if ($clear) { + $this->_bufferedScripts = array(); + $this->_jsVars = array(); + } + return $scripts; + } + +/** + * Generates the object string for variables passed to javascript. + * + * @return string Generated JSON object of all set vars + */ + protected function _createVars() { + if (!empty($this->_jsVars)) { + $setVar = (strpos($this->setVariable, '.')) ? $this->setVariable : 'window.' . $this->setVariable; + $this->buffer($setVar . ' = ' . $this->object($this->_jsVars) . ';', true); + } + } + +/** + * Generate an 'Ajax' link. Uses the selected JS engine to create a link + * element that is enhanced with Javascript. Options can include + * both those for HtmlHelper::link() and JsBaseEngine::request(), JsBaseEngine::event(); + * + * ### Options + * + * - `confirm` - Generate a confirm() dialog before sending the event. + * - `id` - use a custom id. + * - `htmlAttributes` - additional non-standard htmlAttributes. Standard attributes are class, id, + * rel, title, escape, onblur and onfocus. + * - `buffer` - Disable the buffering and return a script tag in addition to the link. + * + * @param string $title Title for the link. + * @param string|array $url Mixed either a string URL or an cake url array. + * @param array $options Options for both the HTML element and Js::request() + * @return string Completed link. If buffering is disabled a script tag will be returned as well. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::link + */ + public function link($title, $url = null, $options = array()) { + if (!isset($options['id'])) { + $options['id'] = 'link-' . intval(mt_rand()); + } + list($options, $htmlOptions) = $this->_getHtmlOptions($options); + $out = $this->Html->link($title, $url, $htmlOptions); + $this->get('#' . $htmlOptions['id']); + $requestString = $event = ''; + if (isset($options['confirm'])) { + $requestString = $this->confirmReturn($options['confirm']); + unset($options['confirm']); + } + $buffer = isset($options['buffer']) ? $options['buffer'] : null; + $safe = isset($options['safe']) ? $options['safe'] : true; + unset($options['buffer'], $options['safe']); + + $requestString .= $this->request($url, $options); + + if (!empty($requestString)) { + $event = $this->event('click', $requestString, $options + array('buffer' => $buffer)); + } + if (isset($buffer) && !$buffer) { + $opts = array('safe' => $safe); + $out .= $this->Html->scriptBlock($event, $opts); + } + return $out; + } + +/** + * Pass variables into Javascript. Allows you to set variables that will be + * output when the buffer is fetched with `JsHelper::getBuffer()` or `JsHelper::writeBuffer()` + * The Javascript variable used to output set variables can be controlled with `JsHelper::$setVariable` + * + * @param string|array $one Either an array of variables to set, or the name of the variable to set. + * @param string|array $two If $one is a string, $two is the value for that key. + * @return void + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::set + */ + public function set($one, $two = null) { + $data = null; + if (is_array($one)) { + if (is_array($two)) { + $data = array_combine($one, $two); + } else { + $data = $one; + } + } else { + $data = array($one => $two); + } + if ($data == null) { + return false; + } + $this->_jsVars = array_merge($this->_jsVars, $data); + } + +/** + * Uses the selected JS engine to create a submit input + * element that is enhanced with Javascript. Options can include + * both those for FormHelper::submit() and JsBaseEngine::request(), JsBaseEngine::event(); + * + * Forms submitting with this method, cannot send files. Files do not transfer over XmlHttpRequest + * and require an iframe or flash. + * + * ### Options + * + * - `url` The url you wish the XHR request to submit to. + * - `confirm` A string to use for a confirm() message prior to submitting the request. + * - `method` The method you wish the form to send by, defaults to POST + * - `buffer` Whether or not you wish the script code to be buffered, defaults to true. + * - Also see options for JsHelper::request() and JsHelper::event() + * + * @param string $caption The display text of the submit button. + * @param array $options Array of options to use. See the options for the above mentioned methods. + * @return string Completed submit button. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::submit + */ + public function submit($caption = null, $options = array()) { + if (!isset($options['id'])) { + $options['id'] = 'submit-' . intval(mt_rand()); + } + $formOptions = array('div'); + list($options, $htmlOptions) = $this->_getHtmlOptions($options, $formOptions); + $out = $this->Form->submit($caption, $htmlOptions); + + $this->get('#' . $htmlOptions['id']); + + $options['data'] = $this->serializeForm(array('isForm' => false, 'inline' => true)); + $requestString = $url = ''; + if (isset($options['confirm'])) { + $requestString = $this->confirmReturn($options['confirm']); + unset($options['confirm']); + } + if (isset($options['url'])) { + $url = $options['url']; + unset($options['url']); + } + if (!isset($options['method'])) { + $options['method'] = 'post'; + } + $options['dataExpression'] = true; + + $buffer = isset($options['buffer']) ? $options['buffer'] : null; + $safe = isset($options['safe']) ? $options['safe'] : true; + unset($options['buffer'], $options['safe']); + + $requestString .= $this->request($url, $options); + if (!empty($requestString)) { + $event = $this->event('click', $requestString, $options + array('buffer' => $buffer)); + } + if (isset($buffer) && !$buffer) { + $opts = array('safe' => $safe); + $out .= $this->Html->scriptBlock($event, $opts); + } + return $out; + } + +/** + * Parse a set of Options and extract the Html options. + * Extracted Html Options are removed from the $options param. + * + * @param array $options Options to filter. + * @param array $additional Array of additional keys to extract and include in the return options array. + * @return array Array of js options and Htmloptions + */ + protected function _getHtmlOptions($options, $additional = array()) { + $htmlKeys = array_merge( + array('class', 'id', 'escape', 'onblur', 'onfocus', 'rel', 'title', 'style'), + $additional + ); + $htmlOptions = array(); + foreach ($htmlKeys as $key) { + if (isset($options[$key])) { + $htmlOptions[$key] = $options[$key]; + } + unset($options[$key]); + } + if (isset($options['htmlAttributes'])) { + $htmlOptions = array_merge($htmlOptions, $options['htmlAttributes']); + unset($options['htmlAttributes']); + } + return array($options, $htmlOptions); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/MootoolsEngineHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/MootoolsEngineHelper.php new file mode 100644 index 0000000..3919754 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/MootoolsEngineHelper.php @@ -0,0 +1,376 @@ +<?php +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('JsBaseEngineHelper', 'View/Helper'); + +/** + * MooTools Engine Helper for JsHelper + * + * Provides MooTools specific Javascript for JsHelper. + * Assumes that you have the following MooTools packages + * + * - Remote, Remote.HTML, Remote.JSON + * - Fx, Fx.Tween, Fx.Morph + * - Selectors, DomReady, + * - Drag, Drag.Move + * + * @package Cake.View.Helper + */ +class MootoolsEngineHelper extends JsBaseEngineHelper { + +/** + * Option mappings for MooTools + * + * @var array + */ + protected $_optionMap = array( + 'request' => array( + 'complete' => 'onComplete', + 'success' => 'onSuccess', + 'before' => 'onRequest', + 'error' => 'onFailure' + ), + 'sortable' => array( + 'distance' => 'snap', + 'containment' => 'constrain', + 'sort' => 'onSort', + 'complete' => 'onComplete', + 'start' => 'onStart', + ), + 'drag' => array( + 'snapGrid' => 'snap', + 'start' => 'onStart', + 'drag' => 'onDrag', + 'stop' => 'onComplete', + ), + 'drop' => array( + 'drop' => 'onDrop', + 'hover' => 'onEnter', + 'leave' => 'onLeave', + ), + 'slider' => array( + 'complete' => 'onComplete', + 'change' => 'onChange', + 'direction' => 'mode', + 'step' => 'steps' + ) + ); + +/** + * Contains a list of callback names -> default arguments. + * + * @var array + */ + protected $_callbackArguments = array( + 'slider' => array( + 'onTick' => 'position', + 'onChange' => 'step', + 'onComplete' => 'event' + ), + 'request' => array( + 'onRequest' => '', + 'onComplete' => '', + 'onCancel' => '', + 'onSuccess' => 'responseText, responseXML', + 'onFailure' => 'xhr', + 'onException' => 'headerName, value', + ), + 'drag' => array( + 'onBeforeStart' => 'element', + 'onStart' => 'element', + 'onSnap' => 'element', + 'onDrag' => 'element, event', + 'onComplete' => 'element, event', + 'onCancel' => 'element', + ), + 'drop' => array( + 'onBeforeStart' => 'element', + 'onStart' => 'element', + 'onSnap' => 'element', + 'onDrag' => 'element, event', + 'onComplete' => 'element, event', + 'onCancel' => 'element', + 'onDrop' => 'element, droppable, event', + 'onLeave' => 'element, droppable', + 'onEnter' => 'element, droppable', + ), + 'sortable' => array( + 'onStart' => 'element, clone', + 'onSort' => 'element, clone', + 'onComplete' => 'element', + ) + ); + +/** + * Create javascript selector for a CSS rule + * + * @param string $selector The selector that is targeted + * @return MootoolsEngineHelper instance of $this. Allows chained methods. + */ + public function get($selector) { + $this->_multipleSelection = false; + if ($selector == 'window' || $selector == 'document') { + $this->selection = "$(" . $selector . ")"; + return $this; + } + if (preg_match('/^#[^\s.]+$/', $selector)) { + $this->selection = '$("' . substr($selector, 1) . '")'; + return $this; + } + $this->_multipleSelection = true; + $this->selection = '$$("' . $selector . '")'; + return $this; + } + +/** + * Add an event to the script cache. Operates on the currently selected elements. + * + * ### Options + * + * - 'wrap' - Whether you want the callback wrapped in an anonymous function. (defaults true) + * - 'stop' - Whether you want the event to stopped. (defaults true) + * + * @param string $type Type of event to bind to the current dom id + * @param string $callback The Javascript function you wish to trigger or the function literal + * @param array $options Options for the event. + * @return string completed event handler + */ + public function event($type, $callback, $options = array()) { + $defaults = array('wrap' => true, 'stop' => true); + $options = array_merge($defaults, $options); + + $function = 'function (event) {%s}'; + if ($options['wrap'] && $options['stop']) { + $callback = "event.stop();\n" . $callback; + } + if ($options['wrap']) { + $callback = sprintf($function, $callback); + } + $out = $this->selection . ".addEvent(\"{$type}\", $callback);"; + return $out; + } + +/** + * Create a domReady event. This is a special event in many libraries + * + * @param string $functionBody The code to run on domReady + * @return string completed domReady method + */ + public function domReady($functionBody) { + $this->selection = 'window'; + return $this->event('domready', $functionBody, array('stop' => false)); + } + +/** + * Create an iteration over the current selection result. + * + * @param string $callback The function body you wish to apply during the iteration. + * @return string completed iteration + */ + public function each($callback) { + return $this->selection . '.each(function (item, index) {' . $callback . '});'; + } + +/** + * Trigger an Effect. + * + * @param string $name The name of the effect to trigger. + * @param array $options Array of options for the effect. + * @return string completed string with effect. + * @see JsBaseEngineHelper::effect() + */ + public function effect($name, $options = array()) { + $speed = null; + if (isset($options['speed']) && in_array($options['speed'], array('fast', 'slow'))) { + if ($options['speed'] == 'fast') { + $speed = '"short"'; + } elseif ($options['speed'] == 'slow') { + $speed = '"long"'; + } + } + $effect = ''; + switch ($name) { + case 'hide': + $effect = 'setStyle("display", "none")'; + break; + case 'show': + $effect = 'setStyle("display", "")'; + break; + case 'fadeIn': + case 'fadeOut': + case 'slideIn': + case 'slideOut': + list($effectName, $direction) = preg_split('/([A-Z][a-z]+)/', $name, -1, PREG_SPLIT_DELIM_CAPTURE); + $direction = strtolower($direction); + if ($speed) { + $effect .= "set(\"$effectName\", {duration:$speed})."; + } + $effect .= "$effectName(\"$direction\")"; + break; + } + return $this->selection . '.' . $effect . ';'; + } + +/** + * Create an new Request. + * + * Requires `Request`. If you wish to use 'update' key you must have ```Request.HTML``` + * if you wish to do Json requests you will need ```JSON``` and ```Request.JSON```. + * + * @param string|array $url + * @param array $options + * @return string The completed ajax call. + */ + public function request($url, $options = array()) { + $url = $this->url($url); + $options = $this->_mapOptions('request', $options); + $type = $data = null; + if (isset($options['type']) || isset($options['update'])) { + if (isset($options['type']) && strtolower($options['type']) == 'json') { + $type = '.JSON'; + } + if (isset($options['update'])) { + $options['update'] = str_replace('#', '', $options['update']); + $type = '.HTML'; + } + unset($options['type']); + } + if (!empty($options['data'])) { + $data = $options['data']; + unset($options['data']); + } + $options['url'] = $url; + $options = $this->_prepareCallbacks('request', $options); + if (!empty($options['dataExpression'])) { + $callbacks[] = 'data'; + unset($options['dataExpression']); + } elseif (!empty($data)) { + $data = $this->object($data); + } + $options = $this->_parseOptions($options, array_keys($this->_callbackArguments['request'])); + return "var jsRequest = new Request$type({{$options}}).send($data);"; + } + +/** + * Create a sortable element. + * + * Requires the `Sortables` plugin from MootoolsMore + * + * @param array $options Array of options for the sortable. + * @return string Completed sortable script. + * @see JsBaseEngineHelper::sortable() for options list. + */ + public function sortable($options = array()) { + $options = $this->_processOptions('sortable', $options); + return 'var jsSortable = new Sortables(' . $this->selection . ', {' . $options . '});'; + } + +/** + * Create a Draggable element. + * + * Requires the `Drag` plugin from MootoolsMore + * + * @param array $options Array of options for the draggable. + * @return string Completed draggable script. + * @see JsHelper::drag() for options list. + */ + public function drag($options = array()) { + $options = $this->_processOptions('drag', $options); + return $this->selection . '.makeDraggable({' . $options . '});'; + } + +/** + * Create a Droppable element. + * + * Requires the `Drag` and `Drag.Move` plugins from MootoolsMore + * + * Droppables in Mootools function differently from other libraries. Droppables + * are implemented as an extension of Drag. So in addition to making a get() selection for + * the droppable element. You must also provide a selector rule to the draggable element. Furthermore, + * Mootools droppables inherit all options from Drag. + * + * @param array $options Array of options for the droppable. + * @return string Completed droppable script. + * @see JsBaseEngineHelper::drop() for options list. + */ + public function drop($options = array()) { + if (empty($options['drag'])) { + trigger_error( + __d('cake_dev', 'MootoolsEngine::drop() requires a "drag" option to properly function'), E_USER_WARNING + ); + return false; + } + $options['droppables'] = $this->selection; + + $this->get($options['drag']); + unset($options['drag']); + + $options = $this->_mapOptions('drag', $this->_mapOptions('drop', $options)); + $options = $this->_prepareCallbacks('drop', $options); + $safe = array_merge(array_keys($this->_callbackArguments['drop']), array('droppables')); + $optionString = $this->_parseOptions($options, $safe); + $out = $this->selection . '.makeDraggable({' . $optionString . '});'; + $this->selection = $options['droppables']; + return $out; + } + +/** + * Create a slider control + * + * Requires `Slider` from MootoolsMore + * + * @param array $options Array of options for the slider. + * @return string Completed slider script. + * @see JsBaseEngineHelper::slider() for options list. + */ + public function slider($options = array()) { + $slider = $this->selection; + $this->get($options['handle']); + unset($options['handle']); + + if (isset($options['min']) && isset($options['max'])) { + $options['range'] = array($options['min'], $options['max']); + unset($options['min'], $options['max']); + } + $optionString = $this->_processOptions('slider', $options); + if (!empty($optionString)) { + $optionString = ', {' . $optionString . '}'; + } + $out = 'var jsSlider = new Slider(' . $slider . ', ' . $this->selection . $optionString . ');'; + $this->selection = $slider; + return $out; + } + +/** + * Serialize the form attached to $selector. + * + * @param array $options Array of options. + * @return string Completed serializeForm() snippet + * @see JsBaseEngineHelper::serializeForm() + */ + public function serializeForm($options = array()) { + $options = array_merge(array('isForm' => false, 'inline' => false), $options); + $selection = $this->selection; + if (!$options['isForm']) { + $selection = '$(' . $this->selection . '.form)'; + } + $method = '.toQueryString()'; + if (!$options['inline']) { + $method .= ';'; + } + return $selection . $method; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/NumberHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/NumberHelper.php new file mode 100644 index 0000000..5889484 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/NumberHelper.php @@ -0,0 +1,149 @@ +<?php +/** + * Number Helper. + * + * Methods to make numbers more readable. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('CakeNumber', 'Utility'); +App::uses('AppHelper', 'View/Helper'); + +/** + * Number helper library. + * + * Methods to make numbers more readable. + * + * @package Cake.View.Helper + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html + * @see CakeNumber + */ +class NumberHelper extends AppHelper { + +/** + * CakeNumber instance + * + * @var CakeNumber + */ + protected $_engine = null; + +/** + * Default Constructor + * + * ### Settings: + * + * - `engine` Class name to use to replace CakeNumber functionality + * The class needs to be placed in the `Utility` directory. + * + * @param View $View The View this helper is being attached to. + * @param array $settings Configuration settings for the helper + * @throws CakeException When the engine class could not be found. + */ + public function __construct(View $View, $settings = array()) { + $settings = Hash::merge(array('engine' => 'CakeNumber'), $settings); + parent::__construct($View, $settings); + list($plugin, $engineClass) = pluginSplit($settings['engine'], true); + App::uses($engineClass, $plugin . 'Utility'); + if (class_exists($engineClass)) { + $this->_engine = new $engineClass($settings); + } else { + throw new CakeException(__d('cake_dev', '%s could not be found', $engineClass)); + } + } + +/** + * Call methods from CakeNumber utility class + */ + public function __call($method, $params) { + return call_user_func_array(array($this->_engine, $method), $params); + } + +/** + * @see: CakeNumber::precision() + * + * @param float $number A floating point number. + * @param integer $precision The precision of the returned number. + * @return float Formatted float. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::precision + */ + public function precision($number, $precision = 3) { + return $this->_engine->precision($number, $precision); + } + +/** + * @see: CakeNumber::toReadableSize() + * + * @param integer $size Size in bytes + * @return string Human readable size + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toReadableSize + */ + public function toReadableSize($size) { + return $this->_engine->toReadableSize($size); + } + +/** + * @see: CakeNumber::toPercentage() + * + * @param float $number A floating point number + * @param integer $precision The precision of the returned number + * @return string Percentage string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toPercentage + */ + public function toPercentage($number, $precision = 2) { + return $this->_engine->toPercentage($number, $precision); + } + +/** + * @see: CakeNumber::format() + * + * @param float $number A floating point number + * @param integer $options if int then places, if string then before, if (,.-) then use it + * or array with places and before keys + * @return string formatted number + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::format + */ + public function format($number, $options = false) { + return $this->_engine->format($number, $options); + } + +/** + * @see: CakeNumber::currency() + * + * @param float $number + * @param string $currency Shortcut to default options. Valid values are 'USD', 'EUR', 'GBP', otherwise + * set at least 'before' and 'after' options. + * @param array $options + * @return string Number formatted as a currency. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::currency + */ + public function currency($number, $currency = 'USD', $options = array()) { + return $this->_engine->currency($number, $currency, $options); + } + +/** + * @see: CakeNumber::addFormat() + * + * @param string $formatName The format name to be used in the future. + * @param array $options The array of options for this format. + * @return void + * @see NumberHelper::currency() + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::addFormat + */ + public function addFormat($formatName, $options) { + return $this->_engine->addFormat($formatName, $options); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PaginatorHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PaginatorHelper.php new file mode 100644 index 0000000..05a9935 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PaginatorHelper.php @@ -0,0 +1,901 @@ +<?php +/** + * Pagination Helper class file. + * + * Generates pagination links + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); + +/** + * Pagination Helper class for easy generation of pagination links. + * + * PaginationHelper encloses all methods needed when working with pagination. + * + * @package Cake.View.Helper + * @property HtmlHelper $Html + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html + */ +class PaginatorHelper extends AppHelper { + +/** + * Helper dependencies + * + * @var array + */ + public $helpers = array('Html'); + +/** + * The class used for 'Ajax' pagination links. Defaults to JsHelper. You should make sure + * that JsHelper is defined as a helper before PaginatorHelper, if you want to customize the JsHelper. + * + * @var string + */ + protected $_ajaxHelperClass = 'Js'; + +/** + * Holds the default options for pagination links + * + * The values that may be specified are: + * + * - `format` Format of the counter. Supported formats are 'range' and 'pages' + * and custom (default). In the default mode the supplied string is parsed and constants are replaced + * by their actual values. + * placeholders: %page%, %pages%, %current%, %count%, %start%, %end% . + * - `separator` The separator of the actual page and number of pages (default: ' of '). + * - `url` Url of the action. See Router::url() + * - `url['sort']` the key that the recordset is sorted. + * - `url['direction']` Direction of the sorting (default: 'asc'). + * - `url['page']` Page number to use in links. + * - `model` The name of the model. + * - `escape` Defines if the title field for the link should be escaped (default: true). + * - `update` DOM id of the element updated with the results of the AJAX call. + * If this key isn't specified Paginator will use plain HTML links. + * - `paging['paramType']` The type of parameters to use when creating links. Valid options are + * 'querystring' and 'named'. See PaginatorComponent::$settings for more information. + * - `convertKeys` - A list of keys in url arrays that should be converted to querysting params + * if paramType == 'querystring'. + * + * @var array + */ + public $options = array( + 'convertKeys' => array('page', 'limit', 'sort', 'direction') + ); + +/** + * Constructor for the helper. Sets up the helper that is used for creating 'AJAX' links. + * + * Use `public $helpers = array('Paginator' => array('ajax' => 'CustomHelper'));` to set a custom Helper + * or choose a non JsHelper Helper. If you want to use a specific library with JsHelper declare JsHelper and its + * adapter before including PaginatorHelper in your helpers array. + * + * The chosen custom helper must implement a `link()` method. + * + * @param View $View the view object the helper is attached to. + * @param array $settings Array of settings. + * @throws CakeException When the AjaxProvider helper does not implement a link method. + */ + public function __construct(View $View, $settings = array()) { + $ajaxProvider = isset($settings['ajax']) ? $settings['ajax'] : 'Js'; + $this->helpers[] = $ajaxProvider; + $this->_ajaxHelperClass = $ajaxProvider; + App::uses($ajaxProvider . 'Helper', 'View/Helper'); + $classname = $ajaxProvider . 'Helper'; + if (!class_exists($classname) || !method_exists($classname, 'link')) { + throw new CakeException(sprintf( + __d('cake_dev', '%s does not implement a link() method, it is incompatible with PaginatorHelper'), $classname + )); + } + parent::__construct($View, $settings); + } + +/** + * Before render callback. Overridden to merge passed args with url options. + * + * @param string $viewFile + * @return void + */ + public function beforeRender($viewFile) { + $this->options['url'] = array_merge($this->request->params['pass'], $this->request->params['named']); + if (!empty($this->request->query)) { + $this->options['url']['?'] = $this->request->query; + } + parent::beforeRender($viewFile); + } + +/** + * Gets the current paging parameters from the resultset for the given model + * + * @param string $model Optional model name. Uses the default if none is specified. + * @return array The array of paging parameters for the paginated resultset. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::params + */ + public function params($model = null) { + if (empty($model)) { + $model = $this->defaultModel(); + } + if (!isset($this->request->params['paging']) || empty($this->request->params['paging'][$model])) { + return null; + } + return $this->request->params['paging'][$model]; + } + +/** + * Sets default options for all pagination links + * + * @param array|string $options Default options for pagination links. If a string is supplied - it + * is used as the DOM id element to update. See PaginatorHelper::$options for list of keys. + * @return void + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::options + */ + public function options($options = array()) { + if (is_string($options)) { + $options = array('update' => $options); + } + + if (!empty($options['paging'])) { + if (!isset($this->request->params['paging'])) { + $this->request->params['paging'] = array(); + } + $this->request->params['paging'] = array_merge($this->request->params['paging'], $options['paging']); + unset($options['paging']); + } + $model = $this->defaultModel(); + + if (!empty($options[$model])) { + if (!isset($this->request->params['paging'][$model])) { + $this->request->params['paging'][$model] = array(); + } + $this->request->params['paging'][$model] = array_merge( + $this->request->params['paging'][$model], $options[$model] + ); + unset($options[$model]); + } + if (!empty($options['convertKeys'])) { + $options['convertKeys'] = array_merge($this->options['convertKeys'], $options['convertKeys']); + } + $this->options = array_filter(array_merge($this->options, $options)); + } + +/** + * Gets the current page of the recordset for the given model + * + * @param string $model Optional model name. Uses the default if none is specified. + * @return string The current page number of the recordset. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::current + */ + public function current($model = null) { + $params = $this->params($model); + + if (isset($params['page'])) { + return $params['page']; + } + return 1; + } + +/** + * Gets the current key by which the recordset is sorted + * + * @param string $model Optional model name. Uses the default if none is specified. + * @param array $options Options for pagination links. See #options for list of keys. + * @return string The name of the key by which the recordset is being sorted, or + * null if the results are not currently sorted. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::sortKey + */ + public function sortKey($model = null, $options = array()) { + if (empty($options)) { + $params = $this->params($model); + $options = $params['options']; + } + if (isset($options['sort']) && !empty($options['sort'])) { + return $options['sort']; + } + if (isset($options['order'])) { + return is_array($options['order']) ? key($options['order']) : $options['order']; + } + if (isset($params['order'])) { + return is_array($params['order']) ? key($params['order']) : $params['order']; + } + return null; + } + +/** + * Gets the current direction the recordset is sorted + * + * @param string $model Optional model name. Uses the default if none is specified. + * @param array $options Options for pagination links. See #options for list of keys. + * @return string The direction by which the recordset is being sorted, or + * null if the results are not currently sorted. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::sortDir + */ + public function sortDir($model = null, $options = array()) { + $dir = null; + + if (empty($options)) { + $params = $this->params($model); + $options = $params['options']; + } + + if (isset($options['direction'])) { + $dir = strtolower($options['direction']); + } elseif (isset($options['order']) && is_array($options['order'])) { + $dir = strtolower(current($options['order'])); + } elseif (isset($params['order']) && is_array($params['order'])) { + $dir = strtolower(current($params['order'])); + } + + if ($dir == 'desc') { + return 'desc'; + } + return 'asc'; + } + +/** + * Generates a "previous" link for a set of paged records + * + * ### Options: + * + * - `tag` The tag wrapping tag you want to use, defaults to 'span' + * - `escape` Whether you want the contents html entity encoded, defaults to true + * - `model` The model to use, defaults to PaginatorHelper::defaultModel() + * + * @param string $title Title for the link. Defaults to '<< Previous'. + * @param array $options Options for pagination link. See #options for list of keys. + * @param string $disabledTitle Title when the link is disabled. + * @param array $disabledOptions Options for the disabled pagination link. See #options for list of keys. + * @return string A "previous" link or $disabledTitle text if the link is disabled. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::prev + */ + public function prev($title = '<< Previous', $options = array(), $disabledTitle = null, $disabledOptions = array()) { + $defaults = array( + 'rel' => 'prev' + ); + $options = array_merge($defaults, (array)$options); + return $this->_pagingLink('Prev', $title, $options, $disabledTitle, $disabledOptions); + } + +/** + * Generates a "next" link for a set of paged records + * + * ### Options: + * + * - `tag` The tag wrapping tag you want to use, defaults to 'span' + * - `escape` Whether you want the contents html entity encoded, defaults to true + * - `model` The model to use, defaults to PaginatorHelper::defaultModel() + * + * @param string $title Title for the link. Defaults to 'Next >>'. + * @param array $options Options for pagination link. See above for list of keys. + * @param string $disabledTitle Title when the link is disabled. + * @param array $disabledOptions Options for the disabled pagination link. See above for list of keys. + * @return string A "next" link or or $disabledTitle text if the link is disabled. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::next + */ + public function next($title = 'Next >>', $options = array(), $disabledTitle = null, $disabledOptions = array()) { + $defaults = array( + 'rel' => 'next' + ); + $options = array_merge($defaults, (array)$options); + return $this->_pagingLink('Next', $title, $options, $disabledTitle, $disabledOptions); + } + +/** + * Generates a sorting link. Sets named parameters for the sort and direction. Handles + * direction switching automatically. + * + * ### Options: + * + * - `escape` Whether you want the contents html entity encoded, defaults to true + * - `model` The model to use, defaults to PaginatorHelper::defaultModel() + * - `direction` The default direction to use when this link isn't active. + * + * @param string $key The name of the key that the recordset should be sorted. + * @param string $title Title for the link. If $title is null $key will be used + * for the title and will be generated by inflection. + * @param array $options Options for sorting link. See above for list of keys. + * @return string A link sorting default by 'asc'. If the resultset is sorted 'asc' by the specified + * key the returned link will sort by 'desc'. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::sort + */ + public function sort($key, $title = null, $options = array()) { + $options = array_merge(array('url' => array(), 'model' => null), $options); + $url = $options['url']; + unset($options['url']); + + if (empty($title)) { + $title = $key; + $title = __(Inflector::humanize(preg_replace('/_id$/', '', $title))); + } + $dir = isset($options['direction']) ? $options['direction'] : 'asc'; + unset($options['direction']); + + $sortKey = $this->sortKey($options['model']); + $defaultModel = $this->defaultModel(); + $isSorted = ( + $sortKey === $key || + $sortKey === $defaultModel . '.' . $key || + $key === $defaultModel . '.' . $sortKey + ); + + if ($isSorted) { + $dir = $this->sortDir($options['model']) === 'asc' ? 'desc' : 'asc'; + $class = $dir === 'asc' ? 'desc' : 'asc'; + if (!empty($options['class'])) { + $options['class'] .= ' ' . $class; + } else { + $options['class'] = $class; + } + } + if (is_array($title) && array_key_exists($dir, $title)) { + $title = $title[$dir]; + } + + $url = array_merge(array('sort' => $key, 'direction' => $dir), $url, array('order' => null)); + return $this->link($title, $url, $options); + } + +/** + * Generates a plain or Ajax link with pagination parameters + * + * ### Options + * + * - `update` The Id of the DOM element you wish to update. Creates Ajax enabled links + * with the AjaxHelper. + * - `escape` Whether you want the contents html entity encoded, defaults to true + * - `model` The model to use, defaults to PaginatorHelper::defaultModel() + * + * @param string $title Title for the link. + * @param string|array $url Url for the action. See Router::url() + * @param array $options Options for the link. See #options for list of keys. + * @return string A link with pagination parameters. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::link + */ + public function link($title, $url = array(), $options = array()) { + $options = array_merge(array('model' => null, 'escape' => true), $options); + $model = $options['model']; + unset($options['model']); + + if (!empty($this->options)) { + $options = array_merge($this->options, $options); + } + if (isset($options['url'])) { + $url = array_merge((array)$options['url'], (array)$url); + unset($options['url']); + } + unset($options['convertKeys']); + + $url = $this->url($url, true, $model); + + $obj = isset($options['update']) ? $this->_ajaxHelperClass : 'Html'; + return $this->{$obj}->link($title, $url, $options); + } + +/** + * Merges passed URL options with current pagination state to generate a pagination URL. + * + * @param array $options Pagination/URL options array + * @param boolean $asArray Return the url as an array, or a URI string + * @param string $model Which model to paginate on + * @return mixed By default, returns a full pagination URL string for use in non-standard contexts (i.e. JavaScript) + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::url + */ + public function url($options = array(), $asArray = false, $model = null) { + $paging = $this->params($model); + $url = array_merge(array_filter($paging['options']), $options); + + if (isset($url['order'])) { + $sort = $direction = null; + if (is_array($url['order'])) { + list($sort, $direction) = array($this->sortKey($model, $url), current($url['order'])); + } + unset($url['order']); + $url = array_merge($url, compact('sort', 'direction')); + } + $url = $this->_convertUrlKeys($url, $paging['paramType']); + + if ($asArray) { + return $url; + } + return parent::url($url); + } + +/** + * Converts the keys being used into the format set by options.paramType + * + * @param array $url Array of url params to convert + * @param string $type + * @return array converted url params. + */ + protected function _convertUrlKeys($url, $type) { + if ($type == 'named') { + return $url; + } + if (!isset($url['?'])) { + $url['?'] = array(); + } + foreach ($this->options['convertKeys'] as $key) { + if (isset($url[$key])) { + $url['?'][$key] = $url[$key]; + unset($url[$key]); + } + } + return $url; + } + +/** + * Protected method for generating prev/next links + * + * @param string $which + * @param string $title + * @param array $options + * @param string $disabledTitle + * @param array $disabledOptions + * @return string + */ + protected function _pagingLink($which, $title = null, $options = array(), $disabledTitle = null, $disabledOptions = array()) { + $check = 'has' . $which; + $_defaults = array( + 'url' => array(), 'step' => 1, 'escape' => true, + 'model' => null, 'tag' => 'span', 'class' => strtolower($which) + ); + $options = array_merge($_defaults, (array)$options); + $paging = $this->params($options['model']); + if (empty($disabledOptions)) { + $disabledOptions = $options; + } + + if (!$this->{$check}($options['model']) && (!empty($disabledTitle) || !empty($disabledOptions))) { + if (!empty($disabledTitle) && $disabledTitle !== true) { + $title = $disabledTitle; + } + $options = array_merge($_defaults, (array)$disabledOptions); + } elseif (!$this->{$check}($options['model'])) { + return null; + } + + foreach (array_keys($_defaults) as $key) { + ${$key} = $options[$key]; + unset($options[$key]); + } + $url = array_merge(array('page' => $paging['page'] + ($which == 'Prev' ? $step * -1 : $step)), $url); + + if ($this->{$check}($model)) { + return $this->Html->tag($tag, $this->link($title, $url, array_merge($options, compact('escape'))), compact('class')); + } else { + unset($options['rel']); + return $this->Html->tag($tag, $title, array_merge($options, compact('escape', 'class'))); + } + } + +/** + * Returns true if the given result set is not at the first page + * + * @param string $model Optional model name. Uses the default if none is specified. + * @return boolean True if the result set is not at the first page. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::hasPrev + */ + public function hasPrev($model = null) { + return $this->_hasPage($model, 'prev'); + } + +/** + * Returns true if the given result set is not at the last page + * + * @param string $model Optional model name. Uses the default if none is specified. + * @return boolean True if the result set is not at the last page. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::hasNext + */ + public function hasNext($model = null) { + return $this->_hasPage($model, 'next'); + } + +/** + * Returns true if the given result set has the page number given by $page + * + * @param string $model Optional model name. Uses the default if none is specified. + * @param integer $page The page number - if not set defaults to 1. + * @return boolean True if the given result set has the specified page number. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::hasPage + */ + public function hasPage($model = null, $page = 1) { + if (is_numeric($model)) { + $page = $model; + $model = null; + } + $paging = $this->params($model); + return $page <= $paging['pageCount']; + } + +/** + * Does $model have $page in its range? + * + * @param string $model Model name to get parameters for. + * @param integer $page Page number you are checking. + * @return boolean Whether model has $page + */ + protected function _hasPage($model, $page) { + $params = $this->params($model); + if (!empty($params)) { + if ($params["{$page}Page"] == true) { + return true; + } + } + return false; + } + +/** + * Gets the default model of the paged sets + * + * @return string Model name or null if the pagination isn't initialized. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::defaultModel + */ + public function defaultModel() { + if ($this->_defaultModel != null) { + return $this->_defaultModel; + } + if (empty($this->request->params['paging'])) { + return null; + } + list($this->_defaultModel) = array_keys($this->request->params['paging']); + return $this->_defaultModel; + } + +/** + * Returns a counter string for the paged result set + * + * ### Options + * + * - `model` The model to use, defaults to PaginatorHelper::defaultModel(); + * - `format` The format string you want to use, defaults to 'pages' Which generates output like '1 of 5' + * set to 'range' to generate output like '1 - 3 of 13'. Can also be set to a custom string, containing + * the following placeholders `{:page}`, `{:pages}`, `{:current}`, `{:count}`, `{:model}`, `{:start}`, `{:end}` and any + * custom content you would like. + * - `separator` The separator string to use, default to ' of ' + * + * The `%page%` style placeholders also work, but are deprecated and will be removed in a future version. + * @param array $options Options for the counter string. See #options for list of keys. + * @return string Counter string. + * @deprecated The %page% style placeholders are deprecated. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::counter + */ + public function counter($options = array()) { + if (is_string($options)) { + $options = array('format' => $options); + } + + $options = array_merge( + array( + 'model' => $this->defaultModel(), + 'format' => 'pages', + 'separator' => __d('cake', ' of ') + ), + $options); + + $paging = $this->params($options['model']); + if ($paging['pageCount'] == 0) { + $paging['pageCount'] = 1; + } + $start = 0; + if ($paging['count'] >= 1) { + $start = (($paging['page'] - 1) * $paging['limit']) + 1; + } + $end = $start + $paging['limit'] - 1; + if ($paging['count'] < $end) { + $end = $paging['count']; + } + + switch ($options['format']) { + case 'range': + if (!is_array($options['separator'])) { + $options['separator'] = array(' - ', $options['separator']); + } + $out = $start . $options['separator'][0] . $end . $options['separator'][1]; + $out .= $paging['count']; + break; + case 'pages': + $out = $paging['page'] . $options['separator'] . $paging['pageCount']; + break; + default: + $map = array( + '%page%' => $paging['page'], + '%pages%' => $paging['pageCount'], + '%current%' => $paging['current'], + '%count%' => $paging['count'], + '%start%' => $start, + '%end%' => $end, + '%model%' => strtolower(Inflector::humanize(Inflector::tableize($options['model']))) + ); + $out = str_replace(array_keys($map), array_values($map), $options['format']); + + $newKeys = array( + '{:page}', '{:pages}', '{:current}', '{:count}', '{:start}', '{:end}', '{:model}' + ); + $out = str_replace($newKeys, array_values($map), $out); + break; + } + return $out; + } + +/** + * Returns a set of numbers for the paged result set + * uses a modulus to decide how many numbers to show on each side of the current page (default: 8). + * + * `$this->Paginator->numbers(array('first' => 2, 'last' => 2));` + * + * Using the first and last options you can create links to the beginning and end of the page set. + * + * ### Options + * + * - `before` Content to be inserted before the numbers + * - `after` Content to be inserted after the numbers + * - `model` Model to create numbers for, defaults to PaginatorHelper::defaultModel() + * - `modulus` how many numbers to include on either side of the current page, defaults to 8. + * - `separator` Separator content defaults to ' | ' + * - `tag` The tag to wrap links in, defaults to 'span' + * - `first` Whether you want first links generated, set to an integer to define the number of 'first' + * links to generate. + * - `last` Whether you want last links generated, set to an integer to define the number of 'last' + * links to generate. + * - `ellipsis` Ellipsis content, defaults to '...' + * - `class` Class for wrapper tag + * - `currentClass` Class for wrapper tag on current active page, defaults to 'current' + * + * @param array $options Options for the numbers, (before, after, model, modulus, separator) + * @return string numbers string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::numbers + */ + public function numbers($options = array()) { + if ($options === true) { + $options = array( + 'before' => ' | ', 'after' => ' | ', 'first' => 'first', 'last' => 'last' + ); + } + + $defaults = array( + 'tag' => 'span', 'before' => null, 'after' => null, 'model' => $this->defaultModel(), 'class' => null, + 'modulus' => '8', 'separator' => ' | ', 'first' => null, 'last' => null, 'ellipsis' => '...', 'currentClass' => 'current' + ); + $options += $defaults; + + $params = (array)$this->params($options['model']) + array('page' => 1); + unset($options['model']); + + if ($params['pageCount'] <= 1) { + return false; + } + + extract($options); + unset($options['tag'], $options['before'], $options['after'], $options['model'], + $options['modulus'], $options['separator'], $options['first'], $options['last'], + $options['ellipsis'], $options['class'], $options['currentClass'] + ); + + $out = ''; + + if ($modulus && $params['pageCount'] > $modulus) { + $half = intval($modulus / 2); + $end = $params['page'] + $half; + + if ($end > $params['pageCount']) { + $end = $params['pageCount']; + } + $start = $params['page'] - ($modulus - ($end - $params['page'])); + if ($start <= 1) { + $start = 1; + $end = $params['page'] + ($modulus - $params['page']) + 1; + } + + if ($first && $start > 1) { + $offset = ($start <= (int)$first) ? $start - 1 : $first; + if ($offset < $start - 1) { + $out .= $this->first($offset, compact('tag', 'separator', 'ellipsis', 'class')); + } else { + $out .= $this->first($offset, compact('tag', 'separator', 'class', 'ellipsis') + array('after' => $separator)); + } + } + + $out .= $before; + + for ($i = $start; $i < $params['page']; $i++) { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')) . $separator; + } + + if ($class) { + $currentClass .= ' ' . $class; + } + $out .= $this->Html->tag($tag, $params['page'], array('class' => $currentClass)); + if ($i != $params['pageCount']) { + $out .= $separator; + } + + $start = $params['page'] + 1; + for ($i = $start; $i < $end; $i++) { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')) . $separator; + } + + if ($end != $params['page']) { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $end), $options), compact('class')); + } + + $out .= $after; + + if ($last && $end < $params['pageCount']) { + $offset = ($params['pageCount'] < $end + (int)$last) ? $params['pageCount'] - $end : $last; + if ($offset <= $last && $params['pageCount'] - $end > $offset) { + $out .= $this->last($offset, compact('tag', 'separator', 'ellipsis', 'class')); + } else { + $out .= $this->last($offset, compact('tag', 'separator', 'class', 'ellipsis') + array('before' => $separator)); + } + } + + } else { + $out .= $before; + + for ($i = 1; $i <= $params['pageCount']; $i++) { + if ($i == $params['page']) { + if ($class) { + $currentClass .= ' ' . $class; + } + $out .= $this->Html->tag($tag, $i, array('class' => $currentClass)); + } else { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')); + } + if ($i != $params['pageCount']) { + $out .= $separator; + } + } + + $out .= $after; + } + + return $out; + } + +/** + * Returns a first or set of numbers for the first pages. + * + * `echo $this->Paginator->first('< first');` + * + * Creates a single link for the first page. Will output nothing if you are on the first page. + * + * `echo $this->Paginator->first(3);` + * + * Will create links for the first 3 pages, once you get to the third or greater page. Prior to that + * nothing will be output. + * + * ### Options: + * + * - `tag` The tag wrapping tag you want to use, defaults to 'span' + * - `after` Content to insert after the link/tag + * - `model` The model to use defaults to PaginatorHelper::defaultModel() + * - `separator` Content between the generated links, defaults to ' | ' + * - `ellipsis` Content for ellipsis, defaults to '...' + * + * @param string|integer $first if string use as label for the link. If numeric, the number of page links + * you want at the beginning of the range. + * @param array $options An array of options. + * @return string numbers string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::first + */ + public function first($first = '<< first', $options = array()) { + $options = array_merge( + array( + 'tag' => 'span', + 'after' => null, + 'model' => $this->defaultModel(), + 'separator' => ' | ', + 'ellipsis' => '...', + 'class' => null + ), + (array)$options); + + $params = array_merge(array('page' => 1), (array)$this->params($options['model'])); + unset($options['model']); + + if ($params['pageCount'] <= 1) { + return false; + } + extract($options); + unset($options['tag'], $options['after'], $options['model'], $options['separator'], $options['ellipsis'], $options['class']); + + $out = ''; + + if (is_int($first) && $params['page'] >= $first) { + if ($after === null) { + $after = $ellipsis; + } + for ($i = 1; $i <= $first; $i++) { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')); + if ($i != $first) { + $out .= $separator; + } + } + $out .= $after; + } elseif ($params['page'] > 1 && is_string($first)) { + $options += array('rel' => 'first'); + $out = $this->Html->tag($tag, $this->link($first, array('page' => 1), $options), compact('class')) . $after; + } + return $out; + } + +/** + * Returns a last or set of numbers for the last pages. + * + * `echo $this->Paginator->last('last >');` + * + * Creates a single link for the last page. Will output nothing if you are on the last page. + * + * `echo $this->Paginator->last(3);` + * + * Will create links for the last 3 pages. Once you enter the page range, no output will be created. + * + * ### Options: + * + * - `tag` The tag wrapping tag you want to use, defaults to 'span' + * - `before` Content to insert before the link/tag + * - `model` The model to use defaults to PaginatorHelper::defaultModel() + * - `separator` Content between the generated links, defaults to ' | ' + * - `ellipsis` Content for ellipsis, defaults to '...' + * + * @param string|integer $last if string use as label for the link, if numeric print page numbers + * @param array $options Array of options + * @return string numbers string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#PaginatorHelper::last + */ + public function last($last = 'last >>', $options = array()) { + $options = array_merge( + array( + 'tag' => 'span', + 'before' => null, + 'model' => $this->defaultModel(), + 'separator' => ' | ', + 'ellipsis' => '...', + 'class' => null + ), + (array)$options); + + $params = array_merge(array('page' => 1), (array)$this->params($options['model'])); + unset($options['model']); + + if ($params['pageCount'] <= 1) { + return false; + } + + extract($options); + unset($options['tag'], $options['before'], $options['model'], $options['separator'], $options['ellipsis'], $options['class']); + + $out = ''; + $lower = $params['pageCount'] - $last + 1; + + if (is_int($last) && $params['page'] <= $lower) { + if ($before === null) { + $before = $ellipsis; + } + for ($i = $lower; $i <= $params['pageCount']; $i++) { + $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options), compact('class')); + if ($i != $params['pageCount']) { + $out .= $separator; + } + } + $out = $before . $out; + } elseif ($params['page'] < $params['pageCount'] && is_string($last)) { + $options += array('rel' => 'last'); + $out = $before . $this->Html->tag( + $tag, $this->link($last, array('page' => $params['pageCount']), $options), compact('class') + ); + } + return $out; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PrototypeEngineHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PrototypeEngineHelper.php new file mode 100644 index 0000000..c1feb6d --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PrototypeEngineHelper.php @@ -0,0 +1,370 @@ +<?php +/** + * Prototype Engine Helper for JsHelper + * + * Provides Prototype specific Javascript for JsHelper. Requires at least + * Prototype 1.6 + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.3 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('JsBaseEngineHelper', 'View/Helper'); + +/** + * Prototype Engine Helper for JsHelper + * + * Provides Prototype specific Javascript for JsHelper. Requires at least + * Prototype 1.6 + * + * @package Cake.View.Helper + */ +class PrototypeEngineHelper extends JsBaseEngineHelper { + +/** + * Is the current selection a multiple selection? or is it just a single element. + * + * @var boolean + */ + protected $_multiple = false; + +/** + * Option mappings for Prototype + * + * @var array + */ + protected $_optionMap = array( + 'request' => array( + 'async' => 'asynchronous', + 'data' => 'parameters', + 'before' => 'onCreate', + 'success' => 'onSuccess', + 'complete' => 'onComplete', + 'error' => 'onFailure' + ), + 'sortable' => array( + 'sort' => 'onChange', + 'complete' => 'onUpdate', + ), + 'drag' => array( + 'snapGrid' => 'snap', + 'container' => 'constraint', + 'stop' => 'onEnd', + 'start' => 'onStart', + 'drag' => 'onDrag', + ), + 'drop' => array( + 'hover' => 'onHover', + 'drop' => 'onDrop', + 'hoverClass' => 'hoverclass', + ), + 'slider' => array( + 'direction' => 'axis', + 'change' => 'onSlide', + 'complete' => 'onChange', + 'value' => 'sliderValue', + ) + ); + +/** + * Contains a list of callback names -> default arguments. + * + * @var array + */ + protected $_callbackArguments = array( + 'slider' => array( + 'onSlide' => 'value', + 'onChange' => 'value', + ), + 'drag' => array( + 'onStart' => 'event', + 'onDrag' => 'event', + 'change' => 'draggable', + 'onEnd' => 'event', + ), + 'drop' => array( + 'onHover' => 'draggable, droppable, event', + 'onDrop' => 'draggable, droppable, event', + ), + 'request' => array( + 'onCreate' => 'transport', + 'onComplete' => 'transport', + 'onFailure' => 'response, jsonHeader', + 'onRequest' => 'transport', + 'onSuccess' => 'response, jsonHeader' + ), + 'sortable' => array( + 'onStart' => 'element', + 'onChange' => 'element', + 'onUpdate' => 'element', + ), + ); + +/** + * Create javascript selector for a CSS rule + * + * @param string $selector The selector that is targeted + * @return PrototypeEngineHelper instance of $this. Allows chained methods. + */ + public function get($selector) { + $this->_multiple = false; + if ($selector == 'window' || $selector == 'document') { + $this->selection = "$(" . $selector . ")"; + return $this; + } + if (preg_match('/^#[^\s.]+$/', $selector)) { + $this->selection = '$("' . substr($selector, 1) . '")'; + return $this; + } + $this->_multiple = true; + $this->selection = '$$("' . $selector . '")'; + return $this; + } + +/** + * Add an event to the script cache. Operates on the currently selected elements. + * + * ### Options + * + * - `wrap` - Whether you want the callback wrapped in an anonymous function. (defaults true) + * - `stop` - Whether you want the event to stopped. (defaults true) + * + * @param string $type Type of event to bind to the current 946 id + * @param string $callback The Javascript function you wish to trigger or the function literal + * @param array $options Options for the event. + * @return string completed event handler + */ + public function event($type, $callback, $options = array()) { + $defaults = array('wrap' => true, 'stop' => true); + $options = array_merge($defaults, $options); + + $function = 'function (event) {%s}'; + if ($options['wrap'] && $options['stop']) { + $callback = "event.stop();\n" . $callback; + } + if ($options['wrap']) { + $callback = sprintf($function, $callback); + } + $out = $this->selection . ".observe(\"{$type}\", $callback);"; + return $out; + } + +/** + * Create a domReady event. This is a special event in many libraries + * + * @param string $functionBody The code to run on domReady + * @return string completed domReady method + */ + public function domReady($functionBody) { + $this->selection = 'document'; + return $this->event('dom:loaded', $functionBody, array('stop' => false)); + } + +/** + * Create an iteration over the current selection result. + * + * @param string $callback The function body you wish to apply during the iteration. + * @return string completed iteration + */ + public function each($callback) { + return $this->selection . '.each(function (item, index) {' . $callback . '});'; + } + +/** + * Trigger an Effect. + * + * ### Note: Effects require Scriptaculous to be loaded. + * + * @param string $name The name of the effect to trigger. + * @param array $options Array of options for the effect. + * @return string completed string with effect. + * @see JsBaseEngineHelper::effect() + */ + public function effect($name, $options = array()) { + $effect = ''; + $optionString = null; + if (isset($options['speed'])) { + if ($options['speed'] == 'fast') { + $options['duration'] = 0.5; + } elseif ($options['speed'] == 'slow') { + $options['duration'] = 2; + } else { + $options['duration'] = 1; + } + unset($options['speed']); + } + if (!empty($options)) { + $optionString = ', {' . $this->_parseOptions($options) . '}'; + } + switch ($name) { + case 'hide': + case 'show': + $effect = $this->selection . '.' . $name . '();'; + break; + case 'slideIn': + case 'slideOut': + $name = ($name == 'slideIn') ? 'slideDown' : 'slideUp'; + $effect = 'Effect.' . $name . '(' . $this->selection . $optionString . ');'; + break; + case 'fadeIn': + case 'fadeOut': + $name = ($name == 'fadeIn') ? 'appear' : 'fade'; + $effect = $this->selection . '.' . $name . '(' . substr($optionString, 2) . ');'; + break; + } + return $effect; + } + +/** + * Create an Ajax or Ajax.Updater call. + * + * @param string|array $url + * @param array $options + * @return string The completed ajax call. + */ + public function request($url, $options = array()) { + $url = '"' . $this->url($url) . '"'; + $options = $this->_mapOptions('request', $options); + $type = '.Request'; + $data = null; + if (isset($options['type']) && strtolower($options['type']) == 'json') { + unset($options['type']); + } + if (isset($options['update'])) { + $url = '"' . str_replace('#', '', $options['update']) . '", ' . $url; + $type = '.Updater'; + unset($options['update'], $options['type']); + } + $safe = array_keys($this->_callbackArguments['request']); + $options = $this->_prepareCallbacks('request', $options, $safe); + if (!empty($options['dataExpression'])) { + $safe[] = 'parameters'; + unset($options['dataExpression']); + } + $options = $this->_parseOptions($options, $safe); + if (!empty($options)) { + $options = ', {' . $options . '}'; + } + return "var jsRequest = new Ajax$type($url$options);"; + } + +/** + * Create a sortable element. + * + * #### Note: Requires scriptaculous to be loaded. + * + * The scriptaculous implementation of sortables does not support the 'start' + * and 'distance' options. + * + * @param array $options Array of options for the sortable. + * @return string Completed sortable script. + * @see JsBaseEngineHelper::sortable() for options list. + */ + public function sortable($options = array()) { + $options = $this->_processOptions('sortable', $options); + if (!empty($options)) { + $options = ', {' . $options . '}'; + } + return 'var jsSortable = Sortable.create(' . $this->selection . $options . ');'; + } + +/** + * Create a Draggable element. + * + * #### Note: Requires scriptaculous to be loaded. + * + * @param array $options Array of options for the draggable. + * @return string Completed draggable script. + * @see JsBaseEngineHelper::draggable() for options list. + */ + public function drag($options = array()) { + $options = $this->_processOptions('drag', $options); + if (!empty($options)) { + $options = ', {' . $options . '}'; + } + if ($this->_multiple) { + return $this->each('new Draggable(item' . $options . ');'); + } + return 'var jsDrag = new Draggable(' . $this->selection . $options . ');'; + } + +/** + * Create a Droppable element. + * + * #### Note: Requires scriptaculous to be loaded. + * + * @param array $options Array of options for the droppable. + * @return string Completed droppable script. + * @see JsBaseEngineHelper::droppable() for options list. + */ + public function drop($options = array()) { + $options = $this->_processOptions('drop', $options); + if (!empty($options)) { + $options = ', {' . $options . '}'; + } + return 'Droppables.add(' . $this->selection . $options . ');'; + } + +/** + * Creates a slider control widget. + * + * ### Note: Requires scriptaculous to be loaded. + * + * @param array $options Array of options for the slider. + * @return string Completed slider script. + * @see JsBaseEngineHelper::slider() for options list. + */ + public function slider($options = array()) { + $slider = $this->selection; + $this->get($options['handle']); + unset($options['handle']); + + if (isset($options['min']) && isset($options['max'])) { + $options['range'] = sprintf('$R(%s,%s)', $options['min'], $options['max']); + unset($options['min'], $options['max']); + } + $options = $this->_mapOptions('slider', $options); + $options = $this->_prepareCallbacks('slider', $options); + $optionString = $this->_parseOptions( + $options, array_merge(array_keys($this->_callbackArguments['slider']), array('range')) + ); + if (!empty($optionString)) { + $optionString = ', {' . $optionString . '}'; + } + $out = 'var jsSlider = new Control.Slider(' . $this->selection . ', ' . $slider . $optionString . ');'; + $this->selection = $slider; + return $out; + } + +/** + * Serialize the form attached to $selector. + * + * @param array $options Array of options. + * @return string Completed serializeForm() snippet + * @see JsBaseEngineHelper::serializeForm() + */ + public function serializeForm($options = array()) { + $options = array_merge(array('isForm' => false, 'inline' => false), $options); + $selection = $this->selection; + if (!$options['isForm']) { + $selection = '$(' . $this->selection . '.form)'; + } + $method = '.serialize()'; + if (!$options['inline']) { + $method .= ';'; + } + return $selection . $method; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/RssHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/RssHelper.php new file mode 100644 index 0000000..bd41284 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/RssHelper.php @@ -0,0 +1,345 @@ +<?php +/** + * RSS Helper class file. + * + * Simplifies the output of RSS feeds. + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.2 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); +App::uses('Xml', 'Utility'); + +/** + * RSS Helper class for easy output RSS structures. + * + * @package Cake.View.Helper + * @property TimeHelper $Time + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html + */ +class RssHelper extends AppHelper { + +/** + * Helpers used by RSS Helper + * + * @var array + */ + public $helpers = array('Time'); + +/** + * Base URL + * + * @var string + */ + public $base = null; + +/** + * URL to current action. + * + * @var string + */ + public $here = null; + +/** + * Parameter array. + * + * @var array + */ + public $params = array(); + +/** + * Current action. + * + * @var string + */ + public $action = null; + +/** + * POSTed model data + * + * @var array + */ + public $data = null; + +/** + * Name of the current model + * + * @var string + */ + public $model = null; + +/** + * Name of the current field + * + * @var string + */ + public $field = null; + +/** + * Default spec version of generated RSS + * + * @var string + */ + public $version = '2.0'; + +/** + * Returns an RSS document wrapped in `<rss />` tags + * + * @param array $attrib `<rss />` tag attributes + * @param string $content + * @return string An RSS document + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::document + */ + public function document($attrib = array(), $content = null) { + if ($content === null) { + $content = $attrib; + $attrib = array(); + } + if (!isset($attrib['version']) || empty($attrib['version'])) { + $attrib['version'] = $this->version; + } + + return $this->elem('rss', $attrib, $content); + } + +/** + * Returns an RSS `<channel />` element + * + * @param array $attrib `<channel />` tag attributes + * @param array $elements Named array elements which are converted to tags + * @param string $content Content (`<item />`'s belonging to this channel + * @return string An RSS `<channel />` + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::channel + */ + public function channel($attrib = array(), $elements = array(), $content = null) { + if (!isset($elements['title']) && !empty($this->_View->pageTitle)) { + $elements['title'] = $this->_View->pageTitle; + } + if (!isset($elements['link'])) { + $elements['link'] = '/'; + } + if (!isset($elements['description'])) { + $elements['description'] = ''; + } + $elements['link'] = $this->url($elements['link'], true); + + $elems = ''; + foreach ($elements as $elem => $data) { + $attributes = array(); + if (is_array($data)) { + if (strtolower($elem) == 'cloud') { + $attributes = $data; + $data = array(); + } elseif (isset($data['attrib']) && is_array($data['attrib'])) { + $attributes = $data['attrib']; + unset($data['attrib']); + } else { + $innerElements = ''; + foreach ($data as $subElement => $value) { + $innerElements .= $this->elem($subElement, array(), $value); + } + $data = $innerElements; + } + } + $elems .= $this->elem($elem, $attributes, $data); + } + return $this->elem('channel', $attrib, $elems . $content, !($content === null)); + } + +/** + * Transforms an array of data using an optional callback, and maps it to a set + * of `<item />` tags + * + * @param array $items The list of items to be mapped + * @param string|array $callback A string function name, or array containing an object + * and a string method name + * @return string A set of RSS `<item />` elements + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::items + */ + public function items($items, $callback = null) { + if ($callback != null) { + $items = array_map($callback, $items); + } + + $out = ''; + $c = count($items); + + for ($i = 0; $i < $c; $i++) { + $out .= $this->item(array(), $items[$i]); + } + return $out; + } + +/** + * Converts an array into an `<item />` element and its contents + * + * @param array $att The attributes of the `<item />` element + * @param array $elements The list of elements contained in this `<item />` + * @return string An RSS `<item />` element + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::item + */ + public function item($att = array(), $elements = array()) { + $content = null; + + if (isset($elements['link']) && !isset($elements['guid'])) { + $elements['guid'] = $elements['link']; + } + + foreach ($elements as $key => $val) { + $attrib = array(); + + $escape = true; + if (is_array($val) && isset($val['convertEntities'])) { + $escape = $val['convertEntities']; + unset($val['convertEntities']); + } + + switch ($key) { + case 'pubDate' : + $val = $this->time($val); + break; + case 'category' : + if (is_array($val) && !empty($val[0])) { + foreach ($val as $category) { + $attrib = array(); + if (is_array($category) && isset($category['domain'])) { + $attrib['domain'] = $category['domain']; + unset($category['domain']); + } + $categories[] = $this->elem($key, $attrib, $category); + } + $elements[$key] = implode('', $categories); + continue 2; + } elseif (is_array($val) && isset($val['domain'])) { + $attrib['domain'] = $val['domain']; + } + break; + case 'link': + case 'guid': + case 'comments': + if (is_array($val) && isset($val['url'])) { + $attrib = $val; + unset($attrib['url']); + $val = $val['url']; + } + $val = $this->url($val, true); + break; + case 'source': + if (is_array($val) && isset($val['url'])) { + $attrib['url'] = $this->url($val['url'], true); + $val = $val['title']; + } elseif (is_array($val)) { + $attrib['url'] = $this->url($val[0], true); + $val = $val[1]; + } + break; + case 'enclosure': + if (is_string($val['url']) && is_file(WWW_ROOT . $val['url']) && file_exists(WWW_ROOT . $val['url'])) { + if (!isset($val['length']) && strpos($val['url'], '://') === false) { + $val['length'] = sprintf("%u", filesize(WWW_ROOT . $val['url'])); + } + if (!isset($val['type']) && function_exists('mime_content_type')) { + $val['type'] = mime_content_type(WWW_ROOT . $val['url']); + } + } + $val['url'] = $this->url($val['url'], true); + $attrib = $val; + $val = null; + break; + } + if (!is_null($val) && $escape) { + $val = h($val); + } + $elements[$key] = $this->elem($key, $attrib, $val); + } + if (!empty($elements)) { + $content = implode('', $elements); + } + return $this->elem('item', (array)$att, $content, !($content === null)); + } + +/** + * Converts a time in any format to an RSS time + * + * @param integer|string|DateTime $time + * @return string An RSS-formatted timestamp + * @see TimeHelper::toRSS + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::time + */ + public function time($time) { + return $this->Time->toRSS($time); + } + +/** + * Generates an XML element + * + * @param string $name The name of the XML element + * @param array $attrib The attributes of the XML element + * @param string|array $content XML element content + * @param boolean $endTag Whether the end tag of the element should be printed + * @return string XML + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::elem + */ + public function elem($name, $attrib = array(), $content = null, $endTag = true) { + $namespace = null; + if (isset($attrib['namespace'])) { + $namespace = $attrib['namespace']; + unset($attrib['namespace']); + } + $cdata = false; + if (is_array($content) && isset($content['cdata'])) { + $cdata = true; + unset($content['cdata']); + } + if (is_array($content) && array_key_exists('value', $content)) { + $content = $content['value']; + } + $children = array(); + if (is_array($content)) { + $children = $content; + $content = null; + } + + $xml = '<' . $name; + if (!empty($namespace)) { + $xml .= ' xmlns:"' . $namespace . '"'; + } + $bareName = $name; + if (strpos($name, ':') !== false) { + list($prefix, $bareName) = explode(':', $name, 2); + switch ($prefix) { + case 'atom': + $xml .= ' xmlns:atom="http://www.w3.org/2005/Atom"'; + break; + } + } + if ($cdata && !empty($content)) { + $content = '<![CDATA[' . $content . ']]>'; + } + $xml .= '>' . $content . '</' . $name . '>'; + $elem = Xml::build($xml, array('return' => 'domdocument')); + $nodes = $elem->getElementsByTagName($bareName); + foreach ($attrib as $key => $value) { + $nodes->item(0)->setAttribute($key, $value); + } + foreach ($children as $k => $child) { + $child = $elem->createElement($name, $child); + $nodes->item(0)->appendChild($child); + } + + $xml = $elem->saveXml(); + $xml = trim(substr($xml, strpos($xml, '?>') + 2)); + return $xml; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/SessionHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/SessionHelper.php new file mode 100644 index 0000000..259c4df --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/SessionHelper.php @@ -0,0 +1,163 @@ +<?php +/** + * Session Helper provides access to the Session in the Views. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 1.1.7.3328 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); +App::uses('CakeSession', 'Model/Datasource'); + +/** + * Session Helper. + * + * Session reading from the view. + * + * @package Cake.View.Helper + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html + */ +class SessionHelper extends AppHelper { + +/** + * Used to read a session values set in a controller for a key or return values for all keys. + * + * In your view: `$this->Session->read('Controller.sessKey');` + * Calling the method without a param will return all session vars + * + * @param string $name the name of the session key you want to read + * @return mixed values from the session vars + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html#SessionHelper::read + */ + public function read($name = null) { + return CakeSession::read($name); + } + +/** + * Used to check is a session key has been set + * + * In your view: `$this->Session->check('Controller.sessKey');` + * + * @param string $name + * @return boolean + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html#SessionHelper::check + */ + public function check($name) { + return CakeSession::check($name); + } + +/** + * Returns last error encountered in a session + * + * In your view: `$this->Session->error();` + * + * @return string last error + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html#displaying-notifcations-or-flash-messages + */ + public function error() { + return CakeSession::error(); + } + +/** + * Used to render the message set in Controller::Session::setFlash() + * + * In your view: $this->Session->flash('somekey'); + * Will default to flash if no param is passed + * + * You can pass additional information into the flash message generation. This allows you + * to consolidate all the parameters for a given type of flash message into the view. + * + * {{{ + * echo $this->Session->flash('flash', array('params' => array('class' => 'new-flash'))); + * }}} + * + * The above would generate a flash message with a custom class name. Using $attrs['params'] you + * can pass additional data into the element rendering that will be made available as local variables + * when the element is rendered: + * + * {{{ + * echo $this->Session->flash('flash', array('params' => array('name' => $user['User']['name']))); + * }}} + * + * This would pass the current user's name into the flash message, so you could create personalized + * messages without the controller needing access to that data. + * + * Lastly you can choose the element that is rendered when creating the flash message. Using + * custom elements allows you to fully customize how flash messages are generated. + * + * {{{ + * echo $this->Session->flash('flash', array('element' => 'my_custom_element')); + * }}} + * + * If you want to use an element from a plugin for rendering your flash message you can do that using the + * plugin param: + * + * {{{ + * echo $this->Session->flash('flash', array( + * 'element' => 'my_custom_element', + * 'params' => array('plugin' => 'my_plugin') + * )); + * }}} + * + * @param string $key The [Message.]key you are rendering in the view. + * @param array $attrs Additional attributes to use for the creation of this flash message. + * Supports the 'params', and 'element' keys that are used in the helper. + * @return string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html#SessionHelper::flash + */ + public function flash($key = 'flash', $attrs = array()) { + $out = false; + + if (CakeSession::check('Message.' . $key)) { + $flash = CakeSession::read('Message.' . $key); + $message = $flash['message']; + unset($flash['message']); + + if (!empty($attrs)) { + $flash = array_merge($flash, $attrs); + } + + if ($flash['element'] == 'default') { + $class = 'message'; + if (!empty($flash['params']['class'])) { + $class = $flash['params']['class']; + } + $out = '<div id="' . $key . 'Message" class="' . $class . '">' . $message . '</div>'; + } elseif ($flash['element'] == '' || $flash['element'] == null) { + $out = $message; + } else { + $options = array(); + if (isset($flash['params']['plugin'])) { + $options['plugin'] = $flash['params']['plugin']; + } + $tmpVars = $flash['params']; + $tmpVars['message'] = $message; + $out = $this->_View->element($flash['element'], $tmpVars, $options); + } + CakeSession::delete('Message.' . $key); + } + return $out; + } + +/** + * Used to check is a session is valid in a view + * + * @return boolean + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/session.html#SessionHelper::valid + */ + public function valid() { + return CakeSession::valid(); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TextHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TextHelper.php new file mode 100644 index 0000000..096029e --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TextHelper.php @@ -0,0 +1,277 @@ +<?php +/** + * Text Helper + * + * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links... + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('AppHelper', 'View/Helper'); + +/** + * Text helper library. + * + * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links... + * + * @package Cake.View.Helper + * @property HtmlHelper $Html + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html + * @see String + */ +class TextHelper extends AppHelper { + +/** + * helpers + * + * @var array + */ + public $helpers = array('Html'); + +/** + * An array of md5sums and their contents. + * Used when inserting links into text. + * + * @var array + */ + protected $_placeholders = array(); + +/** + * String utility instance + */ + protected $_engine; + +/** + * Constructor + * + * ### Settings: + * + * - `engine` Class name to use to replace String functionality. + * The class needs to be placed in the `Utility` directory. + * + * @param View $View the view object the helper is attached to. + * @param array $settings Settings array Settings array + * @throws CakeException when the engine class could not be found. + */ + public function __construct(View $View, $settings = array()) { + $settings = Hash::merge(array('engine' => 'String'), $settings); + parent::__construct($View, $settings); + list($plugin, $engineClass) = pluginSplit($settings['engine'], true); + App::uses($engineClass, $plugin . 'Utility'); + if (class_exists($engineClass)) { + $this->_engine = new $engineClass($settings); + } else { + throw new CakeException(__d('cake_dev', '%s could not be found', $engineClass)); + } + } + +/** + * Call methods from String utility class + */ + public function __call($method, $params) { + return call_user_func_array(array($this->_engine, $method), $params); + } + +/** + * Adds links (<a href=....) to a given text, by finding text that begins with + * strings like http:// and ftp://. + * + * ### Options + * + * - `escape` Control HTML escaping of input. Defaults to true. + * + * @param string $text Text + * @param array $options Array of HTML options, and options listed above. + * @return string The text with links + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLinkUrls + */ + public function autoLinkUrls($text, $options = array()) { + $this->_placeholders = array(); + $options += array('escape' => true); + + $text = preg_replace_callback( + '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[^\s<>()]+)#i', + array(&$this, '_insertPlaceHolder'), + $text + ); + $text = preg_replace_callback( + '#(?<!href="|">)(?<!\b[[:punct:]])(?<!http://|https://|ftp://|nntp://)www.[^\n\%\ <]+[^<\n\%\,\.\ <](?<!\))#i', + array(&$this, '_insertPlaceHolder'), + $text + ); + if ($options['escape']) { + $text = h($text); + } + return $this->_linkUrls($text, $options); + } + +/** + * Saves the placeholder for a string, for later use. This gets around double + * escaping content in URL's. + * + * @param array $matches An array of regexp matches. + * @return string Replaced values. + */ + protected function _insertPlaceHolder($matches) { + $key = md5($matches[0]); + $this->_placeholders[$key] = $matches[0]; + return $key; + } + +/** + * Replace placeholders with links. + * + * @param string $text The text to operate on. + * @param array $htmlOptions The options for the generated links. + * @return string The text with links inserted. + */ + protected function _linkUrls($text, $htmlOptions) { + $replace = array(); + foreach ($this->_placeholders as $hash => $url) { + $link = $url; + if (!preg_match('#^[a-z]+\://#', $url)) { + $url = 'http://' . $url; + } + $replace[$hash] = $this->Html->link($link, $url, $htmlOptions); + } + return strtr($text, $replace); + } + +/** + * Links email addresses + * + * @param string $text The text to operate on + * @param array $options An array of options to use for the HTML. + * @return string + * @see TextHelper::autoLinkEmails() + */ + protected function _linkEmails($text, $options) { + $replace = array(); + foreach ($this->_placeholders as $hash => $url) { + $replace[$hash] = $this->Html->link($url, 'mailto:' . $url, $options); + } + return strtr($text, $replace); + } + +/** + * Adds email links (<a href="mailto:....) to a given text. + * + * ### Options + * + * - `escape` Control HTML escaping of input. Defaults to true. + * + * @param string $text Text + * @param array $options Array of HTML options, and options listed above. + * @return string The text with links + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLinkEmails + */ + public function autoLinkEmails($text, $options = array()) { + $options += array('escape' => true); + $this->_placeholders = array(); + + $atom = '[a-z0-9!#$%&\'*+\/=?^_`{|}~-]'; + $text = preg_replace_callback( + '/(' . $atom . '+(?:\.' . $atom . '+)*@[a-z0-9-]+(?:\.[a-z0-9-]+)+)/i', + array(&$this, '_insertPlaceholder'), + $text + ); + if ($options['escape']) { + $text = h($text); + } + return $this->_linkEmails($text, $options); + } + +/** + * Convert all links and email addresses to HTML links. + * + * ### Options + * + * - `escape` Control HTML escaping of input. Defaults to true. + * + * @param string $text Text + * @param array $options Array of HTML options, and options listed above. + * @return string The text with links + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLink + */ + public function autoLink($text, $options = array()) { + $text = $this->autoLinkUrls($text, $options); + return $this->autoLinkEmails($text, array_merge($options, array('escape' => false))); + } + +/** + * @see String::highlight() + * + * @param string $text Text to search the phrase in + * @param string $phrase The phrase that will be searched + * @param array $options An array of html attributes and options. + * @return string The highlighted text + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight + */ + public function highlight($text, $phrase, $options = array()) { + return $this->_engine->highlight($text, $phrase, $options); + } + +/** + * @see String::stripLinks() + * + * @param string $text Text + * @return string The text without links + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks + */ + public function stripLinks($text) { + return $this->_engine->stripLinks($text); + } + +/** + * @see String::truncate() + * + * @param string $text String to truncate. + * @param integer $length Length of returned string, including ellipsis. + * @param array $options An array of html attributes and options. + * @return string Trimmed string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::truncate + */ + public function truncate($text, $length = 100, $options = array()) { + return $this->_engine->truncate($text, $length, $options); + } + +/** + * @see String::excerpt() + * + * @param string $text String to search the phrase in + * @param string $phrase Phrase that will be searched for + * @param integer $radius The amount of characters that will be returned on each side of the founded phrase + * @param string $ending Ending that will be appended + * @return string Modified string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt + */ + public function excerpt($text, $phrase, $radius = 100, $ending = '...') { + return $this->_engine->excerpt($text, $phrase, $radius, $ending); + } + +/** + * @see String::toList() + * + * @param array $list The list to be joined + * @param string $and The word used to join the last and second last items together with. Defaults to 'and' + * @param string $separator The separator used to join all the other items together. Defaults to ', ' + * @return string The glued together string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::toList + */ + public function toList($list, $and = 'and', $separator = ', ') { + return $this->_engine->toList($list, $and, $separator); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TimeHelper.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TimeHelper.php new file mode 100644 index 0000000..2849179 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TimeHelper.php @@ -0,0 +1,458 @@ +<?php +/** + * Time Helper class file. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Helper + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('CakeTime', 'Utility'); +App::uses('Multibyte', 'I18n'); +App::uses('AppHelper', 'View/Helper'); + +/** + * Time Helper class for easy use of time data. + * + * Manipulation of time data. + * + * @package Cake.View.Helper + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html + * @see CakeTime + */ +class TimeHelper extends AppHelper { + +/** + * CakeTime instance + */ + protected $_engine = null; + +/** + * Constructor + * + * ### Settings: + * + * - `engine` Class name to use to replace CakeTime functionality + * The class needs to be placed in the `Utility` directory. + * + * @param View $View the view object the helper is attached to. + * @param array $settings Settings array Settings array + * @throws CakeException When the engine class could not be found. + */ + public function __construct(View $View, $settings = array()) { + $settings = Hash::merge(array('engine' => 'CakeTime'), $settings); + parent::__construct($View, $settings); + list($plugin, $engineClass) = pluginSplit($settings['engine'], true); + App::uses($engineClass, $plugin . 'Utility'); + if (class_exists($engineClass)) { + $this->_engine = new $engineClass($settings); + } else { + throw new CakeException(__d('cake_dev', '%s could not be found', $engineClass)); + } + } + +/** + * Magic accessor for deprecated attributes. + * + * @param string $name Name of the attribute to set. + * @param string $value Value of the attribute to set. + * @return mixed + */ + public function __set($name, $value) { + switch ($name) { + case 'niceFormat': + $this->_engine->{$name} = $value; + break; + default: + $this->{$name} = $value; + break; + } + } + +/** + * Magic isset check for deprecated attributes. + * + * @param string $name Name of the attribute to check. + * @return boolean + */ + public function __isset($name) { + if (isset($this->{$name})) { + return true; + } + $magicGet = array('niceFormat'); + if (in_array($name, $magicGet)) { + return $this->__get($name) !== null; + } + return null; + } + +/** + * Magic accessor for attributes that were deprecated. + * + * @param string $name Name of the attribute to get. + * @return mixed + */ + public function __get($name) { + if (isset($this->_engine->{$name})) { + return $this->_engine->{$name}; + } + $magicGet = array('niceFormat'); + if (in_array($name, $magicGet)) { + return $this->_engine->{$name}; + } + return null; + } + +/** + * Call methods from CakeTime utility class + */ + public function __call($method, $params) { + return call_user_func_array(array($this->_engine, $method), $params); + } + +/** + * @see CakeTime::convertSpecifiers() + * + * @param string $format Format with specifiers for strftime function. + * Accepts the special specifier %S which mimics the modifier S for date() + * @param string $time UNIX timestamp + * @return string windows safe and date() function compatible format for strftime + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function convertSpecifiers($format, $time = null) { + return $this->_engine->convertSpecifiers($format, $time); + } + +/** + * @see CakeTime::convert() + * + * @param string $serverTime UNIX timestamp + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return integer UNIX timestamp + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function convert($serverTime, $timezone) { + return $this->_engine->convert($serverTime, $timezone); + } + +/** + * @see CakeTime::serverOffset() + * + * @return integer Offset + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function serverOffset() { + return $this->_engine->serverOffset(); + } + +/** + * @see CakeTime::fromString() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Parsed timestamp + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function fromString($dateString, $timezone = null) { + return $this->_engine->fromString($dateString, $timezone); + } + +/** + * @see CakeTime::nice() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @param string $format The format to use. If null, `TimeHelper::$niceFormat` is used + * @return string Formatted date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function nice($dateString = null, $timezone = null, $format = null) { + return $this->_engine->nice($dateString, $timezone, $format); + } + +/** + * @see CakeTime::niceShort() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime objectp + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Described, relative date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function niceShort($dateString = null, $timezone = null) { + return $this->_engine->niceShort($dateString, $timezone); + } + +/** + * @see CakeTime::daysAsSql() + * + * @param integer|string|DateTime $begin UNIX timestamp, strtotime() valid string or DateTime object + * @param integer|string|DateTime $end UNIX timestamp, strtotime() valid string or DateTime object + * @param string $fieldName Name of database field to compare with + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Partial SQL string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function daysAsSql($begin, $end, $fieldName, $timezone = null) { + return $this->_engine->daysAsSql($begin, $end, $fieldName, $timezone); + } + +/** + * @see CakeTime::dayAsSql() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string $fieldName Name of database field to compare with + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Partial SQL string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function dayAsSql($dateString, $fieldName, $timezone = null) { + return $this->_engine->dayAsSql($dateString, $fieldName, $timezone); + } + +/** + * @see CakeTime::isToday() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string is today + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isToday($dateString, $timezone = null) { + return $this->_engine->isToday($dateString, $timezone); + } + +/** + * @see CakeTime::isThisWeek() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string is within current week + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isThisWeek($dateString, $timezone = null) { + return $this->_engine->isThisWeek($dateString, $timezone); + } + +/** + * @see CakeTime::isThisMonth() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string is within current month + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isThisMonth($dateString, $timezone = null) { + return $this->_engine->isThisMonth($dateString, $timezone); + } + +/** + * @see CakeTime::isThisYear() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string is within current year + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isThisYear($dateString, $timezone = null) { + return $this->_engine->isThisYear($dateString, $timezone); + } + +/** + * @see CakeTime::wasYesterday() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string was yesterday + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + * + */ + public function wasYesterday($dateString, $timezone = null) { + return $this->_engine->wasYesterday($dateString, $timezone); + } + +/** + * @see CakeTime::isTomorrow() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean True if datetime string was yesterday + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isTomorrow($dateString, $timezone = null) { + return $this->_engine->isTomorrow($dateString, $timezone); + } + +/** + * @see CakeTime::toQuarter() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param boolean $range if true returns a range in Y-m-d format + * @return mixed 1, 2, 3, or 4 quarter of year or array if $range true + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function toQuarter($dateString, $range = false) { + return $this->_engine->toQuarter($dateString, $range); + } + +/** + * @see CakeTime::toUnix() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return integer Unix timestamp + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function toUnix($dateString, $timezone = null) { + return $this->_engine->toUnix($dateString, $timezone); + } + +/** + * @see CakeTime::toAtom() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Formatted date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function toAtom($dateString, $timezone = null) { + return $this->_engine->toAtom($dateString, $timezone); + } + +/** + * @see CakeTime::toRSS() + * + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Formatted date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function toRSS($dateString, $timezone = null) { + return $this->_engine->toRSS($dateString, $timezone); + } + +/** + * @see CakeTime::timeAgoInWords() + * + * ## Addition options + * + * - `element` - The element to wrap the formatted time in. + * Has a few additional options: + * - `tag` - The tag to use, defaults to 'span'. + * - `class` - The classname to use, defaults to `time-ago-in-words`. + * - `title` - Defaults to the $dateTime input. + * + * @param integer|string|DateTime $dateTime UNIX timestamp, strtotime() valid string or DateTime object + * @param array $options Default format if timestamp is used in $dateString + * @return string Relative time string. + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function timeAgoInWords($dateTime, $options = array()) { + $element = null; + $stringDate = ''; + + if (is_array($options) && !empty($options['element'])) { + $element = array( + 'tag' => 'span', + 'class' => 'time-ago-in-words', + 'title' => $dateTime + ); + + if (is_array($options['element'])) { + $element = array_merge($element, $options['element']); + } else { + $element['tag'] = $options['element']; + } + unset($options['element']); + } + $relativeDate = $this->_engine->timeAgoInWords($dateTime, $options); + + if ($element) { + $relativeDate = sprintf( + '<%s%s>%s</%s>', + $element['tag'], + $this->_parseAttributes($element, array('tag')), + $relativeDate, + $element['tag'] + ); + } + return $relativeDate; + } + +/** + * @see CakeTime::wasWithinLast() + * + * @param string|integer $timeInterval the numeric value with space then time type. + * Example of valid types: 6 hours, 2 days, 1 minute. + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function wasWithinLast($timeInterval, $dateString, $timezone = null) { + return $this->_engine->wasWithinLast($timeInterval, $dateString, $timezone); + } + +/** + * @see CakeTime::isWithinLast() + * + * @param string|integer $timeInterval the numeric value with space then time type. + * Example of valid types: 6 hours, 2 days, 1 minute. + * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return boolean + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time + */ + public function isWithinNext($timeInterval, $dateString, $timezone = null) { + return $this->_engine->isWithinNext($timeInterval, $dateString, $timezone); + } + +/** + * @see CakeTime::gmt() + * + * @param integer|string|DateTime $string UNIX timestamp, strtotime() valid string or DateTime object + * @return integer UNIX timestamp + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function gmt($string = null) { + return $this->_engine->gmt($string); + } + +/** + * @see CakeTime::format() + * + * @param integer|string|DateTime $format date format string (or a UNIX timestamp, strtotime() valid string or DateTime object) + * @param integer|string|DateTime $date UNIX timestamp, strtotime() valid string or DateTime object (or a date format string) + * @param boolean $invalid flag to ignore results of fromString == false + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Formatted date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function format($format, $date = null, $invalid = false, $timezone = null) { + return $this->_engine->format($format, $date, $invalid, $timezone); + } + +/** + * @see CakeTime::i18nFormat() + * + * @param integer|string|DateTime $date UNIX timestamp, strtotime() valid string or DateTime object + * @param string $format strftime format string. + * @param boolean $invalid flag to ignore results of fromString == false + * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object + * @return string Formatted and translated date string + * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting + */ + public function i18nFormat($date, $format = null, $invalid = false, $timezone = null) { + return $this->_engine->i18nFormat($date, $format, $invalid, $timezone); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/HelperCollection.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/HelperCollection.php new file mode 100644 index 0000000..f07019c --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/HelperCollection.php @@ -0,0 +1,203 @@ +<?php +/** + * Helpers collection is used as a registry for loaded helpers and handles loading + * and constructing helper class objects. + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('ObjectCollection', 'Utility'); +App::uses('CakeEventListener', 'Event'); + +/** + * Helpers collection is used as a registry for loaded helpers and handles loading + * and constructing helper class objects. + * + * @package Cake.View + */ +class HelperCollection extends ObjectCollection implements CakeEventListener { + +/** + * View object to use when making helpers. + * + * @var View + */ + protected $_View; + +/** + * Constructor + * + * @param View $view + */ + public function __construct(View $view) { + $this->_View = $view; + } + +/** + * Tries to lazy load a helper based on its name, if it cannot be found + * in the application folder, then it tries looking under the current plugin + * if any + * + * @param string $helper The helper name to be loaded + * @return boolean wheter the helper could be loaded or not + * @throws MissingHelperException When a helper could not be found. + * App helpers are searched, and then plugin helpers. + */ + public function __isset($helper) { + if (parent::__isset($helper)) { + return true; + } + + try { + $this->load($helper); + } catch (MissingHelperException $exception) { + if ($this->_View->plugin) { + $this->load($this->_View->plugin . '.' . $helper); + return true; + } + } + + if (!empty($exception)) { + throw $exception; + } + + return true; + } + +/** + * Provide public read access to the loaded objects + * + * @param string $name Name of property to read + * @return mixed + */ + public function __get($name) { + if ($result = parent::__get($name)) { + return $result; + } + if ($this->__isset($name)) { + return $this->_loaded[$name]; + } + return null; + } + +/** + * Loads/constructs a helper. Will return the instance in the registry if it already exists. + * By setting `$enable` to false you can disable callbacks for a helper. Alternatively you + * can set `$settings['enabled'] = false` to disable callbacks. This alias is provided so that when + * declaring $helpers arrays you can disable callbacks on helpers. + * + * You can alias your helper as an existing helper by setting the 'className' key, i.e., + * {{{ + * public $helpers = array( + * 'Html' => array( + * 'className' => 'AliasedHtml' + * ); + * ); + * }}} + * All calls to the `Html` helper would use `AliasedHtml` instead. + * + * @param string $helper Helper name to load + * @param array $settings Settings for the helper. + * @return Helper A helper object, Either the existing loaded helper or a new one. + * @throws MissingHelperException when the helper could not be found + */ + public function load($helper, $settings = array()) { + if (is_array($settings) && isset($settings['className'])) { + $alias = $helper; + $helper = $settings['className']; + } + list($plugin, $name) = pluginSplit($helper, true); + if (!isset($alias)) { + $alias = $name; + } + + if (isset($this->_loaded[$alias])) { + return $this->_loaded[$alias]; + } + $helperClass = $name . 'Helper'; + App::uses($helperClass, $plugin . 'View/Helper'); + if (!class_exists($helperClass)) { + throw new MissingHelperException(array( + 'class' => $helperClass, + 'plugin' => substr($plugin, 0, -1) + )); + } + $this->_loaded[$alias] = new $helperClass($this->_View, $settings); + + $vars = array('request', 'theme', 'plugin'); + foreach ($vars as $var) { + $this->_loaded[$alias]->{$var} = $this->_View->{$var}; + } + $enable = isset($settings['enabled']) ? $settings['enabled'] : true; + if ($enable) { + $this->enable($alias); + } + return $this->_loaded[$alias]; + } + +/** + * Returns a list of all events that will fire in the View during it's lifecycle. + * + * @return array + */ + public function implementedEvents() { + return array( + 'View.beforeRenderFile' => 'trigger', + 'View.afterRenderFile' => 'trigger', + 'View.beforeRender' => 'trigger', + 'View.afterRender' => 'trigger', + 'View.beforeLayout' => 'trigger', + 'View.afterLayout' => 'trigger' + ); + } + +/** + * Trigger a callback method on every object in the collection. + * Used to trigger methods on objects in the collection. Will fire the methods in the + * order they were attached. + * + * ### Options + * + * - `breakOn` Set to the value or values you want the callback propagation to stop on. + * Can either be a scalar value, or an array of values to break on. Defaults to `false`. + * + * - `break` Set to true to enabled breaking. When a trigger is broken, the last returned value + * will be returned. If used in combination with `collectReturn` the collected results will be returned. + * Defaults to `false`. + * + * - `collectReturn` Set to true to collect the return of each object into an array. + * This array of return values will be returned from the trigger() call. Defaults to `false`. + * + * - `modParams` Allows each object the callback gets called on to modify the parameters to the next object. + * Setting modParams to an integer value will allow you to modify the parameter with that index. + * Any non-null value will modify the parameter index indicated. + * Defaults to false. + * + * + * @param string $callback|CakeEvent Method to fire on all the objects. Its assumed all the objects implement + * the method you are calling. If an instance of CakeEvent is provided, then then Event name will parsed to + * get the callback name. This is done by getting the last word after any dot in the event name + * (eg. `Model.afterSave` event will trigger the `afterSave` callback) + * @param array $params Array of parameters for the triggered callback. + * @param array $options Array of options. + * @return mixed Either the last result or all results if collectReturn is on. + * @throws CakeException when modParams is used with an index that does not exist. + */ + public function trigger($callback, $params = array(), $options = array()) { + if ($callback instanceof CakeEvent) { + $callback->omitSubject = true; + } + return parent::trigger($callback, $params, $options); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/JsonView.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/JsonView.php new file mode 100644 index 0000000..3cf669c --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/JsonView.php @@ -0,0 +1,108 @@ +<?php +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('View', 'View'); + +/** + * A view class that is used for JSON responses. + * + * By setting the '_serialize' key in your controller, you can specify a view variable + * that should be serialized to JSON and used as the response for the request. + * This allows you to omit views + layouts, if your just need to emit a single view + * variable as the JSON response. + * + * In your controller, you could do the following: + * + * `$this->set(array('posts' => $posts, '_serialize' => 'posts'));` + * + * When the view is rendered, the `$posts` view variable will be serialized + * into JSON. + * + * You can also define `'_serialize'` as an array. This will create a top level object containing + * all the named view variables: + * + * {{{ + * $this->set(compact('posts', 'users', 'stuff')); + * $this->set('_serialize', array('posts', 'users')); + * }}} + * + * The above would generate a JSON object that looks like: + * + * `{"posts": [...], "users": [...]}` + * + * If you don't use the `_serialize` key, you will need a view. You can use extended + * views to provide layout like functionality. + * + * @package Cake.View + * @since CakePHP(tm) v 2.1.0 + */ +class JsonView extends View { + +/** + * JSON views are always located in the 'json' sub directory for a + * controllers views. + * + * @var string + */ + public $subDir = 'json'; + +/** + * Constructor + * + * @param Controller $controller + */ + public function __construct(Controller $controller = null) { + parent::__construct($controller); + if (isset($controller->response) && $controller->response instanceof CakeResponse) { + $controller->response->type('json'); + } + } + +/** + * Render a JSON view. + * + * Uses the special '_serialize' parameter to convert a set of + * view variables into a JSON response. Makes generating simple + * JSON responses very easy. You can omit the '_serialize' parameter, + * and use a normal view + layout as well. + * + * @param string $view The view being rendered. + * @param string $layout The layout being rendered. + * @return string The rendered view. + */ + public function render($view = null, $layout = null) { + if (isset($this->viewVars['_serialize'])) { + $serialize = $this->viewVars['_serialize']; + if (is_array($serialize)) { + $data = array(); + foreach ($serialize as $key) { + $data[$key] = $this->viewVars[$key]; + } + } else { + $data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null; + } + $content = json_encode($data); + $this->Blocks->set('content', $content); + return $content; + } + if ($view !== false && $viewFileName = $this->_getViewFileName($view)) { + if (!$this->_helpersLoaded) { + $this->loadHelpers(); + } + $content = $this->_render($viewFileName); + $this->Blocks->set('content', $content); + return $content; + } + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/MediaView.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/MediaView.php new file mode 100644 index 0000000..49a3140 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/MediaView.php @@ -0,0 +1,238 @@ +<?php +/** + * Methods to display or download any type of file + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since CakePHP(tm) v 1.2.0.5714 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('View', 'View'); +App::uses('CakeRequest', 'Network'); + +/** + * Media View provides a custom view implementation for sending files to visitors. Its great + * for making the response of a controller action be a file that is saved somewhere on the filesystem. + * + * An example use comes from the CakePHP internals. MediaView is used to serve plugin and theme assets, + * as they are not normally accessible from an application's webroot. Unlike other views, MediaView + * uses several viewVars that have special meaning: + * + * - `id` The filename on the server's filesystem, including extension. + * - `name` The filename that will be sent to the user, specified without the extension. + * - `download` Set to true to set a `Content-Disposition` header. This is ideal for file downloads. + * - `extension` The extension of the file being served. This is used to set the mimetype. + * If not provided its extracted from filename provided as `id`. + * - `path` The absolute path, including the trailing / on the server's filesystem to `id`. + * - `mimeType` The mime type of the file if CakeResponse doesn't know about it. + * Must be an associative array with extension as key and mime type as value eg. array('ini' => 'text/plain') + * + * ### Usage + * + * {{{ + * class ExampleController extends AppController { + * public function download() { + * $this->viewClass = 'Media'; + * $params = array( + * 'id' => 'example.zip', + * 'name' => 'example', + * 'download' => true, + * 'extension' => 'zip', + * 'path' => APP . 'files' . DS + * ); + * $this->set($params); + * } + * } + * }}} + * + * @package Cake.View + */ +class MediaView extends View { + +/** + * Indicates whether response gzip compression was enabled for this class + * + * @var boolean + */ + protected $_compressionEnabled = false; + +/** + * Display or download the given file + * + * @param string $view Not used + * @param string $layout Not used + * @return mixed + * @throws NotFoundException + */ + public function render($view = null, $layout = null) { + $name = $download = $extension = $id = $modified = $path = $cache = $mimeType = $compress = null; + extract($this->viewVars, EXTR_OVERWRITE); + + if (is_dir($path)) { + $path = $path . $id; + } else { + $path = APP . $path . $id; + } + + if (!is_file($path)) { + if (Configure::read('debug')) { + throw new NotFoundException(sprintf('The requested file %s was not found', $path)); + } + throw new NotFoundException('The requested file was not found'); + } + + if (is_array($mimeType)) { + $this->response->type($mimeType); + } + + if (!isset($extension)) { + $extension = pathinfo($id, PATHINFO_EXTENSION); + } + + if ($this->_isActive()) { + $extension = strtolower($extension); + $chunkSize = 8192; + $buffer = ''; + $fileSize = @filesize($path); + $handle = fopen($path, 'rb'); + + if ($handle === false) { + return false; + } + if (!empty($modified) && !is_numeric($modified)) { + $modified = strtotime($modified, time()); + } else { + $modified = time(); + } + if (!$extension || $this->response->type($extension) === false) { + $download = true; + } + + if ($cache) { + $this->response->cache($modified, $cache); + } else { + $this->response->header(array( + 'Date' => gmdate('D, d M Y H:i:s', time()) . ' GMT', + 'Expires' => '0', + 'Cache-Control' => 'private, must-revalidate, post-check=0, pre-check=0', + 'Pragma' => 'no-cache' + )); + } + + if ($download) { + $agent = env('HTTP_USER_AGENT'); + + if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) { + $contentType = 'application/octetstream'; + } elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) { + $contentType = 'application/force-download'; + } + + if (!empty($contentType)) { + $this->response->type($contentType); + } + if (is_null($name)) { + $name = $id; + } elseif ($extension) { + $name .= '.' . $extension; + } + $this->response->download($name); + $this->response->header(array('Accept-Ranges' => 'bytes')); + + $httpRange = env('HTTP_RANGE'); + if (isset($httpRange)) { + list($toss, $range) = explode('=', $httpRange); + + $size = $fileSize - 1; + $length = $fileSize - $range; + + $this->response->header(array( + 'Content-Length' => $length, + 'Content-Range' => 'bytes ' . $range . $size . '/' . $fileSize + )); + + $this->response->statusCode(206); + fseek($handle, $range); + } else { + $this->response->header('Content-Length', $fileSize); + } + } else { + $this->response->header(array( + 'Content-Length' => $fileSize + )); + } + $this->_clearBuffer(); + if ($compress) { + $this->_compressionEnabled = $this->response->compress(); + } + + $this->response->send(); + return $this->_sendFile($handle); + } + + return false; + } + +/** + * Reads out a file handle, and echos the content to the client. + * + * @param resource $handle A file handle or stream + * @return void + */ + protected function _sendFile($handle) { + $chunkSize = 8192; + $buffer = ''; + while (!feof($handle)) { + if (!$this->_isActive()) { + fclose($handle); + return false; + } + set_time_limit(0); + $buffer = fread($handle, $chunkSize); + echo $buffer; + if (!$this->_compressionEnabled) { + $this->_flushBuffer(); + } + } + fclose($handle); + } + +/** + * Returns true if connection is still active + * + * @return boolean + */ + protected function _isActive() { + return connection_status() == 0 && !connection_aborted(); + } + +/** + * Clears the contents of the topmost output buffer and discards them + * + * @return boolean + */ + protected function _clearBuffer() { + return @ob_end_clean(); + } + +/** + * Flushes the contents of the output buffer + * + * @return void + */ + protected function _flushBuffer() { + @flush(); + @ob_flush(); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ScaffoldView.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ScaffoldView.php new file mode 100644 index 0000000..5cb9fb6 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ScaffoldView.php @@ -0,0 +1,91 @@ +<?php +/** + * Scaffold. + * + * Automatic forms and actions generation for rapid web application development. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since Cake v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('ThemeView', 'View'); + +/** + * ScaffoldView provides specific view file loading features for scaffolded views. + * + * @package Cake.View + */ +class ScaffoldView extends ThemeView { + +/** + * Override _getViewFileName Appends special scaffolding views in. + * + * @param string $name name of the view file to get. + * @return string action + * @throws MissingViewException + */ + protected function _getViewFileName($name = null) { + if ($name === null) { + $name = $this->action; + } + $name = Inflector::underscore($name); + $prefixes = Configure::read('Routing.prefixes'); + + if (!empty($prefixes)) { + foreach ($prefixes as $prefix) { + if (strpos($name, $prefix . '_') !== false) { + $name = substr($name, strlen($prefix) + 1); + break; + } + } + } + + if ($name === 'add' || $name == 'edit') { + $name = 'form'; + } + + $scaffoldAction = 'scaffold.' . $name; + + if (!is_null($this->subDir)) { + $subDir = strtolower($this->subDir) . DS; + } else { + $subDir = null; + } + + $names[] = $this->viewPath . DS . $subDir . $scaffoldAction; + $names[] = 'Scaffolds' . DS . $subDir . $name; + + $paths = $this->_paths($this->plugin); + $exts = array($this->ext); + if ($this->ext !== '.ctp') { + array_push($exts, '.ctp'); + } + foreach ($exts as $ext) { + foreach ($paths as $path) { + foreach ($names as $name) { + if (file_exists($path . $name . $ext)) { + return $path . $name . $ext; + } + } + } + } + + if ($name === 'Scaffolds' . DS . $subDir . 'error') { + return CAKE . 'View' . DS . 'Errors' . DS . 'scaffold_error.ctp'; + } + + throw new MissingViewException($paths[0] . $name . $this->ext); + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/form.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/form.ctp new file mode 100644 index 0000000..b672595 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/form.ctp @@ -0,0 +1,51 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Scaffolds + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<div class="<?php echo $pluralVar; ?> form"> +<?php + echo $this->Form->create(); + echo $this->Form->inputs($scaffoldFields, array('created', 'modified', 'updated')); + echo $this->Form->end(__d('cake', 'Submit')); +?> +</div> +<div class="actions"> + <h3><?php echo __d('cake', 'Actions'); ?></h3> + <ul> +<?php if ($this->request->action != 'add'): ?> + <li><?php echo $this->Form->postLink( + __d('cake', 'Delete'), + array('action' => 'delete', $this->Form->value($modelClass . '.' . $primaryKey)), + null, + __d('cake', 'Are you sure you want to delete # %s?', $this->Form->value($modelClass . '.' . $primaryKey))); + ?></li> +<?php endif; ?> + <li><?php echo $this->Html->link(__d('cake', 'List') . ' ' . $pluralHumanName, array('action' => 'index')); ?></li> +<?php + $done = array(); + foreach ($associations as $_type => $_data) { + foreach ($_data as $_alias => $_details) { + if ($_details['controller'] != $this->name && !in_array($_details['controller'], $done)) { + echo "\t\t<li>" . $this->Html->link(__d('cake', 'List %s', Inflector::humanize($_details['controller'])), array('controller' => $_details['controller'], 'action' => 'index')) . "</li>\n"; + echo "\t\t<li>" . $this->Html->link(__d('cake', 'New %s', Inflector::humanize(Inflector::underscore($_alias))), array('controller' => $_details['controller'], 'action' => 'add')) . "</li>\n"; + $done[] = $_details['controller']; + } + } + } +?> + </ul> +</div>
\ No newline at end of file diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/index.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/index.ctp new file mode 100644 index 0000000..fffec7f --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/index.ctp @@ -0,0 +1,94 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Scaffolds + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<div class="<?php echo $pluralVar; ?> index"> +<h2><?php echo $pluralHumanName; ?></h2> +<table cellpadding="0" cellspacing="0"> +<tr> +<?php foreach ($scaffoldFields as $_field): ?> + <th><?php echo $this->Paginator->sort($_field); ?></th> +<?php endforeach; ?> + <th><?php echo __d('cake', 'Actions'); ?></th> +</tr> +<?php +$i = 0; +foreach (${$pluralVar} as ${$singularVar}): + echo "<tr>"; + foreach ($scaffoldFields as $_field) { + $isKey = false; + if (!empty($associations['belongsTo'])) { + foreach ($associations['belongsTo'] as $_alias => $_details) { + if ($_field === $_details['foreignKey']) { + $isKey = true; + echo "<td>" . $this->Html->link(${$singularVar}[$_alias][$_details['displayField']], array('controller' => $_details['controller'], 'action' => 'view', ${$singularVar}[$_alias][$_details['primaryKey']])) . "</td>"; + break; + } + } + } + if ($isKey !== true) { + echo "<td>" . h(${$singularVar}[$modelClass][$_field]) . "</td>"; + } + } + + echo '<td class="actions">'; + echo $this->Html->link(__d('cake', 'View'), array('action' => 'view', ${$singularVar}[$modelClass][$primaryKey])); + echo $this->Html->link(__d('cake', 'Edit'), array('action' => 'edit', ${$singularVar}[$modelClass][$primaryKey])); + echo $this->Form->postLink( + __d('cake', 'Delete'), + array('action' => 'delete', ${$singularVar}[$modelClass][$primaryKey]), + null, + __d('cake', 'Are you sure you want to delete').' #' . ${$singularVar}[$modelClass][$primaryKey] + ); + echo '</td>'; + echo '</tr>'; + +endforeach; + +?> +</table> + <p><?php + echo $this->Paginator->counter(array( + 'format' => __d('cake', 'Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}') + )); + ?></p> + <div class="paging"> + <?php + echo $this->Paginator->prev('< ' . __d('cake', 'previous'), array(), null, array('class' => 'prev disabled')); + echo $this->Paginator->numbers(array('separator' => '')); + echo $this->Paginator->next(__d('cake', 'next') .' >', array(), null, array('class' => 'next disabled')); + ?> + </div> +</div> +<div class="actions"> + <h3><?php echo __d('cake', 'Actions'); ?></h3> + <ul> + <li><?php echo $this->Html->link(__d('cake', 'New %s', $singularHumanName), array('action' => 'add')); ?></li> +<?php + $done = array(); + foreach ($associations as $_type => $_data) { + foreach ($_data as $_alias => $_details) { + if ($_details['controller'] != $this->name && !in_array($_details['controller'], $done)) { + echo "<li>" . $this->Html->link(__d('cake', 'List %s', Inflector::humanize($_details['controller'])), array('controller' => $_details['controller'], 'action' => 'index')) . "</li>"; + echo "<li>" . $this->Html->link(__d('cake', 'New %s', Inflector::humanize(Inflector::underscore($_alias))), array('controller' => $_details['controller'], 'action' => 'add')) . "</li>"; + $done[] = $_details['controller']; + } + } + } +?> + </ul> +</div> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/view.ctp b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/view.ctp new file mode 100644 index 0000000..c383d12 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/view.ctp @@ -0,0 +1,146 @@ +<?php +/** + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View.Scaffolds + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +?> +<div class="<?php echo $pluralVar; ?> view"> +<h2><?php echo __d('cake', 'View %s', $singularHumanName); ?></h2> + <dl> +<?php +$i = 0; +foreach ($scaffoldFields as $_field) { + $isKey = false; + if (!empty($associations['belongsTo'])) { + foreach ($associations['belongsTo'] as $_alias => $_details) { + if ($_field === $_details['foreignKey']) { + $isKey = true; + echo "\t\t<dt>" . Inflector::humanize($_alias) . "</dt>\n"; + echo "\t\t<dd>\n\t\t\t" . $this->Html->link(${$singularVar}[$_alias][$_details['displayField']], array('controller' => $_details['controller'], 'action' => 'view', ${$singularVar}[$_alias][$_details['primaryKey']])) . "\n\t\t </dd>\n"; + break; + } + } + } + if ($isKey !== true) { + echo "\t\t<dt>" . Inflector::humanize($_field) . "</dt>\n"; + echo "\t\t<dd>" . h(${$singularVar}[$modelClass][$_field]) . " </dd>\n"; + } +} +?> + </dl> +</div> +<div class="actions"> + <h3><?php echo __d('cake', 'Actions'); ?></h3> + <ul> +<?php + echo "\t\t<li>" . $this->Html->link(__d('cake', 'Edit %s', $singularHumanName), array('action' => 'edit', ${$singularVar}[$modelClass][$primaryKey])) . " </li>\n"; + echo "\t\t<li>" . $this->Form->postLink(__d('cake', 'Delete %s', $singularHumanName), array('action' => 'delete', ${$singularVar}[$modelClass][$primaryKey]), null, __d('cake', 'Are you sure you want to delete').' #' . ${$singularVar}[$modelClass][$primaryKey] . '?') . " </li>\n"; + echo "\t\t<li>" . $this->Html->link(__d('cake', 'List %s', $pluralHumanName), array('action' => 'index')) . " </li>\n"; + echo "\t\t<li>" . $this->Html->link(__d('cake', 'New %s', $singularHumanName), array('action' => 'add')) . " </li>\n"; + + $done = array(); + foreach ($associations as $_type => $_data) { + foreach ($_data as $_alias => $_details) { + if ($_details['controller'] != $this->name && !in_array($_details['controller'], $done)) { + echo "\t\t<li>" . $this->Html->link(__d('cake', 'List %s', Inflector::humanize($_details['controller'])), array('controller' => $_details['controller'], 'action' => 'index')) . "</li>\n"; + echo "\t\t<li>" . $this->Html->link(__d('cake', 'New %s', Inflector::humanize(Inflector::underscore($_alias))), array('controller' => $_details['controller'], 'action' => 'add')) . "</li>\n"; + $done[] = $_details['controller']; + } + } + } +?> + </ul> +</div> +<?php +if (!empty($associations['hasOne'])) : +foreach ($associations['hasOne'] as $_alias => $_details): ?> +<div class="related"> + <h3><?php echo __d('cake', "Related %s", Inflector::humanize($_details['controller'])); ?></h3> +<?php if (!empty(${$singularVar}[$_alias])): ?> + <dl> +<?php + $i = 0; + $otherFields = array_keys(${$singularVar}[$_alias]); + foreach ($otherFields as $_field) { + echo "\t\t<dt>" . Inflector::humanize($_field) . "</dt>\n"; + echo "\t\t<dd>\n\t" . ${$singularVar}[$_alias][$_field] . "\n </dd>\n"; + } +?> + </dl> +<?php endif; ?> + <div class="actions"> + <ul> + <li><?php echo $this->Html->link(__d('cake', 'Edit %s', Inflector::humanize(Inflector::underscore($_alias))), array('controller' => $_details['controller'], 'action' => 'edit', ${$singularVar}[$_alias][$_details['primaryKey']]))."</li>\n"; ?> + </ul> + </div> +</div> +<?php +endforeach; +endif; + +if (empty($associations['hasMany'])) { + $associations['hasMany'] = array(); +} +if (empty($associations['hasAndBelongsToMany'])) { + $associations['hasAndBelongsToMany'] = array(); +} +$relations = array_merge($associations['hasMany'], $associations['hasAndBelongsToMany']); +$i = 0; +foreach ($relations as $_alias => $_details): +$otherSingularVar = Inflector::variable($_alias); +?> +<div class="related"> + <h3><?php echo __d('cake', "Related %s", Inflector::humanize($_details['controller'])); ?></h3> +<?php if (!empty(${$singularVar}[$_alias])): ?> + <table cellpadding="0" cellspacing="0"> + <tr> +<?php + $otherFields = array_keys(${$singularVar}[$_alias][0]); + if (isset($_details['with'])) { + $index = array_search($_details['with'], $otherFields); + unset($otherFields[$index]); + } + foreach ($otherFields as $_field) { + echo "\t\t<th>" . Inflector::humanize($_field) . "</th>\n"; + } +?> + <th class="actions">Actions</th> + </tr> +<?php + $i = 0; + foreach (${$singularVar}[$_alias] as ${$otherSingularVar}): + echo "\t\t<tr>\n"; + + foreach ($otherFields as $_field) { + echo "\t\t\t<td>" . ${$otherSingularVar}[$_field] . "</td>\n"; + } + + echo "\t\t\t<td class=\"actions\">\n"; + echo "\t\t\t\t" . $this->Html->link(__d('cake', 'View'), array('controller' => $_details['controller'], 'action' => 'view', ${$otherSingularVar}[$_details['primaryKey']])). "\n"; + echo "\t\t\t\t" . $this->Html->link(__d('cake', 'Edit'), array('controller' => $_details['controller'], 'action' => 'edit', ${$otherSingularVar}[$_details['primaryKey']])). "\n"; + echo "\t\t\t\t" . $this->Form->postLink(__d('cake', 'Delete'), array('controller' => $_details['controller'], 'action' => 'delete', ${$otherSingularVar}[$_details['primaryKey']]), null, __d('cake', 'Are you sure you want to delete', true).' #' . ${$otherSingularVar}[$_details['primaryKey']] . '?'). "\n"; + echo "\t\t\t</td>\n"; + echo "\t\t</tr>\n"; + endforeach; +?> + </table> +<?php endif; ?> + <div class="actions"> + <ul> + <li><?php echo $this->Html->link(__d('cake', "New %s", Inflector::humanize(Inflector::underscore($_alias))), array('controller' => $_details['controller'], 'action' => 'add')); ?> </li> + </ul> + </div> +</div> +<?php endforeach; ?> diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ThemeView.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ThemeView.php new file mode 100644 index 0000000..6b3617c --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ThemeView.php @@ -0,0 +1,31 @@ +<?php +/** + * A custom view class that is used for themeing + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('View', 'View'); + +/** + * Theme view class + * + * Stub class for 2.1 Compatibility + * + * @package Cake.View + */ +class ThemeView extends View { + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/View.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/View.php new file mode 100644 index 0000000..59ce0ac --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/View.php @@ -0,0 +1,1129 @@ +<?php +/** + * Methods for displaying presentation data in the view. + * + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package Cake.View + * @since CakePHP(tm) v 0.10.0.1076 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('HelperCollection', 'View'); +App::uses('AppHelper', 'View/Helper'); +App::uses('Router', 'Routing'); +App::uses('ViewBlock', 'View'); +App::uses('CakeEvent', 'Event'); +App::uses('CakeEventManager', 'Event'); +App::uses('CakeResponse', 'Network'); + +/** + * View, the V in the MVC triad. View interacts with Helpers and view variables passed + * in from the controller to render the results of the controller action. Often this is HTML, + * but can also take the form of JSON, XML, PDF's or streaming files. + * + * CakePHP uses a two-step-view pattern. This means that the view content is rendered first, + * and then inserted into the selected layout. This also means you can pass data from the view to the + * layout using `$this->set()` + * + * Since 2.1, the base View class also includes support for themes by default. Theme views are regular + * view files that can provide unique HTML and static assets. If theme views are not found for the + * current view the default app view files will be used. You can set `$this->theme = 'mytheme'` + * in your Controller to use the Themes. + * + * Example of theme path with `$this->theme = 'SuperHot';` Would be `app/View/Themed/SuperHot/Posts` + * + * @package Cake.View + * @property CacheHelper $Cache + * @property FormHelper $Form + * @property HtmlHelper $Html + * @property JsHelper $Js + * @property NumberHelper $Number + * @property PaginatorHelper $Paginator + * @property RssHelper $Rss + * @property SessionHelper $Session + * @property TextHelper $Text + * @property TimeHelper $Time + * @property ViewBlock $Blocks + */ +class View extends Object { + +/** + * Helpers collection + * + * @var HelperCollection + */ + public $Helpers; + +/** + * ViewBlock instance. + * + * @var ViewBlock + */ + public $Blocks; + +/** + * Name of the plugin. + * + * @link http://manual.cakephp.org/chapter/plugins + * @var string + */ + public $plugin = null; + +/** + * Name of the controller. + * + * @var string Name of controller + */ + public $name = null; + +/** + * Current passed params + * + * @var mixed + */ + public $passedArgs = array(); + +/** + * An array of names of built-in helpers to include. + * + * @var mixed A single name as a string or a list of names as an array. + */ + public $helpers = array('Html'); + +/** + * Path to View. + * + * @var string Path to View + */ + public $viewPath = null; + +/** + * Variables for the view + * + * @var array + */ + public $viewVars = array(); + +/** + * Name of view to use with this View. + * + * @var string + */ + public $view = null; + +/** + * Name of layout to use with this View. + * + * @var string + */ + public $layout = 'default'; + +/** + * Path to Layout. + * + * @var string Path to Layout + */ + public $layoutPath = null; + +/** + * Turns on or off Cake's conventional mode of applying layout files. On by default. + * Setting to off means that layouts will not be automatically applied to rendered views. + * + * @var boolean + */ + public $autoLayout = true; + +/** + * File extension. Defaults to Cake's template ".ctp". + * + * @var string + */ + public $ext = '.ctp'; + +/** + * Sub-directory for this view file. This is often used for extension based routing. + * Eg. With an `xml` extension, $subDir would be `xml/` + * + * @var string + */ + public $subDir = null; + +/** + * Theme name. + * + * @var string + */ + public $theme = null; + +/** + * Used to define methods a controller that will be cached. + * + * @see Controller::$cacheAction + * @var mixed + */ + public $cacheAction = false; + +/** + * Holds current errors for the model validation. + * + * @var array + */ + public $validationErrors = array(); + +/** + * True when the view has been rendered. + * + * @var boolean + */ + public $hasRendered = false; + +/** + * List of generated DOM UUIDs. + * + * @var array + */ + public $uuids = array(); + +/** + * An instance of a CakeRequest object that contains information about the current request. + * This object contains all the information about a request and several methods for reading + * additional information about the request. + * + * @var CakeRequest + */ + public $request; + +/** + * Reference to the Response object + * + * @var CakeResponse + */ + public $response; + +/** + * The Cache configuration View will use to store cached elements. Changing this will change + * the default configuration elements are stored under. You can also choose a cache config + * per element. + * + * @var string + * @see View::element() + */ + public $elementCache = 'default'; + +/** + * List of variables to collect from the associated controller. + * + * @var array + */ + protected $_passedVars = array( + 'viewVars', 'autoLayout', 'ext', 'helpers', 'view', 'layout', 'name', 'theme', + 'layoutPath', 'viewPath', 'request', 'plugin', 'passedArgs', 'cacheAction' + ); + +/** + * Scripts (and/or other <head /> tags) for the layout. + * + * @var array + */ + protected $_scripts = array(); + +/** + * Holds an array of paths. + * + * @var array + */ + protected $_paths = array(); + +/** + * Indicate that helpers have been loaded. + * + * @var boolean + */ + protected $_helpersLoaded = false; + +/** + * The names of views and their parents used with View::extend(); + * + * @var array + */ + protected $_parents = array(); + +/** + * The currently rendering view file. Used for resolving parent files. + * + * @var string + */ + protected $_current = null; + +/** + * Currently rendering an element. Used for finding parent fragments + * for elements. + * + * @var string + */ + protected $_currentType = ''; + +/** + * Content stack, used for nested templates that all use View::extend(); + * + * @var array + */ + protected $_stack = array(); + +/** + * Instance of the CakeEventManager this View object is using + * to dispatch inner events. Usually the manager is shared with + * the controller, so it it possible to register view events in + * the controller layer. + * + * @var CakeEventManager + */ + protected $_eventManager = null; + +/** + * The view file to be rendered, only used inside _execute() + */ + private $__viewFileName = null; + +/** + * Whether the event manager was already configured for this object + * + * @var boolean + */ + protected $_eventManagerConfigured = false; + + const TYPE_VIEW = 'view'; + const TYPE_ELEMENT = 'element'; + const TYPE_LAYOUT = 'layout'; + +/** + * Constructor + * + * @param Controller $controller A controller object to pull View::_passedVars from. + */ + public function __construct(Controller $controller = null) { + if (is_object($controller)) { + $count = count($this->_passedVars); + for ($j = 0; $j < $count; $j++) { + $var = $this->_passedVars[$j]; + $this->{$var} = $controller->{$var}; + } + $this->_eventManager = $controller->getEventManager(); + } + if (empty($this->request) && !($this->request = Router::getRequest(true))) { + $this->request = new CakeRequest(null, false); + $this->request->base = ''; + $this->request->here = $this->request->webroot = '/'; + } + if (is_object($controller) && isset($controller->response)) { + $this->response = $controller->response; + } else { + $this->response = new CakeResponse(array('charset' => Configure::read('App.encoding'))); + } + $this->Helpers = new HelperCollection($this); + $this->Blocks = new ViewBlock(); + parent::__construct(); + } + +/** + * Returns the CakeEventManager manager instance that is handling any callbacks. + * You can use this instance to register any new listeners or callbacks to the + * controller events, or create your own events and trigger them at will. + * + * @return CakeEventManager + */ + public function getEventManager() { + if (empty($this->_eventManager)) { + $this->_eventManager = new CakeEventManager(); + } + if (!$this->_eventManagerConfigured) { + $this->_eventManager->attach($this->Helpers); + $this->_eventManagerConfigured = true; + } + return $this->_eventManager; + } + +/** + * Renders a piece of PHP with provided parameters and returns HTML, XML, or any other string. + * + * This realizes the concept of Elements, (or "partial layouts") and the $params array is used to send + * data to be used in the element. Elements can be cached improving performance by using the `cache` option. + * + * @param string $name Name of template file in the/app/View/Elements/ folder, + * or `MyPlugin.template` to use the template element from MyPlugin. If the element + * is not found in the plugin, the normal view path cascade will be searched. + * @param array $data Array of data to be made available to the rendered view (i.e. the Element) + * @param array $options Array of options. Possible keys are: + * - `cache` - Can either be `true`, to enable caching using the config in View::$elementCache. Or an array + * If an array, the following keys can be used: + * - `config` - Used to store the cached element in a custom cache configuration. + * - `key` - Used to define the key used in the Cache::write(). It will be prefixed with `element_` + * - `plugin` - Load an element from a specific plugin. This option is deprecated, see below. + * - `callbacks` - Set to true to fire beforeRender and afterRender helper callbacks for this element. + * Defaults to false. + * @return string Rendered Element + * @deprecated The `$options['plugin']` is deprecated and will be removed in CakePHP 3.0. Use + * `Plugin.element_name` instead. + */ + public function element($name, $data = array(), $options = array()) { + $file = $plugin = $key = null; + $callbacks = false; + + if (isset($options['plugin'])) { + $name = Inflector::camelize($options['plugin']) . '.' . $name; + } + + if (isset($options['callbacks'])) { + $callbacks = $options['callbacks']; + } + + if (isset($options['cache'])) { + $underscored = null; + if ($plugin) { + $underscored = Inflector::underscore($plugin); + } + $keys = array_merge(array($underscored, $name), array_keys($options), array_keys($data)); + $caching = array( + 'config' => $this->elementCache, + 'key' => implode('_', $keys) + ); + if (is_array($options['cache'])) { + $defaults = array( + 'config' => $this->elementCache, + 'key' => $caching['key'] + ); + $caching = array_merge($defaults, $options['cache']); + } + $key = 'element_' . $caching['key']; + $contents = Cache::read($key, $caching['config']); + if ($contents !== false) { + return $contents; + } + } + + $file = $this->_getElementFilename($name); + + if ($file) { + if (!$this->_helpersLoaded) { + $this->loadHelpers(); + } + if ($callbacks) { + $this->getEventManager()->dispatch(new CakeEvent('View.beforeRender', $this, array($file))); + } + + $this->_currentType = self::TYPE_ELEMENT; + $element = $this->_render($file, array_merge($this->viewVars, $data)); + + if ($callbacks) { + $this->getEventManager()->dispatch(new CakeEvent('View.afterRender', $this, array($file, $element))); + } + if (isset($options['cache'])) { + Cache::write($key, $element, $caching['config']); + } + return $element; + } + $file = 'Elements' . DS . $name . $this->ext; + + if (Configure::read('debug') > 0) { + return __d('cake_dev', 'Element Not Found: %s', $file); + } + } + +/** + * Renders view for given view file and layout. + * + * Render triggers helper callbacks, which are fired before and after the view are rendered, + * as well as before and after the layout. The helper callbacks are called: + * + * - `beforeRender` + * - `afterRender` + * - `beforeLayout` + * - `afterLayout` + * + * If View::$autoRender is false and no `$layout` is provided, the view will be returned bare. + * + * View and layout names can point to plugin views/layouts. Using the `Plugin.view` syntax + * a plugin view/layout can be used instead of the app ones. If the chosen plugin is not found + * the view will be located along the regular view path cascade. + * + * @param string $view Name of view file to use + * @param string $layout Layout to use. + * @return string Rendered Element + * @throws CakeException if there is an error in the view. + */ + public function render($view = null, $layout = null) { + if ($this->hasRendered) { + return true; + } + if (!$this->_helpersLoaded) { + $this->loadHelpers(); + } + $this->Blocks->set('content', ''); + + if ($view !== false && $viewFileName = $this->_getViewFileName($view)) { + $this->_currentType = self::TYPE_VIEW; + $this->getEventManager()->dispatch(new CakeEvent('View.beforeRender', $this, array($viewFileName))); + $this->Blocks->set('content', $this->_render($viewFileName)); + $this->getEventManager()->dispatch(new CakeEvent('View.afterRender', $this, array($viewFileName))); + } + + if ($layout === null) { + $layout = $this->layout; + } + if ($layout && $this->autoLayout) { + $this->Blocks->set('content', $this->renderLayout('', $layout)); + } + $this->hasRendered = true; + return $this->Blocks->get('content'); + } + +/** + * Renders a layout. Returns output from _render(). Returns false on error. + * Several variables are created for use in layout. + * + * - `title_for_layout` - A backwards compatible place holder, you should set this value if you want more control. + * - `content_for_layout` - contains rendered view file + * - `scripts_for_layout` - Contains content added with addScript() as well as any content in + * the 'meta', 'css', and 'script' blocks. They are appended in that order. + * + * Deprecated features: + * + * - `$scripts_for_layout` is deprecated and will be removed in CakePHP 3.0. + * Use the block features instead. `meta`, `css` and `script` will be populated + * by the matching methods on HtmlHelper. + * - `$title_for_layout` is deprecated and will be removed in CakePHP 3.0 + * - `$content_for_layout` is deprecated and will be removed in CakePHP 3.0. + * Use the `content` block instead. + * + * @param string $content Content to render in a view, wrapped by the surrounding layout. + * @param string $layout Layout name + * @return mixed Rendered output, or false on error + * @throws CakeException if there is an error in the view. + */ + public function renderLayout($content, $layout = null) { + $layoutFileName = $this->_getLayoutFileName($layout); + if (empty($layoutFileName)) { + return $this->Blocks->get('content'); + } + + if (!$this->_helpersLoaded) { + $this->loadHelpers(); + } + if (empty($content)) { + $content = $this->Blocks->get('content'); + } + $this->getEventManager()->dispatch(new CakeEvent('View.beforeLayout', $this, array($layoutFileName))); + + $scripts = implode("\n\t", $this->_scripts); + $scripts .= $this->Blocks->get('meta') . $this->Blocks->get('css') . $this->Blocks->get('script'); + + $this->viewVars = array_merge($this->viewVars, array( + 'content_for_layout' => $content, + 'scripts_for_layout' => $scripts, + )); + + if (!isset($this->viewVars['title_for_layout'])) { + $this->viewVars['title_for_layout'] = Inflector::humanize($this->viewPath); + } + + $this->_currentType = self::TYPE_LAYOUT; + $this->Blocks->set('content', $this->_render($layoutFileName)); + + $this->getEventManager()->dispatch(new CakeEvent('View.afterLayout', $this, array($layoutFileName))); + return $this->Blocks->get('content'); + } + +/** + * Render cached view. Works in concert with CacheHelper and Dispatcher to + * render cached view files. + * + * @param string $filename the cache file to include + * @param string $timeStart the page render start time + * @return boolean Success of rendering the cached file. + */ + public function renderCache($filename, $timeStart) { + ob_start(); + include ($filename); + + if (Configure::read('debug') > 0 && $this->layout != 'xml') { + echo "<!-- Cached Render Time: " . round(microtime(true) - $timeStart, 4) . "s -->"; + } + $out = ob_get_clean(); + + if (preg_match('/^<!--cachetime:(\\d+)-->/', $out, $match)) { + if (time() >= $match['1']) { + @unlink($filename); + unset ($out); + return false; + } else { + if ($this->layout === 'xml') { + header('Content-type: text/xml'); + } + $commentLength = strlen('<!--cachetime:' . $match['1'] . '-->'); + return substr($out, $commentLength); + } + } + } + +/** + * Returns a list of variables available in the current View context + * + * @return array Array of the set view variable names. + */ + public function getVars() { + return array_keys($this->viewVars); + } + +/** + * Returns the contents of the given View variable(s) + * + * @param string $var The view var you want the contents of. + * @return mixed The content of the named var if its set, otherwise null. + * @deprecated Will be removed in 3.0 Use View::get() instead. + */ + public function getVar($var) { + return $this->get($var); + } + +/** + * Returns the contents of the given View variable or a block. + * Blocks are checked before view variables. + * + * @param string $var The view var you want the contents of. + * @return mixed The content of the named var if its set, otherwise null. + */ + public function get($var) { + if (!isset($this->viewVars[$var])) { + return null; + } + return $this->viewVars[$var]; + } + +/** + * Get the names of all the existing blocks. + * + * @return array An array containing the blocks. + * @see ViewBlock::keys() + */ + public function blocks() { + return $this->Blocks->keys(); + } + +/** + * Start capturing output for a 'block' + * + * @param string $name The name of the block to capture for. + * @return void + * @see ViewBlock::start() + */ + public function start($name) { + return $this->Blocks->start($name); + } + +/** + * Append to an existing or new block. Appending to a new + * block will create the block. + * + * @param string $name Name of the block + * @param string $value The content for the block. + * @return void + * @throws CakeException when you use non-string values. + * @see ViewBlock::append() + */ + public function append($name, $value = null) { + return $this->Blocks->append($name, $value); + } + +/** + * Set the content for a block. This will overwrite any + * existing content. + * + * @param string $name Name of the block + * @param string $value The content for the block. + * @return void + * @throws CakeException when you use non-string values. + * @see ViewBlock::assign() + */ + public function assign($name, $value) { + return $this->Blocks->set($name, $value); + } + +/** + * Fetch the content for a block. If a block is + * empty or undefined '' will be returned. + * + * @param string $name Name of the block + * @return The block content or '' if the block does not exist. + * @see ViewBlock::fetch() + */ + public function fetch($name) { + return $this->Blocks->get($name); + } + +/** + * End a capturing block. The compliment to View::start() + * + * @return void + * @see ViewBlock::start() + */ + public function end() { + return $this->Blocks->end(); + } + +/** + * Provides view or element extension/inheritance. Views can extends a + * parent view and populate blocks in the parent template. + * + * @param string $name The view or element to 'extend' the current one with. + * @return void + * @throws LogicException when you extend a view with itself or make extend loops. + * @throws LogicException when you extend an element which doesn't exist + */ + public function extend($name) { + if ($name[0] === '/' || $this->_currentType === self::TYPE_VIEW) { + $parent = $this->_getViewFileName($name); + } else { + switch ($this->_currentType) { + case self::TYPE_ELEMENT: + $parent = $this->_getElementFileName($name); + if (!$parent) { + list($plugin, $name) = $this->pluginSplit($name); + $paths = $this->_paths($plugin); + $defaultPath = $paths[0] . 'Elements' . DS; + throw new LogicException(__d( + 'cake_dev', + 'You cannot extend an element which does not exist (%s).', + $defaultPath . $name . $this->ext + )); + } + break; + case self::TYPE_LAYOUT: + $parent = $this->_getLayoutFileName($name); + break; + default: + $parent = $this->_getViewFileName($name); + } + } + + if ($parent == $this->_current) { + throw new LogicException(__d('cake_dev', 'You cannot have views extend themselves.')); + } + if (isset($this->_parents[$parent]) && $this->_parents[$parent] == $this->_current) { + throw new LogicException(__d('cake_dev', 'You cannot have views extend in a loop.')); + } + $this->_parents[$this->_current] = $parent; + } + +/** + * Adds a script block or other element to be inserted in $scripts_for_layout in + * the `<head />` of a document layout + * + * @param string $name Either the key name for the script, or the script content. Name can be used to + * update/replace a script element. + * @param string $content The content of the script being added, optional. + * @return void + * @deprecated Will be removed in 3.0. Supersceeded by blocks functionality. + * @see View::start() + */ + public function addScript($name, $content = null) { + if (empty($content)) { + if (!in_array($name, array_values($this->_scripts))) { + $this->_scripts[] = $name; + } + } else { + $this->_scripts[$name] = $content; + } + } + +/** + * Generates a unique, non-random DOM ID for an object, based on the object type and the target URL. + * + * @param string $object Type of object, i.e. 'form' or 'link' + * @param string $url The object's target URL + * @return string + */ + public function uuid($object, $url) { + $c = 1; + $url = Router::url($url); + $hash = $object . substr(md5($object . $url), 0, 10); + while (in_array($hash, $this->uuids)) { + $hash = $object . substr(md5($object . $url . $c), 0, 10); + $c++; + } + $this->uuids[] = $hash; + return $hash; + } + +/** + * Allows a template or element to set a variable that will be available in + * a layout or other element. Analogous to Controller::set(). + * + * @param string|array $one A string or an array of data. + * @param string|array $two Value in case $one is a string (which then works as the key). + * Unused if $one is an associative array, otherwise serves as the values to $one's keys. + * @return void + */ + public function set($one, $two = null) { + $data = null; + if (is_array($one)) { + if (is_array($two)) { + $data = array_combine($one, $two); + } else { + $data = $one; + } + } else { + $data = array($one => $two); + } + if ($data == null) { + return false; + } + $this->viewVars = $data + $this->viewVars; + } + +/** + * Magic accessor for helpers. Provides access to attributes that were deprecated. + * + * @param string $name Name of the attribute to get. + * @return mixed + */ + public function __get($name) { + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name}; + case 'action': + return $this->request->params['action']; + case 'params': + return $this->request; + case 'output': + return $this->Blocks->get('content'); + } + if (isset($this->Helpers->{$name})) { + $this->{$name} = $this->Helpers->{$name}; + return $this->Helpers->{$name}; + } + return $this->{$name}; + } + +/** + * Magic accessor for deprecated attributes. + * + * @param string $name Name of the attribute to set. + * @param string $value Value of the attribute to set. + * @return mixed + */ + public function __set($name, $value) { + switch ($name) { + case 'output': + return $this->Blocks->set('content', $value); + default: + $this->{$name} = $value; + } + } + +/** + * Magic isset check for deprecated attributes. + * + * @param string $name Name of the attribute to check. + * @return boolean + */ + public function __isset($name) { + if (isset($this->{$name})) { + return true; + } + $magicGet = array('base', 'here', 'webroot', 'data', 'action', 'params', 'output'); + if (in_array($name, $magicGet)) { + return $this->__get($name) !== null; + } + return false; + } + +/** + * Interact with the HelperCollection to load all the helpers. + * + * @return void + */ + public function loadHelpers() { + $helpers = HelperCollection::normalizeObjectArray($this->helpers); + foreach ($helpers as $name => $properties) { + list($plugin, $class) = pluginSplit($properties['class']); + $this->{$class} = $this->Helpers->load($properties['class'], $properties['settings']); + } + $this->_helpersLoaded = true; + } + +/** + * Renders and returns output for given view filename with its + * array of data. Handles parent/extended views. + * + * @param string $viewFile Filename of the view + * @param array $data Data to include in rendered view. If empty the current View::$viewVars will be used. + * @return string Rendered output + * @throws CakeException when a block is left open. + */ + protected function _render($viewFile, $data = array()) { + if (empty($data)) { + $data = $this->viewVars; + } + $this->_current = $viewFile; + $initialBlocks = count($this->Blocks->unclosed()); + + $this->getEventManager()->dispatch(new CakeEvent('View.beforeRenderFile', $this, array($viewFile))); + $content = $this->_evaluate($viewFile, $data); + $afterEvent = new CakeEvent('View.afterRenderFile', $this, array($viewFile, $content)); + //TODO: For BC puporses, set extra info in the event object. Remove when appropriate + $afterEvent->modParams = 1; + $this->getEventManager()->dispatch($afterEvent); + $content = $afterEvent->data[1]; + + if (isset($this->_parents[$viewFile])) { + $this->_stack[] = $this->fetch('content'); + $this->assign('content', $content); + + $content = $this->_render($this->_parents[$viewFile]); + $this->assign('content', array_pop($this->_stack)); + } + + $remainingBlocks = count($this->Blocks->unclosed()); + + if ($initialBlocks !== $remainingBlocks) { + throw new CakeException(__d('cake_dev', 'The "%s" block was left open. Blocks are not allowed to cross files.', $this->Blocks->active())); + } + + return $content; + } + +/** + * Sandbox method to evaluate a template / view script in. + * + * @param string $viewFn Filename of the view + * @param array $___dataForView Data to include in rendered view. + * If empty the current View::$viewVars will be used. + * @return string Rendered output + */ + protected function _evaluate($viewFile, $dataForView) { + $this->__viewFile = $viewFile; + extract($dataForView); + ob_start(); + + include $this->__viewFile; + + unset($this->_viewFile); + return ob_get_clean(); + } + +/** + * Loads a helper. Delegates to the `HelperCollection::load()` to load the helper + * + * @param string $helperName Name of the helper to load. + * @param array $settings Settings for the helper + * @return Helper a constructed helper object. + * @see HelperCollection::load() + */ + public function loadHelper($helperName, $settings = array()) { + return $this->Helpers->load($helperName, $settings); + } + +/** + * Returns filename of given action's template file (.ctp) as a string. + * CamelCased action names will be under_scored! This means that you can have + * LongActionNames that refer to long_action_names.ctp views. + * + * @param string $name Controller action to find template filename for + * @return string Template filename + * @throws MissingViewException when a view file could not be found. + */ + protected function _getViewFileName($name = null) { + $subDir = null; + + if (!is_null($this->subDir)) { + $subDir = $this->subDir . DS; + } + + if ($name === null) { + $name = $this->view; + } + $name = str_replace('/', DS, $name); + list($plugin, $name) = $this->pluginSplit($name); + + if (strpos($name, DS) === false && $name[0] !== '.') { + $name = $this->viewPath . DS . $subDir . Inflector::underscore($name); + } elseif (strpos($name, DS) !== false) { + if ($name[0] === DS || $name[1] === ':') { + if (is_file($name)) { + return $name; + } + $name = trim($name, DS); + } elseif ($name[0] === '.') { + $name = substr($name, 3); + } elseif (!$plugin || $this->viewPath !== $this->name) { + $name = $this->viewPath . DS . $subDir . $name; + } + } + $paths = $this->_paths($plugin); + $exts = $this->_getExtensions(); + foreach ($exts as $ext) { + foreach ($paths as $path) { + if (file_exists($path . $name . $ext)) { + return $path . $name . $ext; + } + } + } + $defaultPath = $paths[0]; + + if ($this->plugin) { + $pluginPaths = App::path('plugins'); + foreach ($paths as $path) { + if (strpos($path, $pluginPaths[0]) === 0) { + $defaultPath = $path; + break; + } + } + } + throw new MissingViewException(array('file' => $defaultPath . $name . $this->ext)); + } + +/** + * Splits a dot syntax plugin name into its plugin and filename. + * If $name does not have a dot, then index 0 will be null. + * It checks if the plugin is loaded, else filename will stay unchanged for filenames containing dot + * + * @param string $name The name you want to plugin split. + * @param boolean $fallback If true uses the plugin set in the current CakeRequest when parsed plugin is not loaded + * @return array Array with 2 indexes. 0 => plugin name, 1 => filename + */ + public function pluginSplit($name, $fallback = true) { + $plugin = null; + list($first, $second) = pluginSplit($name); + if (CakePlugin::loaded($first) === true) { + $name = $second; + $plugin = $first; + } + if (isset($this->plugin) && !$plugin && $fallback) { + $plugin = $this->plugin; + } + return array($plugin, $name); + } + +/** + * Returns layout filename for this template as a string. + * + * @param string $name The name of the layout to find. + * @return string Filename for layout file (.ctp). + * @throws MissingLayoutException when a layout cannot be located + */ + protected function _getLayoutFileName($name = null) { + if ($name === null) { + $name = $this->layout; + } + $subDir = null; + + if (!is_null($this->layoutPath)) { + $subDir = $this->layoutPath . DS; + } + list($plugin, $name) = $this->pluginSplit($name); + $paths = $this->_paths($plugin); + $file = 'Layouts' . DS . $subDir . $name; + + $exts = $this->_getExtensions(); + foreach ($exts as $ext) { + foreach ($paths as $path) { + if (file_exists($path . $file . $ext)) { + return $path . $file . $ext; + } + } + } + throw new MissingLayoutException(array('file' => $paths[0] . $file . $this->ext)); + } + +/** + * Get the extensions that view files can use. + * + * @return array Array of extensions view files use. + */ + protected function _getExtensions() { + $exts = array($this->ext); + if ($this->ext !== '.ctp') { + array_push($exts, '.ctp'); + } + return $exts; + } + +/** + * Finds an element filename, returns false on failure. + * + * @param string $name The name of the element to find. + * @return mixed Either a string to the element filename or false when one can't be found. + */ + protected function _getElementFileName($name) { + list($plugin, $name) = $this->pluginSplit($name); + + $paths = $this->_paths($plugin); + $exts = $this->_getExtensions(); + foreach ($exts as $ext) { + foreach ($paths as $path) { + if (file_exists($path . 'Elements' . DS . $name . $ext)) { + return $path . 'Elements' . DS . $name . $ext; + } + } + } + return false; + } + +/** + * Return all possible paths to find view files in order + * + * @param string $plugin Optional plugin name to scan for view files. + * @param boolean $cached Set to true to force a refresh of view paths. + * @return array paths + */ + protected function _paths($plugin = null, $cached = true) { + if ($plugin === null && $cached === true && !empty($this->_paths)) { + return $this->_paths; + } + $paths = array(); + $viewPaths = App::path('View'); + $corePaths = array_merge(App::core('View'), App::core('Console/Templates/skel/View')); + + if (!empty($plugin)) { + $count = count($viewPaths); + for ($i = 0; $i < $count; $i++) { + if (!in_array($viewPaths[$i], $corePaths)) { + $paths[] = $viewPaths[$i] . 'Plugin' . DS . $plugin . DS; + } + } + $paths = array_merge($paths, App::path('View', $plugin)); + } + + $paths = array_unique(array_merge($paths, $viewPaths)); + if (!empty($this->theme)) { + $themePaths = array(); + foreach ($paths as $path) { + if (strpos($path, DS . 'Plugin' . DS) === false) { + if ($plugin) { + $themePaths[] = $path . 'Themed' . DS . $this->theme . DS . 'Plugin' . DS . $plugin . DS; + } + $themePaths[] = $path . 'Themed' . DS . $this->theme . DS; + } + } + $paths = array_merge($themePaths, $paths); + } + $paths = array_merge($paths, $corePaths); + if ($plugin !== null) { + return $paths; + } + return $this->_paths = $paths; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ViewBlock.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ViewBlock.php new file mode 100644 index 0000000..5636d74 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ViewBlock.php @@ -0,0 +1,158 @@ +<?php +/** + * PHP 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @since CakePHP(tm) v2.1 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +/** + * ViewBlock implements the concept of Blocks or Slots in the View layer. + * Slots or blocks are combined with extending views and layouts to afford slots + * of content that are present in a layout or parent view, but are defined by the child + * view or elements used in the view. + * + * @package Cake.View + */ +class ViewBlock { + +/** + * Block content. An array of blocks indexed by name. + * + * @var array + */ + protected $_blocks = array(); + +/** + * The active blocks being captured. + * + * @var array + */ + protected $_active = array(); + +/** + * Start capturing output for a 'block' + * + * Blocks allow you to create slots or blocks of dynamic content in the layout. + * view files can implement some or all of a layout's slots. + * + * You can end capturing blocks using View::end(). Blocks can be output + * using View::get(); + * + * @param string $name The name of the block to capture for. + * @return void + */ + public function start($name) { + $this->_active[] = $name; + ob_start(); + } + +/** + * End a capturing block. The compliment to ViewBlock::start() + * + * @return void + * @see ViewBlock::start() + */ + public function end() { + if (!empty($this->_active)) { + $active = end($this->_active); + $content = ob_get_clean(); + if (!isset($this->_blocks[$active])) { + $this->_blocks[$active] = ''; + } + $this->_blocks[$active] .= $content; + array_pop($this->_active); + } + } + +/** + * Append to an existing or new block. Appending to a new + * block will create the block. + * + * Calling append() without a value will create a new capturing + * block that needs to be finished with View::end(). The content + * of the new capturing context will be added to the existing block context. + * + * @param string $name Name of the block + * @param string $value The content for the block. + * @return void + * @throws CakeException when you use non-string values. + */ + public function append($name, $value = null) { + if (isset($value)) { + if (!is_string($value)) { + throw new CakeException(__d('cake_dev', '$value must be a string.')); + } + if (!isset($this->_blocks[$name])) { + $this->_blocks[$name] = ''; + } + $this->_blocks[$name] .= $value; + } else { + $this->start($name); + } + } + +/** + * Set the content for a block. This will overwrite any + * existing content. + * + * @param string $name Name of the block + * @param string $value The content for the block. + * @return void + * @throws CakeException when you use non-string values. + */ + public function set($name, $value) { + if (!is_string($value)) { + throw new CakeException(__d('cake_dev', 'Blocks can only contain strings.')); + } + $this->_blocks[$name] = $value; + } + +/** + * Get the content for a block. + * + * @param string $name Name of the block + * @return The block content or '' if the block does not exist. + */ + public function get($name) { + if (!isset($this->_blocks[$name])) { + return ''; + } + return $this->_blocks[$name]; + } + +/** + * Get the names of all the existing blocks. + * + * @return array An array containing the blocks. + */ + public function keys() { + return array_keys($this->_blocks); + } + +/** + * Get the name of the currently open block. + * + * @return mixed Either null or the name of the last open block. + */ + public function active() { + return end($this->_active); + } + +/** + * Get the names of the unclosed/active blocks. + * + * @return array An array of unclosed blocks. + */ + public function unclosed() { + return $this->_active; + } + +} diff --git a/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/XmlView.php b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/XmlView.php new file mode 100644 index 0000000..f89efa6 --- /dev/null +++ b/poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/XmlView.php @@ -0,0 +1,113 @@ +<?php +/** + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::uses('View', 'View'); +App::uses('Xml', 'Utility'); + +/** + * A view class that is used for creating XML responses. + * + * By setting the '_serialize' key in your controller, you can specify a view variable + * that should be serialized to XML and used as the response for the request. + * This allows you to omit views + layouts, if your just need to emit a single view + * variable as the XML response. + * + * In your controller, you could do the following: + * + * `$this->set(array('posts' => $posts, '_serialize' => 'posts'));` + * + * When the view is rendered, the `$posts` view variable will be serialized + * into XML. + * + * **Note** The view variable you specify must be compatible with Xml::fromArray(). + * + * You can also define `'_serialize'` as an array. This will create an additional + * top level element named `<response>` containing all the named view variables: + * + * {{{ + * $this->set(compact('posts', 'users', 'stuff')); + * $this->set('_serialize', array('posts', 'users')); + * }}} + * + * The above would generate a XML object that looks like: + * + * `<response><posts>...</posts><users>...</users></response>` + * + * If you don't use the `_serialize` key, you will need a view. You can use extended + * views to provide layout like functionality. + * + * @package Cake.View + * @since CakePHP(tm) v 2.1.0 + */ +class XmlView extends View { + +/** + * The subdirectory. XML views are always in xml. + * + * @var string + */ + public $subDir = 'xml'; + +/** + * Constructor + * + * @param Controller $controller + */ + public function __construct(Controller $controller = null) { + parent::__construct($controller); + + if (isset($controller->response) && $controller->response instanceof CakeResponse) { + $controller->response->type('xml'); + } + } + +/** + * Render a XML view. + * + * Uses the special '_serialize' parameter to convert a set of + * view variables into a XML response. Makes generating simple + * XML responses very easy. You can omit the '_serialize' parameter, + * and use a normal view + layout as well. + * + * @param string $view The view being rendered. + * @param string $layout The layout being rendered. + * @return string The rendered view. + */ + public function render($view = null, $layout = null) { + if (isset($this->viewVars['_serialize'])) { + $serialize = $this->viewVars['_serialize']; + if (is_array($serialize)) { + $data = array('response' => array()); + foreach ($serialize as $key) { + $data['response'][$key] = $this->viewVars[$key]; + } + } else { + $data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null; + if (is_array($data) && Set::numeric(array_keys($data))) { + $data = array('response' => array($serialize => $data)); + } + } + $content = Xml::fromArray($data)->asXML(); + return $content; + } + if ($view !== false && $viewFileName = $this->_getViewFileName($view)) { + if (!$this->_helpersLoaded) { + $this->loadHelpers(); + } + $content = $this->_render($viewFileName); + $this->Blocks->set('content', (string)$content); + return $content; + } + } + +} |