From 6dfd5d507d9863f987b30b0a5ab4268aea2ed875 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Thu, 2 Aug 2012 11:09:40 +0000 Subject: J'étais parti sur un download pourri de Cake. Les gars on abusé sur GitHub. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2012-php-weave/trunk@7 d972a294-176a-4cf9-8ea1-fcd5b0c30f5c --- .../Cake/View/Elements/exception_stack_trace.ctp | 75 + .../lib/Cake/View/Elements/sql_dump.ctp | 74 + .../lib/Cake/View/Errors/fatal_error.ctp | 35 + .../lib/Cake/View/Errors/missing_action.ctp | 42 + .../lib/Cake/View/Errors/missing_behavior.ctp | 40 + .../lib/Cake/View/Errors/missing_component.ctp | 40 + .../lib/Cake/View/Errors/missing_connection.ctp | 36 + .../lib/Cake/View/Errors/missing_controller.ctp | 40 + .../lib/Cake/View/Errors/missing_database.ctp | 33 + .../lib/Cake/View/Errors/missing_datasource.ctp | 30 + .../Cake/View/Errors/missing_datasource_config.ctp | 29 + .../lib/Cake/View/Errors/missing_helper.ctp | 40 + .../lib/Cake/View/Errors/missing_layout.ctp | 33 + .../lib/Cake/View/Errors/missing_plugin.ctp | 45 + .../lib/Cake/View/Errors/missing_table.ctp | 29 + .../lib/Cake/View/Errors/missing_view.ctp | 33 + .../lib/Cake/View/Errors/pdo_error.ctp | 38 + .../lib/Cake/View/Errors/private_action.ctp | 29 + .../lib/Cake/View/Errors/scaffold_error.ctp | 36 + .../lib/Cake/View/Helper.php | 914 +++++++ .../lib/Cake/View/Helper/CacheHelper.php | 321 +++ .../lib/Cake/View/Helper/FormHelper.php | 2604 ++++++++++++++++++++ .../lib/Cake/View/Helper/HtmlHelper.php | 1214 +++++++++ .../lib/Cake/View/Helper/JqueryEngineHelper.php | 361 +++ .../lib/Cake/View/Helper/JsBaseEngineHelper.php | 592 +++++ .../lib/Cake/View/Helper/JsHelper.php | 434 ++++ .../lib/Cake/View/Helper/MootoolsEngineHelper.php | 376 +++ .../lib/Cake/View/Helper/NumberHelper.php | 149 ++ .../lib/Cake/View/Helper/PaginatorHelper.php | 901 +++++++ .../lib/Cake/View/Helper/PrototypeEngineHelper.php | 370 +++ .../lib/Cake/View/Helper/RssHelper.php | 345 +++ .../lib/Cake/View/Helper/SessionHelper.php | 163 ++ .../lib/Cake/View/Helper/TextHelper.php | 277 +++ .../lib/Cake/View/Helper/TimeHelper.php | 458 ++++ .../lib/Cake/View/HelperCollection.php | 203 ++ .../lib/Cake/View/JsonView.php | 108 + .../lib/Cake/View/MediaView.php | 238 ++ .../lib/Cake/View/ScaffoldView.php | 91 + .../lib/Cake/View/Scaffolds/form.ctp | 51 + .../lib/Cake/View/Scaffolds/index.ctp | 94 + .../lib/Cake/View/Scaffolds/view.ctp | 146 ++ .../lib/Cake/View/ThemeView.php | 31 + .../lib/Cake/View/View.php | 1129 +++++++++ .../lib/Cake/View/ViewBlock.php | 158 ++ .../lib/Cake/View/XmlView.php | 113 + 45 files changed, 12598 insertions(+) create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/exception_stack_trace.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Elements/sql_dump.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/fatal_error.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_action.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_behavior.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_component.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_connection.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_controller.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_database.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_datasource_config.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_helper.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_layout.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_plugin.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_table.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/missing_view.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/pdo_error.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/private_action.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Errors/scaffold_error.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/CacheHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/FormHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/HtmlHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JqueryEngineHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsBaseEngineHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/JsHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/MootoolsEngineHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/NumberHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PaginatorHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/PrototypeEngineHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/RssHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/SessionHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TextHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Helper/TimeHelper.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/HelperCollection.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/JsonView.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/MediaView.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ScaffoldView.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/form.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/index.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/Scaffolds/view.ctp create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ThemeView.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/View.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/ViewBlock.php create mode 100644 poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View/XmlView.php (limited to 'poc/poc02-compiling-cake/src/vendor/cakephp-2.2.1-0-gcc44130/lib/Cake/View') 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 @@ + +

Stack Trace

+ + 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 @@ +getLog(); + endforeach; +endif; + +if ($noLogs || isset($_forced_from_dbo_)): + foreach ($logs as $source => $logInfo): + $text = $logInfo['count'] > 1 ? 'queries' : 'query'; + printf( + '', + preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true)) + ); + printf('', $source, $logInfo['count'], $text, $logInfo['time']); + ?> + + + + + $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 "\n"; + endforeach; + ?> +
(%s) %s %s took %s ms
NrQueryErrorAffectedNum. rowsTook (ms)
" . ($k + 1) . "" . h($i['query']) . "{$i['error']}{$i['affected']}{$i['numRows']}{$i['took']}
+ Encountered unexpected $logs cannot generate SQL log

'; +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 @@ + +

+

+ : + getMessage()); ?> +
+ + : + getFile()); ?> +
+ + : + getLine()); ?> +

+

+ : + +

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 @@ + +

+ : + ' . $action . '', '' . $controller . ''); ?> +

+

