app::import('Sanitize');
class AppModel extends Model {
var $actsAs = array(
+ 'Collectionable.options',
'Cakeplus.ValidationErrorI18n',
'Cakeplus.AddValidationRule',
'SanitizePlus',
--- /dev/null
+# Collectionable Plugin #
+
+## Introduction ##
+This is a utility plugin for CakePHP. This helps managing find options, virtualFields and validations.
+
+## Setup ##
+- Define $options(such a property name can be modified by configure) for Options Behavior
+- Define $virtualFieldsCollection(such a property name can be modified by configure) for VirtualFields Behavior
+- Define 'Validation'(such a config name can be modified by configure) section into Configure for ConfigValidationBehavior
+- Define $validate{PatternName}, like $validateAdd, same structure with $validate, for MultiValidationBehavior
+
+## Sample code ##
+
+### OptionsBehavior ###
+
+Here is a simple Post Model.
+ class Post extends AppModel {
+ var $hasMany = array('Comment');
+ var $hasOne = array('Status');
+
+ var $acsAs = array('Collectionable.options');
+ var $defaultOption = true; // or string like 'default'
+
+ var $options =array(
+ 'default' => array(
+ 'contain' => array(
+ 'Comment',
+ 'Status',
+ ),
+ 'limit' => 10,
+ ),
+ 'published' => array(
+ 'condtiions' => array('Status.published' => true),
+ ),
+ 'recent' => array(
+ 'order' => ('Post.updated DESC'),
+ ),
+ 'rss' => array(
+ 'limit' => 15,
+ ),
+ 'unlimited' => array(
+ 'limit' => null,
+ ),
+ 'index' => array(
+ // You can do sub merging
+ 'options' => array(
+ 'published',
+ 'recent',
+ ),
+ ),
+ );
+ }
+
+You can use them by like:
+ class PostsController extends AppController {
+ function index() {
+ $this->paginate = $this->Post->options('index');
+ $this->set('posts', $this->paginate());
+ }
+
+ function rss() {
+ $this->paginate = $this->Post->options('index', 'rss'); // multiple merging at run time;
+ $this->set('posts', $this->paginate());
+ }
+
+ function all_in_one_page() {
+ // you can use "options" attribute wihtin finding options
+ $posts = $this->Post->find('all', array('options' => array('index', 'unlimited')));
+ $this->set(compact('posts'));
+ }
+ }
+
+To see more syntax, you would look at [the test case](http://github.com/hiromi2424/Collectionable/blob/master/tests/cases/behaviors/options.test.php) or [the code](http://github.com/hiromi2424/Collectionable/blob/master/models/behaviors/options.php).
+
+### VirtualFieldsBehavior ###
+
+This sample uses [MatchableBehavior](http://github.com/hiromi2424/MatchableBehavior).
+
+ class User extends AppModel {
+ var $hasMany = array('Post');
+ var $actsAs = array('Collectionable.VirtualFields', 'Matchable');
+
+ var $virtualFields = array(
+ 'full_name' => "CONCAT(User.first_name, ' ', User.last_name)",
+ );
+ var $virtualFieldsCollection = array(
+ 'posts_count' => 'COUNT(Post.id)',
+ 'amount_used' => 'SUM(Post.volume)',
+ );
+ }
+
+You can use them by like:
+
+
+ class UsersController extends AppController {
+ function admin_index() {
+ // Hey, you may feel like using OptionsBehavior :P
+ $jointo = array('Post');
+ $group = 'User.id';
+ $virtualFields = array('posts_count', 'amount_used'); // key of collections
+ $this->paginate = compact('jointo', 'group', 'virtualFields');
+ $this->set('users', $this->paginate());
+ }
+
+ function profile() {
+ $virtualFields = array('full_name' => false); // disable virtualFields
+ $user = $this->User->find('first', compact('virtualFields'));
+ $this->set(compact('user'));
+ }
+ }
+
+### ConfigValidationBehavior ###
+
+
+ class User extends AppModel {
+ var $actsAs = array('Collectionable.ConfigValidation');
+
+ var $validate = array(
+ 'nickname' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'min' => array(
+ 'rule' => array('minlength'),
+ 'message' => 'I said more than %s!!',
+ ),
+ ),
+ 'email' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'among' => array(
+ 'rule' => array('between'),
+ ),
+ ),
+ );
+ }
+
+You can set validation parameters, messages from Configuration:
+
+
+ Configure::write('Validation', array(
+ 'parameters' => array(
+ 'User' => array(
+ 'nickname' => array(
+ 'min' => 3,
+ ),
+ 'email' => array(
+ 'among' => array(16, 256)
+ ),
+ ),
+ ),
+ 'messages' => array(
+ 'default' => array(
+ 'required' => 'you need to enter.',
+ 'min' => '%s characters needed',
+ ),
+ 'User' => array(
+ 'email' => array(
+ 'required' => 'are you kidding me or misreading?',
+ ),
+ ),
+ ),
+ ));
+
+
+Note that priority is "hard coded on your model" > "specifying Model and field" > "default".
+But if you turn $overwrite property on, "specifying Model and field" forces to overwrite("default" does not).
+
+
+### MultiValidationBehavior ###
+
+
+ class User extends AppModel {
+
+ var $actsAs = array('Collectionable.MultiValidation');
+
+ var $validate = array(
+ 'password_raw' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'minlength' => array(
+ 'rule' => array('minlength', 6),
+ ),
+ ),
+ );
+
+ // note that $validateprofile is invalid with 'profile'
+ var $validateProfile = array(
+ 'nickname' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'maxlength' => array(
+ 'rule' => array('maxlength', 40),
+ ),
+ ),
+ );
+
+ var $validateRequireEmail = array(
+ 'email' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'email' => array(
+ 'rule' => array('email'),
+ ),
+ ),
+ );
+
+ var $validatePasswordConfirm = array(
+ 'password_confirm' => array(
+ 'required' => array(
+ 'rule' => array('notempty'),
+ ),
+ 'confirm_password' => array(
+ 'rule' => array('confirm_password'),
+ ),
+ ),
+ );
+
+ // You can set validation pattern on demand:
+ function add($data, $validate = true, $options = array()) {
+ $this->useValidationSet('requireEmail');
+ $this->create();
+ return $this->save($data, $validate, $options);
+ }
+
+ // You can dsiable default $validate with second argument as false:
+ function edit($data, $validate = true, $options = array()) {
+ $this->useValidationSet('profile', false);
+ return $this->save($data, $validate, $options);
+ }
+
+ // You can specify two and more rule sets. these will be merged
+ function resetEmail($data) {
+ $this->useValidationSet(array('requireEmail', 'passwordConfirm'));
+ }
+
+ function confirm_password() {
+ // confirm password
+ }
+
+ }
+
+
+## Thanks ##
+- [nojimage](http://github.com/nojimage) created [base of this plugin](http://github.com/nojimage/paging)
+
+
+## License
+
+Licensed under The MIT License.
+Redistributions of files must retain the above copyright notice.
+
+
+Copyright 2010 hiromi, https://github.com/hiromi2424
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
--- /dev/null
+# LANGUAGE translation of CakePHP Application
+# Copyright hiromi <tanaka2424@gmail.com>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Collectionable Plugin for CakePHP v1.0\n"
+"POT-Creation-Date: 2011-02-10 06:00+0900\n"
+"PO-Revision-Date: 2011-02-10 06:11+0900\n"
+"Last-Translator: hiromi <tanaka2424@gmail.com>\n"
+"Language-Team: hiromi <tanaka2424@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: models\behaviors\config_validation.php:118
+#: tests\cases\behaviors\config_validation.test.php:358
+msgid "getValidationParameter() requires 2 arguments as $field and $rule"
+msgstr ""
+
+#: models\behaviors\config_validation.php:143
+#: tests\cases\behaviors\config_validation.test.php:376
+msgid "getValidationMessage() requires a argument as $rule"
+msgstr ""
+
+#: models\behaviors\multi_validation.php:97
+msgid "Unexpected property name: Model::$%s was not found."
+msgstr ""
+
--- /dev/null
+# LANGUAGE translation of CakePHP Application
+# Copyright hiromi <tanaka2424@gmail.com>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Collectionable Plugin for CakePHP v1.0\n"
+"POT-Creation-Date: 2011-02-10 06:00+0900\n"
+"PO-Revision-Date: 2011-02-10 06:11+0900\n"
+"Last-Translator: hiromi <tanaka2424@gmail.com>\n"
+"Language-Team: hiromi <tanaka2424@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: models\behaviors\config_validation.php:118
+#: tests\cases\behaviors\config_validation.test.php:358
+msgid "getValidationParameter() requires 2 arguments as $field and $rule"
+msgstr "getValidationParameter() requires 2 arguments as $field and $rule"
+
+#: models\behaviors\config_validation.php:143
+#: tests\cases\behaviors\config_validation.test.php:376
+msgid "getValidationMessage() requires a argument as $rule"
+msgstr "getValidationMessage() requires a argument as $rule"
+
+#: models\behaviors\multi_validation.php:97
+msgid "Unexpected property name: Model::$%s was not found."
+msgstr "Unexpected property name: Model::$%s was not found."
+
--- /dev/null
+# LANGUAGE translation of CakePHP Application
+# Copyright hiromi <tanaka2424@gmail.com>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Collectionable Plugin for CakePHP v1.0\n"
+"POT-Creation-Date: 2011-02-10 06:00+0900\n"
+"PO-Revision-Date: 2011-02-10 06:11+0900\n"
+"Last-Translator: hiromi <tanaka2424@gmail.com>\n"
+"Language-Team: hiromi <tanaka2424@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: models\behaviors\config_validation.php:118
+#: tests\cases\behaviors\config_validation.test.php:358
+msgid "getValidationParameter() requires 2 arguments as $field and $rule"
+msgstr "getValidationParameter() は$fieldと$ruleの二つの引数が必要です"
+
+#: models\behaviors\config_validation.php:143
+#: tests\cases\behaviors\config_validation.test.php:376
+msgid "getValidationMessage() requires a argument as $rule"
+msgstr "getValidationParameter() は$rule引数が必要です"
+
+#: models\behaviors\multi_validation.php:97
+msgid "Unexpected property name: Model::$%s was not found."
+msgstr "予期しないプロパティ名:Model::$%sが見つかりませんでした。"
+
--- /dev/null
+<?php
+
+class ConfigValidationBehavior extends ModelBehavior {
+ var $configName = 'Validation';
+ var $overwrite = false; // true or $parameterName or $messageName
+ var $convertFormat = true;
+
+ var $parametersName = 'parameters';
+ var $messagesName = 'messages';
+ function beforeValidate(&$model) {
+ if (!$model->validate || !is_array($model->validate)) {
+ return true;
+ }
+
+ $this->_setParameters($model);
+ $this->_setMessages($model);
+ $this->_convertFormat($model);
+ return true;
+ }
+
+ function _setParameters(&$model) {
+ $overwrite = $this->overwrite === true || $this->overwrite == $this->parametersName;
+ foreach ($model->validate as $field => $elements) {
+ foreach ($elements as $name => $element) {
+ $parameters = $this->_config($this->parametersName, $model->name, $field, $name);
+ if ($parameters === null || !isset($element['rule'])) {
+ continue;
+ }
+
+ if (count($element['rule']) > 1 && !$overwrite) {
+ continue;
+ }
+
+ $model->validate[$field][$name]['rule'] = array_merge(array(current($element['rule'])), (array)$parameters);
+ }
+ }
+ }
+
+ function _setMessages(&$model) {
+ $overwrite = $this->overwrite === true || $this->overwrite == $this->messagesName;
+ foreach ($model->validate as $field => $elements) {
+ foreach ($elements as $name => $element) {
+ $default = $this->_config($this->messagesName, 'default', $name);
+ $desire = $this->_config($this->messagesName, $model->name, $field, $name);
+ if ($default === null && $desire === null) {
+ continue;
+ }
+
+ if (isset($element['message']) && !$overwrite) {
+ continue;
+ }
+ if ($desire !== null) {
+ $model->validate[$field][$name]['message'] = $desire;
+ continue;
+ }
+ if (!isset($element['message'])) {
+ $model->validate[$field][$name]['message'] = $default;
+ }
+ }
+ }
+ }
+
+ function _convertFormat(&$model) {
+ if (!$this->convertFormat) {
+ return;
+ }
+ foreach ($model->validate as $field => $elements) {
+ foreach ($elements as $name => $element) {
+ if (!isset($element['message']) || !isset($element['rule']) || !is_array($element['rule'])) {
+ continue;
+ }
+ if (count($element['rule']) > 1) {
+ array_shift($element['rule']);
+ array_unshift($element['rule'], $element['message']);
+ $model->validate[$field][$name]['message'] = call_user_func_array('sprintf', $element['rule']);
+ }
+ }
+ }
+ }
+
+ function _config() {
+ $args = func_get_args();
+ array_unshift($args, $this->configName);
+ return Configure::read(implode('.', $args));
+ }
+
+ function getValidationParameter(&$model, $field, $rule) {
+ if (is_array($field) || is_array($rule) || $field === null || $rule === null) {
+ trigger_error(__d('collectionable', 'getValidationParameter() requires 2 arguments as $field and $rule', true));
+ return null;
+ }
+
+ $this->beforeValidate($model);
+ if (empty($model->validate[$field][$rule]['rule'])) {
+ return null;
+ }
+ $rule = $model->validate[$field][$rule]['rule'];
+ array_shift($rule);
+ if (empty($rule)) {
+ return null;
+ }
+ $parameters = count($rule) === 1 ? current($rule) : $rule;
+ return $parameters;
+ }
+
+ function getValidationMessage(&$model, $rule, $field = null) {
+ if (is_array($rule) || $rule === null) {
+ trigger_error(__d('collectionable', 'getValidationMessage() requires a argument as $rule', true));
+ return null;
+ }
+ if (is_array($field)) {
+ $field = null;
+ }
+ if ($field !== null) {
+ $swap = $rule;
+ $rule = $field;
+ $field = $swap;
+ }
+ if ($field === null) {
+ $default = $this->_config($this->messagesName, 'default', $rule);
+ return $default;
+ }
+
+ $this->beforeValidate($model);
+ if (empty($model->validate[$field][$rule]['message'])) {
+ return null;
+ }
+ return $model->validate[$field][$rule]['message'];
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class MultiValidationBehavior extends ModelBehavior {
+
+ var $settings = array();
+ var $defaultSettings = array(
+ 'restore' => true,
+ );
+
+ var $_backupValidate = array();
+
+ function setup($Model, $settings = array()) {
+
+ $this->settings[$Model->alias] = array_merge($this->defaultSettings, (array)$settings);
+ return true;
+
+ }
+
+ function restoreValidate($Model) {
+
+ if (isset($this->_backupValidate[$Model->alias])) {
+ $Model->validate = $this->_backupValidate[$Model->alias];
+ unset($this->_backupValidate[$Model->alias]);
+ }
+
+ }
+
+ function afterSave($Model, $created = true, $options = array()) {
+
+ if ($this->settings[$Model->alias]['restore']) {
+ $this->restoreValidate($Model);
+ }
+
+ return true;
+
+ }
+
+ function useValidationSet($Model, $method, $useBase = true) {
+
+ $validates = array_map('ucfirst', (array)$method);
+
+ $result = array();
+ foreach ($validates as $validate) {
+
+ $property = 'validate' . $validate;
+ if (!isset($Model->{$property})) {
+ trigger_error(sprintf(__d('collectionable', 'Unexpected property name: Model::$%s was not found.', true), $property));
+ return false;
+ }
+ $result = $this->mergeValidationSet($Model, $result, $Model->{$property});
+
+ }
+
+ if ($useBase) {
+ $result = $this->mergeValidationSet($Model, $Model->validate, $result);
+ }
+
+ $this->_backupValidate[$Model->alias] = $Model->validate;
+ $Model->validate = $result;
+
+ return true;
+
+ }
+
+ function mergeValidationSet($Model) {
+
+ $validationSets = func_get_args();
+ /* $Model = */ array_shift($validationSets);
+
+ $result = array();
+ foreach ($validationSets as $validationSet) {
+ foreach ($validationSet as $field => $ruleSet) {
+ foreach ($ruleSet as $name => $rules) {
+ if (isset($result[$field][$name])) {
+ $result[$field][$name] = array_merge($result[$field][$name], $rules);
+ } else {
+ $result[$field][$name] = $rules;
+ }
+ }
+ }
+ }
+
+ return $result;
+
+ }
+
+}
--- /dev/null
+<?php
+
+class OptionsBehavior extends ModelBehavior {
+
+ var $settings = array();
+ var $defaultSettings = array(
+ 'setupProperty' => true,
+ 'defaultOption' => false,
+ 'optionName' => 'options',
+ );
+
+ var $defaultQuery = array(
+ 'conditions' => null, 'fields' => null, 'joins' => array(), 'limit' => null,
+ 'offset' => null, 'order' => null, 'page' => null, 'group' => null, 'callbacks' => true
+ );
+
+ function setup(&$Model, $settings = array()) {
+ $this->settings = array_merge($this->defaultSettings, (array)$settings);
+ $optionName = $this->settings['optionName'];
+ if ($this->settings['setupProperty']) {
+ if (empty($Model->{$optionName})) {
+ $Model->{$optionName} = array();
+ }
+ if (empty($Model->defaultOption)) {
+ $Model->defaultOption = $this->settings['defaultOption'];
+ }
+ }
+ return true;
+ }
+
+ function beforeFind(&$Model, $query = array()) {
+ if (isset($query['options'])) {
+ $options = $query['options'];
+ unset($query['options']);
+
+ $query = Set::merge($this->defaultQuery, $this->options($Model, $options), Set::filter($query));
+ }
+ return $query;
+ }
+
+ function options(&$Model, $type = null){
+ $args = func_get_args();
+ if (func_num_args() > 2) {
+ array_shift($args);
+ $type = $args;
+ }
+
+ $option = array();
+ if (is_array($type)) {
+ foreach ($type as $t) {
+ $option = Set::merge($option, $this->options($Model, $t));
+ }
+ } else {
+ $optionName = $this->settings['optionName'];
+ $option = isset($Model->{$optionName}[$type]) ? $Model->{$optionName}[$type] : array();
+ $default = array();
+ if ($Model->defaultOption) {
+ $default = $this->_getDefault($Model->defaultOption, $Model->{$optionName});
+ }
+ $options = array();
+ if (isset($option[$optionName]) && !empty($option[$optionName])) {
+ $options = $this->_intelligentlyMerge(array(), $option[$optionName], $Model->{$optionName});
+ unset($option['options']);
+ }
+ $option = Set::merge($default, $options, $option);
+ }
+ return $option;
+ }
+
+ function _getDefault($defaultOption, $options) {
+ $default = array();
+ if ($defaultOption === true && !empty($options['default'])) {
+ $default = $options['default'];
+ } elseif (is_array($defaultOption)) {
+ $default = $this->_intelligentlyMerge($default, $defaultOption, $options);
+ } elseif (!empty($options[$defaultOption])) {
+ $default = $this->_intelligentlyMerge($default, $options[$defaultOption], $options);
+ }
+ return $default;
+ }
+
+ function _intelligentlyMerge($data, $merges, $options) {
+ $merges = (array)$merges;
+ if (Set::numeric(array_keys($merges))) {
+ foreach($merges as $merge) {
+ if (!empty($options[$merge])) {
+ $data = $this->_intelligentlyMerge($data, $options[$merge], $options);
+ }
+ }
+ } else {
+ $optionName = $this->settings['optionName'];
+ if (array_key_exists($optionName, $merges)) {
+ $data = $this->_intelligentlyMerge($data, $merges[$optionName], $options);
+ unset($merges[$optionName]);
+ }
+ $data = Set::merge($data, $merges);
+ }
+ return $data;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class VirtualFieldsBehavior extends ModelBehavior {
+ var $settins = array();
+ var $defaultSettings = array(
+ 'setupProperty' => true,
+ 'collectionName' => 'virtualFieldsCollection',
+ );
+ var $__virtualFieldsBackup = array();
+
+ function setup(&$Model, $settings = array()) {
+ $this->settings = Set::merge($this->defaultSettings, $settings);
+ extract($this->settings);
+ if (!isset($Model->{$collectionName}) && $this->settings['setupProperty']) {
+ $Model->{$collectionName} = array();
+ }
+ return true;
+ }
+
+ function beforeFind(&$Model, $query = array()){
+ extract($this->settings);
+ if (!isset($query['virtualFields'])) {
+ return true;
+ }
+ $virtualFields = Set::normalize($query['virtualFields']);
+ unset($query['virtualFields']);
+
+ $blackList = array();
+ foreach ($virtualFields as $key => $sql) {
+ if (($sql !== false && empty($sql)) || $sql === true) {
+ if (isset($Model->{$collectionName}[$key])) {
+ $virtualFields[$key] = $Model->{$collectionName}[$key];
+ } else {
+ unset($virtualFields[$key]);
+ }
+ } else {
+ $blackList[] = $key;
+ unset($virtualFields[$key]);
+ }
+ }
+
+ if (!empty($virtualFields) || !empty($blackList)){
+ $this->__virtualFieldsBackup[$Model->alias] = $Model->virtualFields;
+ $Model->virtualFields = array_merge($Model->virtualFields, $virtualFields);
+ if (!empty($blackList)) {
+ foreach ($blackList as $key) {
+ if (isset($Model->virtualFields[$key])) {
+ unset($Model->virtualFields[$key]);
+ }
+ }
+ }
+ }
+ return $query;
+ }
+
+ function afterFind(&$Model, $results = array(), $primary = false) {
+ if (isset($this->__virtualFieldsBackup[$Model->alias])) {
+ $Model->virtualFields = $this->__virtualFieldsBackup[$Model->alias];
+ unset($this->__virtualFieldsBackup[$Model->alias]);
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php\r
+App::import('Behavior', 'Collectionable.ConfigValidation');\r
+\r
+class ConfigValidaitonMockModel extends Model {\r
+ var $useTable = false;\r
+ var $validate = array(\r
+ 'nickname' => array(\r
+ 'required' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ 'min' => array(\r
+ 'rule' => array('minlength'),\r
+ 'message' => '%s文字ください',\r
+ ),\r
+ 'max' => array(\r
+ 'rule' => array('maxlength', 32),\r
+ 'message' => '32文字',\r
+ ),\r
+ 'hoge' => array(\r
+ 'rule' => array('userdefined', 2000),\r
+ ),\r
+ 'piyo' => array(\r
+ 'rule' => array('userdefined'),\r
+ ),\r
+ 'fuga' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'ふがー',\r
+ ),\r
+ 'moge' => array(\r
+ 'rule' => array('userdefined', 5000, 'hoge'),\r
+ 'message' => '%s %s',\r
+ ),\r
+ 'multi' => array(\r
+ 'rule' => array('userdefined'),\r
+ ),\r
+ ),\r
+ );\r
+}\r
+\r
+class ConfigValidationBehaviorTestCase extends CakeTestCase {\r
+ var $data = array(\r
+ 'ConfigValidaitonMockModel' => array(\r
+ 'nickname' => '0123456789012',\r
+ ),\r
+ );\r
+\r
+ function start() {\r
+ Configure::write('TestValidation', array(\r
+ 'parameters' => array(\r
+ 'ConfigValidaitonMockModel' => array(\r
+ 'nickname' => array(\r
+ 'min' => 10,\r
+ 'max' => 100,\r
+ 'multi' => array(-100, 900),\r
+ ),\r
+ ),\r
+ ),\r
+ 'messages' => array(\r
+ 'default' => array(\r
+ 'required' => '必須項目です',\r
+ 'max' => '%s文字以内で入力してください。',\r
+ 'hoge' => '%sです',\r
+ 'fuga' => 'でふぉると',\r
+ ),\r
+ 'ConfigValidaitonMockModel' => array(\r
+ 'nickname' => array(\r
+ 'required' => '必ず入力してください。',\r
+ 'piyo' => 'うりりりー',\r
+ 'fuga' => 'してい',\r
+ ),\r
+ ),\r
+ ),\r
+ ));\r
+ parent::start();\r
+ }\r
+\r
+ function startTest() {\r
+ $this->_attach();\r
+ }\r
+\r
+ function endTest() {\r
+ $this->_clear();\r
+ }\r
+\r
+ function _attach() {\r
+ $this->Behavior = new ConfigValidationBehavior;\r
+ $this->Behavior->configName = 'TestValidation';\r
+ $this->Behavior->convertFormat = false;\r
+ $this->Model =& ClassRegistry::init('ConfigValidaitonMockModel');\r
+ }\r
+\r
+ function _clear() {\r
+ unset($this->Behavior);\r
+ unset($this->Model);\r
+ ClassRegistry::flush();\r
+ }\r
+\r
+ function _reattach() {\r
+ $this->_clear();\r
+ $this->_attach();\r
+ }\r
+\r
+ function testAll() {\r
+ $this->Behavior->convertFormat = true;\r
+ $this->Behavior->beforeValidate($this->Model);\r
+\r
+ $result = $this->Model->validate;\r
+ $expects = array(\r
+ 'nickname' => array(\r
+ 'required' => array(\r
+ 'rule' => array('notempty'),\r
+ 'message' => '必ず入力してください。',\r
+ ),\r
+ 'min' => array(\r
+ 'rule' => array('minlength', 10),\r
+ 'message' => '10文字ください',\r
+ ),\r
+ 'max' => array(\r
+ 'rule' => array('maxlength', 32),\r
+ 'message' => '32文字',\r
+ ),\r
+ 'hoge' => array(\r
+ 'rule' => array('userdefined', 2000),\r
+ 'message' => '2000です',\r
+ ),\r
+ 'piyo' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'うりりりー',\r
+ ),\r
+ 'fuga' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'ふがー',\r
+ ),\r
+ 'moge' => array(\r
+ 'rule' => array('userdefined', 5000, 'hoge'),\r
+ 'message' => '5000 hoge',\r
+ ),\r
+ 'multi' => array(\r
+ 'rule' => array('userdefined', -100, 900),\r
+ ),\r
+ ),\r
+ );\r
+\r
+ $this->_reattach();\r
+ $this->Behavior->convertFormat = true;\r
+ $this->Behavior->overwrite = 'parameters';\r
+ $this->Behavior->beforeValidate($this->Model);\r
+\r
+ $result = $this->Model->validate;\r
+ $expects = array(\r
+ 'nickname' => array(\r
+ 'required' => array(\r
+ 'rule' => array('notempty'),\r
+ 'message' => '必ず入力してください。',\r
+ ),\r
+ 'min' => array(\r
+ 'rule' => array('minlength', 10),\r
+ 'message' => '10文字ください',\r
+ ),\r
+ 'max' => array(\r
+ 'rule' => array('maxlength', 100),\r
+ 'message' => '32文字',\r
+ ),\r
+ 'hoge' => array(\r
+ 'rule' => array('userdefined', 2000),\r
+ 'message' => '2000です',\r
+ ),\r
+ 'piyo' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'うりりりー',\r
+ ),\r
+ 'fuga' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'ふがー',\r
+ ),\r
+ 'moge' => array(\r
+ 'rule' => array('userdefined', 5000, 'hoge'),\r
+ 'message' => '5000 hoge',\r
+ ),\r
+ 'multi' => array(\r
+ 'rule' => array('userdefined', -100, 900),\r
+ ),\r
+ ),\r
+ );\r
+\r
+ $this->_reattach();\r
+ $this->Behavior->convertFormat = true;\r
+ $this->Behavior->overwrite = 'messages';\r
+ $this->Behavior->beforeValidate($this->Model);\r
+\r
+ $result = $this->Model->validate;\r
+ $expected = array(\r
+ 'nickname' => array(\r
+ 'required' => array(\r
+ 'rule' => array('notempty'),\r
+ 'message' => '必ず入力してください。',\r
+ ),\r
+ 'min' => array(\r
+ 'rule' => array('minlength', 10),\r
+ 'message' => '10文字ください',\r
+ ),\r
+ 'max' => array(\r
+ 'rule' => array('maxlength', 32),\r
+ 'message' => '32文字',\r
+ ),\r
+ 'hoge' => array(\r
+ 'rule' => array('userdefined', 2000),\r
+ 'message' => '2000です',\r
+ ),\r
+ 'piyo' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'うりりりー',\r
+ ),\r
+ 'fuga' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'してい',\r
+ ),\r
+ 'moge' => array(\r
+ 'rule' => array('userdefined', 5000, 'hoge'),\r
+ 'message' => '5000 hoge',\r
+ ),\r
+ 'multi' => array(\r
+ 'rule' => array('userdefined', -100, 900),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertEqual($result, $expected);\r
+\r
+ $this->_reattach();\r
+ $this->Behavior->convertFormat = true;\r
+ $this->Behavior->overwrite = true;\r
+ $this->Behavior->beforeValidate($this->Model);\r
+\r
+ $result = $this->Model->validate;\r
+ $expected = array(\r
+ 'nickname' => array(\r
+ 'required' => array(\r
+ 'rule' => array('notempty'),\r
+ 'message' => '必ず入力してください。',\r
+ ),\r
+ 'min' => array(\r
+ 'rule' => array('minlength', 10),\r
+ 'message' => '10文字ください',\r
+ ),\r
+ 'max' => array(\r
+ 'rule' => array('maxlength', 100),\r
+ 'message' => '32文字',\r
+ ),\r
+ 'hoge' => array(\r
+ 'rule' => array('userdefined', 2000),\r
+ 'message' => '2000です',\r
+ ),\r
+ 'piyo' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'うりりりー',\r
+ ),\r
+ 'fuga' => array(\r
+ 'rule' => array('userdefined'),\r
+ 'message' => 'してい',\r
+ ),\r
+ 'moge' => array(\r
+ 'rule' => array('userdefined', 5000, 'hoge'),\r
+ 'message' => '5000 hoge',\r
+ ),\r
+ 'multi' => array(\r
+ 'rule' => array('userdefined', -100, 900),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertEqual($result, $expected);\r
+\r
+ $this->_reattach();\r
+ $this->Model->validate = true;\r
+ $this->assertTrue($this->Behavior->beforeValidate($this->Model));\r
+ $this->assertTrue($this->Model->validate);\r
+\r
+ $this->_reattach();\r
+ $this->Model->validate = array();\r
+ $this->assertTrue($this->Behavior->beforeValidate($this->Model));\r
+ $this->assertEqual($this->Model->validate, array());\r
+\r
+ $this->_reattach();\r
+ $this->Model->validate = array('hoge' => array('monyomonyo' => array('hoge' => '%s')));\r
+ $this->assertTrue($this->Behavior->beforeValidate($this->Model));\r
+ $this->assertEqual($this->Model->validate, array('hoge' => array('monyomonyo' => array('hoge' => '%s'))));\r
+ }\r
+\r
+ function testSetParameters() {\r
+ $this->Behavior->_setParameters($this->Model);\r
+\r
+ $this->assertEqual($this->Model->validate['nickname']['min']['rule'], array('minlength', 10));\r
+ $this->assertEqual($this->Model->validate['nickname']['max']['rule'], array('maxlength', 32));\r
+ $this->assertEqual($this->Model->validate['nickname']['multi']['rule'], array('userdefined', -100, 900));\r
+\r
+ $this->_reattach();\r
+ $this->Behavior->overwrite = true;\r
+ $this->Behavior->_setParameters($this->Model);\r
+\r
+ $this->assertEqual($this->Model->validate['nickname']['min']['rule'], array('minlength', 10));\r
+ $this->assertEqual($this->Model->validate['nickname']['max']['rule'], array('maxlength', 100));\r
+ $this->assertEqual($this->Model->validate['nickname']['multi']['rule'], array('userdefined', -100, 900));\r
+ }\r
+\r
+ function testSetMessages() {\r
+ $this->Behavior->_setMessages($this->Model);\r
+ $this->assertEqual($this->Model->validate['nickname']['required']['message'], '必ず入力してください。');\r
+ $this->assertEqual($this->Model->validate['nickname']['max']['message'], '32文字');\r
+ $this->assertEqual($this->Model->validate['nickname']['hoge']['message'], '%sです');\r
+ $this->assertEqual($this->Model->validate['nickname']['piyo']['message'], 'うりりりー');\r
+ $this->assertEqual($this->Model->validate['nickname']['fuga']['message'], 'ふがー');\r
+\r
+ $this->_reattach();\r
+ $this->Behavior->overwrite = true;\r
+ $this->Behavior->_setMessages($this->Model);\r
+\r
+ $this->assertEqual($this->Model->validate['nickname']['fuga']['message'], 'してい');\r
+ }\r
+\r
+ function testConvertFormat() {\r
+ $this->Behavior->convertFormat = true;\r
+ $this->Behavior->_convertFormat($this->Model);\r
+\r
+ $this->assertEqual($this->Model->validate['nickname']['moge']['message'], '5000 hoge');\r
+ }\r
+\r
+ function testGetValidationParameter() {\r
+ $this->expectError();\r
+ $this->assertNull($this->Behavior->getValidationParameter($this->Model, 'nickname', null));\r
+ $this->assertNull($this->Behavior->getValidationParameter($this->Model, 'nickname', 'undefined'));\r
+ $this->assertEqual($this->Behavior->getValidationParameter($this->Model, 'nickname', 'max'), 32);\r
+ $this->assertEqual($this->Behavior->getValidationParameter($this->Model, 'nickname', 'multi'), array(-100, 900));\r
+ }\r
+\r
+ function testGetConfigMessage() {\r
+ $this->Behavior->convertFormat = true;\r
+\r
+ $this->expectError();\r
+ $this->assertNull($this->Behavior->getValidationMessage($this->Model, null));\r
+ $this->assertNull($this->Behavior->getValidationMessage($this->Model, 'not defined'));\r
+ $this->assertEqual($this->Behavior->getValidationMessage($this->Model, 'fuga'), 'でふぉると');\r
+ $this->assertEqual($this->Behavior->getValidationMessage($this->Model, 'max'), '%s文字以内で入力してください。');\r
+ $this->assertEqual($this->Behavior->getValidationMessage($this->Model, 'nickname', 'min'), '10文字ください');\r
+ }\r
+}\r
--- /dev/null
+<?php\r
+\r
+class MultiValidaitonMockModel extends CakeTestModel {\r
+\r
+ var $useTable = false;\r
+ var $validate = array(\r
+ 'email' => array(\r
+ 'email' => array(\r
+ 'rule' => array('email'),\r
+ ),\r
+ ),\r
+ 'title' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+\r
+ var $validateBestAnswer = array(\r
+ 'best_answer_id' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+\r
+ var $validateEdit = array(\r
+ 'email' => array(\r
+ 'email' => array(\r
+ 'rule' => array('email', true),\r
+ ),\r
+ ),\r
+ );\r
+\r
+}\r
+\r
+class MultiValidationBehaviorTestCase extends CakeTestCase {\r
+\r
+ var $data = array(\r
+ 'MultiValidaitonMockModel' => array(\r
+ 'nickname' => '0123456789012',\r
+ ),\r
+ );\r
+\r
+ function startTest() {\r
+ $this->_attach();\r
+ }\r
+\r
+ function endTest() {\r
+ $this->_clear();\r
+ }\r
+\r
+ function _attach($settings = array()) {\r
+\r
+ $this->Model = ClassRegistry::init('MultiValidaitonMockModel');\r
+ $this->Model->Behaviors->detach('Collectionable.MultiValidation');\r
+ $this->Model->Behaviors->attach('Collectionable.MultiValidation', $settings);\r
+\r
+ }\r
+\r
+ function _clear() {\r
+\r
+ unset($this->Model);\r
+ ClassRegistry::flush();\r
+\r
+ }\r
+\r
+ function _reattach($settings = array()) {\r
+\r
+ $this->_clear();\r
+ $this->_attach($settings);\r
+\r
+ }\r
+\r
+ function testUseValidationSet() {\r
+\r
+ $this->Model->useValidationSet('BestAnswer');\r
+ $result = $this->Model->validate;\r
+ $expected = array(\r
+ 'email' => array(\r
+ 'email' => array(\r
+ 'rule' => array('email'),\r
+ ),\r
+ ),\r
+ 'title' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ 'best_answer_id' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertIdentical($result, $expected);\r
+\r
+ $this->Model->restoreValidate();\r
+ $this->Model->useValidationSet('bestAnswer');\r
+ $result = $this->Model->validate;\r
+ $this->assertIdentical($result, $expected);\r
+\r
+ $this->Model->restoreValidate();\r
+ $this->Model->useValidationSet('BestAnswer', false);\r
+ $result = $this->Model->validate;\r
+ $expected = array(\r
+ 'best_answer_id' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertIdentical($result, $expected);\r
+\r
+ $this->Model->restoreValidate();\r
+ $this->Model->useValidationSet(array('bestAnswer', 'edit'));\r
+ $result = $this->Model->validate;\r
+ $expected = array(\r
+ 'email' => array(\r
+ 'email' => array(\r
+ 'rule' => array('email', true),\r
+ ),\r
+ ),\r
+ 'title' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ 'best_answer_id' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertIdentical($result, $expected);\r
+\r
+ $this->expectError();\r
+ $this->assertFalse($this->Model->useValidationSet('invalidPropertyName'));\r
+\r
+ }\r
+\r
+ function testAfterSave() {\r
+\r
+ $this->Model->useValidationSet('bestAnswer', false);\r
+ $this->Model->Behaviors->MultiValidation->afterSave($this->Model);\r
+ $expected = array(\r
+ 'email' => array(\r
+ 'email' => array(\r
+ 'rule' => array('email'),\r
+ ),\r
+ ),\r
+ 'title' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertIdentical($this->Model->validate, $expected);\r
+\r
+ $this->_reattach(array('restore' => false));\r
+\r
+ $this->Model->useValidationSet('bestAnswer', false);\r
+ $this->Model->Behaviors->MultiValidation->afterSave($this->Model);\r
+ $expected = array(\r
+ 'best_answer_id' => array(\r
+ 'notempty' => array(\r
+ 'rule' => array('notempty'),\r
+ ),\r
+ ),\r
+ );\r
+ $this->assertIdentical($this->Model->validate, $expected);\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+<?php
+
+class OptionsBehaviorMockModel extends CakeTestModel {
+ var $useTable = false;
+}
+
+if (!class_exists('VirtualFieldsUser')) {
+ class VirtualFieldsUser extends CakeTestModel {
+ var $name = 'VirtualFieldsUser';
+ var $alias = 'User';
+ var $hasMany = array(
+ 'Post' => array(
+ 'className' => 'VirtualFieldsPost',
+ 'table' => 'Virtual_fields_posts',
+ 'foreignKey' => 'user_id',
+ ),
+ );
+ }
+}
+
+class OptionsBehaviorTest extends CakeTestCase {
+ var $Model;
+ var $fixtures = array('plugin.collectionable.virtual_fields_user', 'plugin.collectionable.virtual_fields_post');
+ var $autoFixtures = false;
+
+ function startCase() {
+ $this->Model =& ClassRegistry::init('OptionsBehaviorMockModel');
+ $this->_reset();
+ }
+
+ function _reset($settings = array()) {
+ unset($this->Model->defaultOption);
+ unset($this->Model->options);
+ $this->Model->Behaviors->attach('Collectionable.Options', $settings);
+ }
+
+ function startTest($method) {
+ $this->_reset(false);
+ }
+
+ function testArguments() {
+ $result = $this->Model->options();
+ $expects = array();
+ $this->assertIdentical($result, $expects);
+
+ $result = $this->Model->options('no sence');
+ $expects = array();
+ $this->assertIdentical($result, $expects);
+
+ $result = $this->Model->options(array('one', 'two', 'three'));
+ $expects = array();
+ $this->assertIdentical($result, $expects);
+
+ $this->_reset(array('defaultOption' => true));
+ $result = $this->Model->defaultOption;
+ $expects = true;
+ $this->assertIdentical($result, $expects);
+ }
+
+ function testDefaults() {
+ $this->Model->options = array(
+ 'default' => array('order' => 'default'),
+ 'one' => array('conditions' => array('one')),
+ 'two' => array('order' => 'two'),
+ 'three' => array('order' => 'three'),
+ );
+
+ $result = $this->Model->options('one');
+ $expects = array('conditions' => array('one'));
+ $this->assertEqual($result, $expects);
+
+ $this->Model->defaultOption = true;
+ $result = $this->Model->options('one');
+ $expects = array('conditions' => array('one'), 'order' => 'default');
+ $this->assertEqual($result, $expects);
+
+ $this->Model->defaultOption = 'three';
+
+ $result = $this->Model->options('one');
+ $expects = array('conditions' => array('one'), 'order' => 'three');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('two');
+ $expects = array('order' => 'two');
+ $this->assertEqual($result, $expects);
+
+ $this->Model->defaultOption = array('one', 'three');
+
+ $result = $this->Model->options('two');
+ $expects = array('conditions' => array('one'), 'order' => 'two');
+ $this->assertEqual($result, $expects);
+
+ }
+
+ function testMerge() {
+ $this->Model->options = array(
+ 'one' => array('conditions' => array('one')),
+ 'two' => array('order' => 'two', 'group' => 'two'),
+ 'three' => array('order' => 'three'),
+ 'four' => array('conditions' => array('four'), 'group' => 'four'),
+ );
+
+ $result = $this->Model->options('one', 'two', 'three');
+ $expects = array('conditions' => array('one'), 'group' => 'two', 'order' => 'three');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('three', 'four', 'one');
+ $expects = array('conditions' => array('four', 'one'), 'order' => 'three', 'group' => 'four');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('one', 'two', 'four');
+ $expects = array('conditions' => array('one', 'four'), 'order' => 'two', 'group' => 'four');
+ $this->assertEqual($result, $expects);
+ }
+
+ function testOptions() {
+ $this->Model->options = array(
+ 'one' => array('conditions' => array('one')),
+ 'two' => array('order' => 'two', 'group' => 'two'),
+ 'three' => array('order' => 'three'),
+ 'four' => array('conditions' => array('four'), 'group' => 'four'),
+ 'string' => array(
+ 'conditions' => array('merging'),
+ 'order' => 'merging',
+ 'options' => 'one',
+ ),
+ 'single_array' => array(
+ 'conditions' => array('merging'),
+ 'order' => 'merging',
+ 'options' => array('one'),
+ ),
+ 'multi_array' => array(
+ 'conditions' => array('merging'),
+ 'order' => 'merging',
+ 'options' => array('one', 'two'),
+ ),
+ 'extra_options' => array(
+ 'conditions' => array('merging'),
+ 'order' => 'merging',
+ 'options' => array(
+ 'conditions' => array('extra'),
+ ),
+ ),
+ 'chaos' => array(
+ 'conditions' => array('merging'),
+ 'order' => 'merging',
+ 'options' => array(
+ 'one',
+ 'four',
+ 'conditions' => array('chaos'),
+ ),
+ ),
+ );
+
+ $result = $this->Model->options('string');
+ $expects = array('conditions' => array('one', 'merging'), 'order' => 'merging');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('single_array');
+ $expects = array('conditions' => array('one', 'merging'), 'order' => 'merging');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('multi_array');
+ $expects = array('conditions' => array('one', 'merging'), 'order' => 'merging', 'group' => 'two');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('extra_options');
+ $expects = array('conditions' => array('extra', 'merging'), 'order' => 'merging');
+ $this->assertEqual($result, $expects);
+
+ $result = $this->Model->options('chaos');
+ $expects = array('one', 'four', 'conditions' => array('chaos', 'merging'), 'order' => 'merging');
+ $this->assertEqual($result, $expects);
+ }
+
+ function testFindOptions() {
+ $this->loadFixtures('VirtualFieldsUser');
+ $User =& ClassRegistry::init(array('alias' => 'User', 'class' => 'VirtualFieldsUser'));
+ $User->recursive = -1;
+ $User->options = array(
+ 'limitation' => array(
+ 'limit' => 1,
+ 'fields' => array('User.id', 'User.first_name')
+ ),
+ );
+ $User->Behaviors->attach('Collectionable.options');
+
+ $result = $User->find('all', array('options' => 'limitation', 'limit' => 2, 'order' => 'User.id'));
+ $expects = array(
+ array('User' => array('id' => 1, 'first_name' => 'yamada')),
+ array('User' => array('id' => 2, 'first_name' => 'tanaka')),
+ );
+ $this->assertEqual($result, $expects);
+ }
+
+ function testRecursiveMerge() {
+ $this->Model->options = array(
+ 'one' => array('conditions' => array('one')),
+ 'two' => array('conditions' => array('two'), 'options' => 'one'),
+ 'three' => array('conditions' => array('three'), 'options' => 'two'),
+ 'four' => array('conditions' => array('four')),
+ );
+
+ $result = $this->Model->options('three');
+ $expects = array('one', 'two', 'three');
+ $this->assertEqual($result['conditions'], $expects);
+
+ $this->Model->defaultOption = 'three';
+ $result = $this->Model->options('four');
+ $expects = array('one', 'two', 'three', 'four');
+ $this->assertEqual($result['conditions'], $expects);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class VirtualFieldsBehaviorMockModel extends CakeTestModel {
+ var $useTable = false;
+}
+
+if (!class_exists('VirtualFieldsUser')) {
+ class VirtualFieldsUser extends CakeTestModel {
+ var $name = 'VirtualFieldsUser';
+ var $alias = 'User';
+ var $hasMany = array(
+ 'Post' => array(
+ 'className' => 'VirtualFieldsPost',
+ 'table' => 'Virtual_fields_posts',
+ 'foreignKey' => 'user_id',
+ ),
+ );
+ }
+}
+
+class VirualFieldsBehaviorTest extends CakeTestCase {
+ var $Behavior;
+ var $Model;
+ var $db;
+
+ var $fixtures = array(
+ 'plugin.collectionable.virtual_fields_post',
+ 'plugin.collectionable.virtual_fields_user',
+ );
+
+ function startCase() {
+ parent::startCase();
+ $this->_reset();
+ }
+
+ function _reset($settings = array(), $model = null) {
+ $model = $model === null ? 'VirtualFieldsBehaviorMockModel' : $model;
+ $this->Model = ClassRegistry::init($model);
+ $this->Model->Behaviors->attach('Collectionable.VirtualFields', $settings);
+ $this->Behavior =& ClassRegistry::getObject('VirtualFieldsBehavior');
+ }
+
+ function testUndefined() {
+ $virtualFields = array('not_be_defined');
+ $this->Behavior->beforeFind($this->Model, compact('virtualFields'));
+ $result = $this->Model->virtualFields;
+ $expects = array();
+ $this->assertEqual($result, $expects);
+
+ $this->Behavior->afterFind($this->Model);
+ $this->Model->virtualFields = array(
+ 'full_name' => "CONCAT(User.first_name, ' ', User.last_name)",
+ );
+ $virtualFields = array('not_be_defined');
+ $this->Behavior->beforeFind($this->Model, compact('virtualFields'));
+ $result = $this->Model->virtualFields;
+ $expects = array('full_name' => "CONCAT(User.first_name, ' ', User.last_name)");
+ $this->assertEqual($result, $expects);
+
+ $this->Behavior->afterFind($this->Model);
+ $this->Model->virtualFields = array();
+ $this->Model->virtualFieldsCollection = array(
+ 'posts_count' => 'COUNT(Post.id)',
+ );
+ $virtualFields = array('not_be_defined');
+ $this->Behavior->beforeFind($this->Model, compact('virtualFields'));
+ $result = $this->Model->virtualFields;
+ $expects = array();
+ $this->assertEqual($result, $expects);
+ }
+
+ function testFind() {
+ $this->_reset(false, 'VirtualFieldsUser');
+ $this->skipIf($this->db->config['driver'] !== 'mysql', "%s This tests belonges to MySQL('s SQL expression)");
+
+ $this->Model->virtualFields = array(
+ 'full_name' => "CONCAT(User.first_name, ' ', User.last_name)",
+ );
+ $this->Model->virtualFieldsCollection = array(
+ 'posts_count' => 'COUNT(Post.id)',
+ );
+ $this->Model->recursive = -1;
+
+ $result = $this->Model->find('first', array('fields' => array('User.full_name')));
+ $expected = array('User' => array('full_name' => 'yamada ichirou'));
+ $this->assertEqual($result, $expected);
+
+ $virtualFields = array('posts_count');
+ $joins = array(
+ array(
+ 'table' => $this->Model->Post->table,
+ 'alias' => 'Post',
+ 'type' => 'LEFT',
+ 'conditions' => array('User.id = Post.user_id')
+ )
+ );
+ $group = 'User.id';
+ $fields = array('User.full_name', 'User.posts_count');
+ $result = $this->Model->find('first', compact('fields', 'virtualFields', 'joins', 'group'));
+ $expected = array('User' => array('full_name' => 'yamada ichirou', 'posts_count' => 2));
+ $this->assertEqual($result, $expected);
+
+ // ensure virtualFields of model was reset
+ $result = $this->Model->find('first', array('fields' => array('User.full_name')));
+ $expected = array('User' => array('full_name' => 'yamada ichirou'));
+ $this->assertEqual($result, $expected);
+
+ $this->Model->virtualFieldsCollection['full_name'] = "CONCAT(User.first_name, '.', User.last_name)";
+ $result = $this->Model->find('first', array('fields' => array('User.full_name'), 'virtualFields' => 'full_name'));
+ $expected = array('User' => array('full_name' => 'yamada.ichirou'));
+ $this->assertEqual($result, $expected);
+
+ $result = $this->Model->find('first', array('fields' => array('User.full_name')));
+ $expected = array('User' => array('full_name' => 'yamada ichirou'));
+ $this->assertEqual($result, $expected);
+ }
+
+ function testBlackList() {
+ $this->Model->virtualFields = array(
+ 'full_name' => "CONCAT(User.first_name, ' ', User.last_name)",
+ 'posts_count' => 'COUNT(Post.id)',
+ );
+
+ $this->Behavior->beforeFind($this->Model);
+ $result = $this->Model->virtualFields;
+ $expected = array('full_name' => "CONCAT(User.first_name, ' ', User.last_name)", 'posts_count' => 'COUNT(Post.id)');
+ $this->assertEqual($result, $expected);
+
+ $this->Behavior->afterFind($this->Model);
+ $virtualFields = array('posts_count' => false);
+ $this->Behavior->beforeFind($this->Model, compact('virtualFields'));
+ $result = $this->Model->virtualFields;
+ $expected = array('full_name' => "CONCAT(User.first_name, ' ', User.last_name)");
+ $this->assertEqual($result, $expected);
+
+ $this->Behavior->afterFind($this->Model);
+ $result = $this->Model->virtualFields;
+ $expected = array('full_name' => "CONCAT(User.first_name, ' ', User.last_name)", 'posts_count' => 'COUNT(Post.id)');
+ $this->assertEqual($result, $expected);
+ }
+
+ function testSettings() {
+
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class VirtualFieldsPostFixture extends CakeTestFixture {
+ var $name = 'VirtualFieldsPost';
+
+ var $fields = array(
+ 'id' => array('type' => 'integer', 'key' => 'primary'),
+ 'user_id' => array('type' => 'integer', 'key' => 'index'),
+ 'title' => array('type' => 'string', 'length' => 255, 'null' => false),
+ 'body' => 'text',
+ );
+
+ var $records = array(
+ array('id' => 1, 'title' => 'title1', 'body' => 'article 1', 'user_id' => 1),
+ array('id' => 2, 'title' => 'title2', 'body' => 'article 2', 'user_id' => 2),
+ array('id' => 3, 'title' => 'title3', 'body' => 'article 3', 'user_id' => 1),
+ array('id' => 4, 'title' => 'title4', 'body' => 'article 4', 'user_id' => 3),
+ );
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class VirtualFieldsUserFixture extends CakeTestFixture {
+ var $name = 'VirtualFieldsUser';
+
+ var $fields = array(
+ 'id' => array('type' => 'integer', 'key' => 'primary'),
+ 'first_name' => array('type' => 'string', 'length' => 255, 'null' => false),
+ 'last_name' => array('type' => 'string', 'length' => 255, 'null' => false),
+ );
+
+ var $records = array(
+ array('id' => 1, 'first_name' => 'yamada', 'last_name' => 'ichirou'),
+ array('id' => 2, 'first_name' => 'tanaka', 'last_name' => 'jirou'),
+ array('id' => 3, 'first_name' => 'kaneda', 'last_name' => 'saburou'),
+ array('id' => 4, 'first_name' => 'shimizu', 'last_name' => 'shinou'),
+ );
+}
\ No newline at end of file