+ : + ' . $controller . '::', '' . $action . '()', APP_DIR . DS . 'Controller' . DS . $controller . '.php'); ?> +

+
+<?php
+class  extends AppController {
+
+
+	public function () {
+
+	}
+
+}
+
+

+ : + +

+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 @@ + +

+

+ : + ' . $pluginDot . $class . ''); ?> +

+

+ : + ' . $class . '', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'Model' . DS . 'Behavior' . DS . $class . '.php'); ?> +

+
+<?php
+class  extends ModelBehavior {
+
+}
+
+

+ : + +

+ +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 @@ + +

+

+ : + ' . $pluginDot . $class . ''); ?> +

+

+ : + ' . $class . '', (empty($plugin) ? APP_DIR : CakePlugin::path($plugin)) . DS . 'Controller' . DS . 'Component' . DS . $class . '.php'); ?> +

+
+<?php
+class  extends Component {
+
+}
+
+

+ : + +

+ +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 @@ + +

+

+ : + +

+ +

+ : + +

+ +

+ : + +

+ +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 @@ + +

+

+ : + ' . $pluginDot . $class . ''); ?> +

+

+ : + ' . $class . '', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'Controller' . DS . $class . '.php'); ?> +

+
+<?php
+class AppController {
+
+}
+
+

+ : + +

+ +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 @@ + +

+

+ : + +

+

+ : + +

+

+ : + +

+ +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 @@ + +

+

+ : + ' . $pluginDot . $class . ''); ?> +

+

+ : + +

+ +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 @@ + +

+

+ : + ' . $config . ''); ?> +

+

+ : + +

+ +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 @@ + +

+

+ : + ' . $pluginDot . $class . ''); ?> +

+

+ : + ' . $class . '', (empty($plugin) ? APP_DIR . DS : CakePlugin::path($plugin)) . 'View' . DS . 'Helper' . DS . $class . '.php'); ?> +

+
+<?php
+class  extends AppHelper {
+
+}
+
+

+ : + +

+ +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 @@ + +

+

+ : + ' . $file . ''); ?> +

+

+ : + ' . $file . ''); ?> +

+

+ : + +

+ +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 @@ + +

+

+ : + ' . $plugin . ''); ?> +

+

+ : + +

+
+<?php
+CakePlugin::load('');
+
+
+

+ : + +

+
+CakePlugin::loadAll();
+
+

+ : + +

+ +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 @@ + +

+

+ : + ' . $table . '', '' . $class . '', '' . $ds . ''); ?> +

+

+ : + +

+ +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 @@ + +

+

+ : + ' . Inflector::camelize($this->request->controller) . 'Controller::', '' . $this->request->action . '()'); ?> +

+

+ : + +

+

+ : + +

+ +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 @@ + +

+

+ : + getMessage()); ?> +

+queryString)) : ?> +

+ : + queryString; ?> +

+ +params)) : ?> + : + params); ?> + +

+ : + +

+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 @@ + +

+

+ : + ' . $controller . '::', '' . $action . '()'); ?> +

+

+ : + +

+ +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
+function _scaffoldError() {
+ +} + +
+ +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 @@ + 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('#]*>#i', "", $this->_cleaned); + do { + $oldstring = $this->_cleaned; + $this->_cleaned = preg_replace('#]*>#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 @@ +` in views + * + * @var array + */ + protected $_replace = array(); + +/** + * Array of string that are replace with there var replace above. + * The strings are any content inside `` 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('//', '', $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('//', 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('/((?<=)[\\s\\S]*?(?=))/i', $cache, $outputResult, PREG_PATTERN_ORDER); + preg_match_all('/(?<=)([\\s\\S]*?)(?=)/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('', $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('##', '', $content); + } + +/** + * Parse the output and replace cache tags + * + * @param string $cache Output to replace content in. + * @return string with all replacements made to + */ + 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 = '_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)/", "", $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 @@ + 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')
value="save" name="Whatever" + * array('label' => 'save', 'name' => 'Whatever', 'div' => array('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
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'); + * + * }}} + * + * Custom text: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish'); + * + * }}} + * + * Custom class name: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish', 'required'); + * + * }}} + * + * Custom attributes: + * + * {{{ + * echo $this->Form->label('Post.published', 'Publish', array( + * 'for' => 'post-publish' + * )); + * + * }}} + * + * @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 `` while + * `$this->Form->range();` will create `` + * + * ### Usage + * + * `$this->Form->search('User.query', array('value' => 'test'));` + * + * Will make an input like: + * + * `` + * + * 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 `', + 'image' => '', + 'tableheader' => '%s', + 'tableheaderrow' => '%s', + 'tablecell' => '%s', + 'tablerow' => '%s', + 'block' => '%s
', + 'blockstart' => '', + 'blockend' => '
', + 'tag' => '<%s%s>%s', + 'tagstart' => '<%s%s>', + 'tagend' => '', + 'tagselfclosing' => '<%s%s/>', + 'para' => '%s

', + 'parastart' => '', + 'label' => '', + 'fieldset' => '%s', + 'fieldsetstart' => '
%s', + 'fieldsetend' => '
', + 'legend' => '%s', + 'css' => '', + 'style' => '', + 'charset' => '', + 'ul' => '%s', + 'ol' => '%s', + 'li' => '%s', + 'error' => '%s
', + 'javascriptblock' => '', + 'javascriptstart' => '', + 'javascriptend' => '' + ); + +/** + * 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' => '', + 'html4-trans' => '', + 'html4-frame' => '', + 'html5' => '', + 'xhtml-strict' => '', + 'xhtml-trans' => '', + 'xhtml-frame' => '', + 'xhtml11' => '' + ); + +/** + * 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 `` 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 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 `` 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 or