From 57904715396d51929e172d037a4d4d68f679a901 Mon Sep 17 00:00:00 2001 From: RyujiAMANO Date: Thu, 14 Jan 2016 14:08:00 +0900 Subject: [PATCH 01/34] =?UTF-8?q?rename=E3=81=97=E3=81=A6=E3=81=A1?= =?UTF-8?q?=E3=82=87=E3=81=A3=E3=81=A8=E4=BD=9C=E6=A5=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bowerrc | 3 + .gitignore | 7 + .travis.yml | 29 + Config/Migration/001_plugin_records.php | 114 +++ Config/Migration/1450753185_init.php | 266 +++++ Config/Schema/empty | 0 Config/Schema/schema.php | 304 ++++++ Console/Command/Task/empty | 0 .../Component/RegistrationsComponent.php | 608 ++++++++++++ .../RegistrationsOwnAnswerComponent.php | 188 ++++ Controller/Component/empty | 0 Controller/RegistrationAddController.php | 106 ++ .../RegistrationAnswerSummariesController.php | 117 +++ Controller/RegistrationAnswersController.php | 334 +++++++ ...strationBlockRolePermissionsController.php | 104 ++ Controller/RegistrationBlocksController.php | 253 +++++ Controller/RegistrationEditController.php | 345 +++++++ .../RegistrationFrameSettingsController.php | 135 +++ Controller/RegistrationsAppController.php | 274 +++++ Controller/RegistrationsController.php | 156 +++ Lib/empty | 0 Locale/jpn/LC_MESSAGES/registrations.po | 935 +++++++++++++++++ Locale/registrations.pot | 937 ++++++++++++++++++ Model/ActionRegistrationAdd.php | 386 ++++++++ Model/Behavior/RegistrationAnswerBehavior.php | 199 ++++ .../RegistrationAnswerDatetimeBehavior.php | 112 +++ ...tionAnswerMatrixMultipleChoiceBehavior.php | 71 ++ ...rationAnswerMatrixSingleChoiceBehavior.php | 187 ++++ ...gistrationAnswerMultipleChoiceBehavior.php | 70 ++ ...RegistrationAnswerSingleChoiceBehavior.php | 63 ++ .../RegistrationAnswerSingleListBehavior.php | 106 ++ .../RegistrationAnswerTextAreaBehavior.php | 45 + .../RegistrationAnswerTextBehavior.php | 82 ++ .../Behavior/RegistrationValidateBehavior.php | 229 +++++ Model/Behavior/empty | 0 Model/Datasource/empty | 0 Model/Registration.php | 565 +++++++++++ Model/RegistrationAnswer.php | 218 ++++ Model/RegistrationAnswerSummary.php | 275 +++++ Model/RegistrationAnswerSummaryCsv.php | 278 ++++++ Model/RegistrationChoice.php | 199 ++++ Model/RegistrationExport.php | 132 +++ .../RegistrationFrameDisplayRegistration.php | 220 ++++ Model/RegistrationFrameSetting.php | 218 ++++ Model/RegistrationPage.php | 282 ++++++ Model/RegistrationQuestion.php | 350 +++++++ Model/RegistrationSetting.php | 112 +++ Model/RegistrationsAppModel.php | 44 + README.md | 11 + Test/Case/AllRegistrationsTest.php | 31 + Test/Case/Controller/Component/empty | 0 .../QuesetionnaireAddController/AddTest.php | 248 +++++ .../ViewTest.php | 420 ++++++++ .../IndexTest.php | 210 ++++ .../RegistrationsController/IndexTest.php | 440 ++++++++ Test/Case/Controller/empty | 0 Test/Case/Model/Behavior/empty | 0 .../GetDefaultChoiceTest.php | 100 ++ .../SaveRegistrationChoiceTest.php | 175 ++++ .../RegistrationPage/GetDefaultPageTest.php | 100 ++ .../SaveRegistrationPageTest.php | 196 ++++ .../GetDefaultQuestionTest.php | 105 ++ .../SaveRegistrationQuestionTest.php | 228 +++++ Test/Case/View/Helper/empty | 0 Test/Fixture/RegistrationAnswerFixture.php | 48 + .../RegistrationAnswerSummaryFixture.php | 48 + Test/Fixture/RegistrationChoiceFixture.php | 68 ++ Test/Fixture/RegistrationFixture.php | 482 +++++++++ ...trationFrameDisplayRegistrationFixture.php | 60 ++ .../RegistrationFrameSettingFixture.php | 53 + Test/Fixture/RegistrationPageFixture.php | 114 +++ Test/Fixture/RegistrationQuestionFixture.php | 149 +++ Test/Fixture/RegistrationSettingFixture.php | 54 + Test/Fixture/empty | 0 TestSuite/RegistrationsSaveTest.php | 175 ++++ Utility/WysIsWygDownloader.php | 68 ++ Vendor/empty | 0 .../AnswerSummaries/aggregate_bar_chart.ctp | 15 + .../aggregate_common_footer.ctp | 30 + .../aggregate_common_header.ctp | 51 + .../aggregate_matrix_bar_chart.ctp | 15 + .../aggregate_matrix_pie_chart.ctp | 21 + .../aggregate_matrix_table.ctp | 84 ++ .../AnswerSummaries/aggregate_pie_chart.ctp | 15 + .../AnswerSummaries/aggregate_table.ctp | 51 + View/Elements/Answers/answer_header.ctp | 16 + .../Answers/answer_test_mode_header.ctp | 40 + .../edit_display_registration.ctp | 102 ++ .../FrameSettings/edit_display_type.ctp | 26 + View/Elements/FrameSettings/edit_form.ctp | 28 + .../edit_list_display_option.ctp | 32 + View/Elements/RegistrationAdd/create_new.ctp | 25 + .../Elements/RegistrationAdd/create_reuse.ctp | 63 ++ .../RegistrationAdd/create_template.ctp | 27 + .../edit_form.ctp | 31 + .../Elements/RegistrationBlocks/edit_form.ctp | 27 + .../RegistrationEdit/Edit/delete_form.ctp | 33 + .../EditQuestion/accordion_heading.ctp | 62 ++ .../EditQuestion/add_question_button.ctp | 20 + .../EditQuestion/hidden_page_info_set.ctp | 19 + .../EditQuestion/hidden_question_info_set.ctp | 20 + .../options_after_published/choice.ctp | 15 + .../options_after_published/date_option.ctp | 84 ++ .../matrix_choice_option.ctp | 37 + .../simple_choice_option.ctp | 51 + .../options_after_published/text_option.ctp | 57 ++ .../options_before_published/choice.ctp | 50 + .../options_before_published/date_option.ctp | 105 ++ .../date_range_input.ctp | 72 ++ .../matrix_choice_option.ctp | 95 ++ .../simple_choice_option.ctp | 114 +++ .../options_before_published/text_option.ctp | 84 ++ .../EditResult/accordion_heading.ctp | 24 + .../EditResult/display_type_set.ctp | 54 + .../EditResult/graph_color_set.ctp | 67 ++ .../EditResult/is_display_set.ctp | 49 + .../RegistrationEdit/edit_flow_chart.ctp | 40 + View/Elements/RegistrationEdit/ng_errors.ctp | 16 + .../RegistrationEdit/registration_title.ctp | 15 + View/Elements/Registrations/add_button.ctp | 25 + View/Elements/Registrations/answer_status.ctp | 52 + .../Registrations/detail_for_editor.ctp | 43 + View/Elements/ng_status_label.ctp | 21 + View/Elements/scripts.ctp | 8 + View/Helper/QuestionEditHelper.php | 148 +++ View/Helper/RegistrationAnswerHelper.php | 419 ++++++++ View/Helper/RegistrationStatusLabelHelper.php | 77 ++ View/Helper/RegistrationUtilHelper.php | 215 ++++ View/Helper/empty | 0 View/RegistrationAdd/add.ctp | 60 ++ View/RegistrationAnswerSummaries/view.ctp | 90 ++ View/RegistrationAnswers/confirm.ctp | 76 ++ View/RegistrationAnswers/no_more_answer.ctp | 15 + View/RegistrationAnswers/test_mode.ctp | 126 +++ View/RegistrationAnswers/thanks.ctp | 43 + View/RegistrationAnswers/view.ctp | Bin 0 -> 2995 bytes .../RegistrationBlockRolePermissions/edit.ctp | 22 + .../noRegistrationBlock.ctp | 21 + View/RegistrationBlocks/edit.ctp | 34 + View/RegistrationBlocks/index.ctp | 106 ++ View/RegistrationBlocks/not_found.ctp | 25 + View/RegistrationEdit/edit.ctp | 186 ++++ View/RegistrationEdit/edit_question.ctp | 187 ++++ View/RegistrationEdit/edit_result.ctp | 111 +++ View/RegistrationFrameSettings/edit.ctp | 34 + View/Registrations/index.ctp | 68 ++ View/Registrations/noRegistration.ctp | 40 + bower.json | 16 + composer.json | 55 + phpunit.xml.dist | 20 + webroot/css/registration.css | 99 ++ webroot/empty | 0 webroot/js/registrations.js | 115 +++ webroot/js/registrations_edit.js | 96 ++ webroot/js/registrations_edit_question.js | 767 ++++++++++++++ webroot/js/registrations_graph.js | 320 ++++++ 156 files changed, 18863 insertions(+) create mode 100644 .bowerrc create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Config/Migration/001_plugin_records.php create mode 100644 Config/Migration/1450753185_init.php create mode 100644 Config/Schema/empty create mode 100644 Config/Schema/schema.php create mode 100644 Console/Command/Task/empty create mode 100644 Controller/Component/RegistrationsComponent.php create mode 100644 Controller/Component/RegistrationsOwnAnswerComponent.php create mode 100644 Controller/Component/empty create mode 100644 Controller/RegistrationAddController.php create mode 100644 Controller/RegistrationAnswerSummariesController.php create mode 100644 Controller/RegistrationAnswersController.php create mode 100644 Controller/RegistrationBlockRolePermissionsController.php create mode 100644 Controller/RegistrationBlocksController.php create mode 100644 Controller/RegistrationEditController.php create mode 100644 Controller/RegistrationFrameSettingsController.php create mode 100644 Controller/RegistrationsAppController.php create mode 100644 Controller/RegistrationsController.php create mode 100644 Lib/empty create mode 100644 Locale/jpn/LC_MESSAGES/registrations.po create mode 100644 Locale/registrations.pot create mode 100644 Model/ActionRegistrationAdd.php create mode 100644 Model/Behavior/RegistrationAnswerBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerDatetimeBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerMatrixMultipleChoiceBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerMultipleChoiceBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerSingleChoiceBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerSingleListBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerTextAreaBehavior.php create mode 100644 Model/Behavior/RegistrationAnswerTextBehavior.php create mode 100644 Model/Behavior/RegistrationValidateBehavior.php create mode 100644 Model/Behavior/empty create mode 100644 Model/Datasource/empty create mode 100644 Model/Registration.php create mode 100644 Model/RegistrationAnswer.php create mode 100644 Model/RegistrationAnswerSummary.php create mode 100644 Model/RegistrationAnswerSummaryCsv.php create mode 100644 Model/RegistrationChoice.php create mode 100644 Model/RegistrationExport.php create mode 100644 Model/RegistrationFrameDisplayRegistration.php create mode 100644 Model/RegistrationFrameSetting.php create mode 100644 Model/RegistrationPage.php create mode 100644 Model/RegistrationQuestion.php create mode 100644 Model/RegistrationSetting.php create mode 100644 Model/RegistrationsAppModel.php create mode 100644 README.md create mode 100644 Test/Case/AllRegistrationsTest.php create mode 100644 Test/Case/Controller/Component/empty create mode 100644 Test/Case/Controller/QuesetionnaireAddController/AddTest.php create mode 100644 Test/Case/Controller/RegistrationAnswersController/ViewTest.php create mode 100644 Test/Case/Controller/RegistrationBlocksController/IndexTest.php create mode 100644 Test/Case/Controller/RegistrationsController/IndexTest.php create mode 100644 Test/Case/Controller/empty create mode 100644 Test/Case/Model/Behavior/empty create mode 100644 Test/Case/Model/RegistrationChoice/GetDefaultChoiceTest.php create mode 100644 Test/Case/Model/RegistrationChoice/SaveRegistrationChoiceTest.php create mode 100644 Test/Case/Model/RegistrationPage/GetDefaultPageTest.php create mode 100644 Test/Case/Model/RegistrationPage/SaveRegistrationPageTest.php create mode 100644 Test/Case/Model/RegistrationQuestion/GetDefaultQuestionTest.php create mode 100644 Test/Case/Model/RegistrationQuestion/SaveRegistrationQuestionTest.php create mode 100644 Test/Case/View/Helper/empty create mode 100644 Test/Fixture/RegistrationAnswerFixture.php create mode 100644 Test/Fixture/RegistrationAnswerSummaryFixture.php create mode 100644 Test/Fixture/RegistrationChoiceFixture.php create mode 100644 Test/Fixture/RegistrationFixture.php create mode 100644 Test/Fixture/RegistrationFrameDisplayRegistrationFixture.php create mode 100644 Test/Fixture/RegistrationFrameSettingFixture.php create mode 100644 Test/Fixture/RegistrationPageFixture.php create mode 100644 Test/Fixture/RegistrationQuestionFixture.php create mode 100644 Test/Fixture/RegistrationSettingFixture.php create mode 100644 Test/Fixture/empty create mode 100644 TestSuite/RegistrationsSaveTest.php create mode 100644 Utility/WysIsWygDownloader.php create mode 100644 Vendor/empty create mode 100644 View/Elements/AnswerSummaries/aggregate_bar_chart.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_common_footer.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_common_header.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_matrix_bar_chart.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_matrix_pie_chart.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_matrix_table.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_pie_chart.ctp create mode 100644 View/Elements/AnswerSummaries/aggregate_table.ctp create mode 100644 View/Elements/Answers/answer_header.ctp create mode 100644 View/Elements/Answers/answer_test_mode_header.ctp create mode 100644 View/Elements/FrameSettings/edit_display_registration.ctp create mode 100644 View/Elements/FrameSettings/edit_display_type.ctp create mode 100644 View/Elements/FrameSettings/edit_form.ctp create mode 100644 View/Elements/FrameSettings/edit_list_display_option.ctp create mode 100644 View/Elements/RegistrationAdd/create_new.ctp create mode 100644 View/Elements/RegistrationAdd/create_reuse.ctp create mode 100644 View/Elements/RegistrationAdd/create_template.ctp create mode 100644 View/Elements/RegistrationBlockRolePermissions/edit_form.ctp create mode 100644 View/Elements/RegistrationBlocks/edit_form.ctp create mode 100644 View/Elements/RegistrationEdit/Edit/delete_form.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/add_question_button.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/hidden_page_info_set.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/hidden_question_info_set.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_after_published/choice.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_after_published/matrix_choice_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_after_published/simple_choice_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/choice.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_range_input.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp create mode 100644 View/Elements/RegistrationEdit/EditResult/accordion_heading.ctp create mode 100644 View/Elements/RegistrationEdit/EditResult/display_type_set.ctp create mode 100644 View/Elements/RegistrationEdit/EditResult/graph_color_set.ctp create mode 100644 View/Elements/RegistrationEdit/EditResult/is_display_set.ctp create mode 100644 View/Elements/RegistrationEdit/edit_flow_chart.ctp create mode 100644 View/Elements/RegistrationEdit/ng_errors.ctp create mode 100644 View/Elements/RegistrationEdit/registration_title.ctp create mode 100644 View/Elements/Registrations/add_button.ctp create mode 100644 View/Elements/Registrations/answer_status.ctp create mode 100644 View/Elements/Registrations/detail_for_editor.ctp create mode 100644 View/Elements/ng_status_label.ctp create mode 100644 View/Elements/scripts.ctp create mode 100644 View/Helper/QuestionEditHelper.php create mode 100644 View/Helper/RegistrationAnswerHelper.php create mode 100644 View/Helper/RegistrationStatusLabelHelper.php create mode 100644 View/Helper/RegistrationUtilHelper.php create mode 100644 View/Helper/empty create mode 100644 View/RegistrationAdd/add.ctp create mode 100644 View/RegistrationAnswerSummaries/view.ctp create mode 100644 View/RegistrationAnswers/confirm.ctp create mode 100644 View/RegistrationAnswers/no_more_answer.ctp create mode 100644 View/RegistrationAnswers/test_mode.ctp create mode 100644 View/RegistrationAnswers/thanks.ctp create mode 100644 View/RegistrationAnswers/view.ctp create mode 100644 View/RegistrationBlockRolePermissions/edit.ctp create mode 100644 View/RegistrationBlockRolePermissions/noRegistrationBlock.ctp create mode 100644 View/RegistrationBlocks/edit.ctp create mode 100644 View/RegistrationBlocks/index.ctp create mode 100644 View/RegistrationBlocks/not_found.ctp create mode 100644 View/RegistrationEdit/edit.ctp create mode 100644 View/RegistrationEdit/edit_question.ctp create mode 100644 View/RegistrationEdit/edit_result.ctp create mode 100644 View/RegistrationFrameSettings/edit.ctp create mode 100644 View/Registrations/index.ctp create mode 100644 View/Registrations/noRegistration.ctp create mode 100644 bower.json create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 webroot/css/registration.css create mode 100644 webroot/empty create mode 100644 webroot/js/registrations.js create mode 100644 webroot/js/registrations_edit.js create mode 100644 webroot/js/registrations_edit_question.js create mode 100644 webroot/js/registrations_graph.js diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..95ba0b9 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "../../../app/webroot/components" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd743c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +tmp/* +[Cc]onfig/core.php +[Cc]onfig/database.php +app/tmp/* +app/[Cc]onfig/core.php +app/[Cc]onfig/database.php +!empty diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0b590c2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + +env: + - NETCOMMONS_VERSION=master DB=mysql + +before_script: + - export NETCOMMONS_BUILD_DIR=`dirname $TRAVIS_BUILD_DIR`/NetCommons3 + - git clone git://github.com/NetCommons3/NetCommons3 $NETCOMMONS_BUILD_DIR + - cd $NETCOMMONS_BUILD_DIR + - git checkout $NETCOMMONS_VERSION + - . tools/build/plugins/cakephp/travis/pre.sh + +script: + - . tools/build/plugins/cakephp/travis/main.sh + +after_script: + - . tools/build/plugins/cakephp/travis/post.sh + +notifications: + email: + recipients: + - netcommons3@googlegroups.com + on_success: never # default: change + on_failure: always # default: always diff --git a/Config/Migration/001_plugin_records.php b/Config/Migration/001_plugin_records.php new file mode 100644 index 0000000..ea2d9d7 --- /dev/null +++ b/Config/Migration/001_plugin_records.php @@ -0,0 +1,114 @@ + + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('NetCommonsMigration', 'NetCommons.Config/Migration'); + +/** + * Add plugin migration + * + * @package NetCommons\PluginManager\Config\Migration + */ +class PluginRecords extends NetCommonsMigration { + +/** + * Migration description + * + * @var string + */ + public $description = 'plugin_records'; + +/** + * Actions to be performed + * + * @var array $migration + */ + public $migration = array( + 'up' => array(), + 'down' => array(), + ); + +/** + * plugin data + * + * @var array $migration + */ + public $records = array( + 'Plugin' => array( + //日本語 + array( + 'language_id' => '2', + 'key' => 'registrations', + 'namespace' => 'netcommons/registrations', + 'default_action' => 'registrations/index', + 'default_setting_action' => 'registration_blocks/index', + 'name' => '登録フォーム', + 'type' => 1, + ), + //英語 + array( + 'language_id' => '1', + 'key' => 'registrations', + 'namespace' => 'netcommons/registrations', + 'default_action' => 'registrations/index', + 'default_setting_action' => 'registration_blocks/index', + 'name' => 'Registrations', + 'type' => 1, + ), + ), + 'PluginsRole' => array( + array( + 'role_key' => 'room_administrator', + 'plugin_key' => 'registrations' + ), + ), + 'PluginsRoom' => array( + //パブリックスペース + array('room_id' => '1', 'plugin_key' => 'registrations', ), + ////プライベートスペース + //array('room_id' => '2', 'plugin_key' => 'registrations', ), + //グループスペース + array('room_id' => '3', 'plugin_key' => 'registrations', ), + ), + ); + +/** + * Before migration callback + * + * @param string $direction Direction of migration process (up or down) + * @return bool Should process continue + */ + public function before($direction) { + return true; + } + +/** + * After migration callback + * + * @param string $direction Direction of migration process (up or down) + * @return bool Should process continue + */ + public function after($direction) { + $this->loadModels([ + 'Plugin' => 'PluginManager.Plugin', + ]); + + if ($direction === 'down') { + $this->Plugin->uninstallPlugin($this->records['Plugin'][0]['key']); + return true; + } + + foreach ($this->records as $model => $records) { + if (!$this->updateRecords($model, $records)) { + return false; + } + } + return true; + } +} diff --git a/Config/Migration/1450753185_init.php b/Config/Migration/1450753185_init.php new file mode 100644 index 0000000..21c3c05 --- /dev/null +++ b/Config/Migration/1450753185_init.php @@ -0,0 +1,266 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +/** + * Registrations Migration + * + * @author Allcreator + * @package NetCommons\Registrations\Config\Migration + */ +class Init extends CakeMigration { + +/** + * Migration description + * + * @var string + */ + public $description = 'init'; + +/** + * Actions to be performed + * + * @var array $migration + */ + public $migration = array( + 'up' => array( + 'create_table' => array( + 'registration_answer_summaries' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'answer_status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '回答状態 1ページずつ表示するような登録フォームの場合、途中状態か否か | 0:回答未完了 | 1:回答完了'), + 'test_status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'テスト時の回答かどうか 0:本番回答 | 1:テスト時回答'), + 'answer_number' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '回答回数 ログインして回答している人物の場合に限定して回答回数をカウントする'), + 'answer_time' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '回答完了の時刻 ページわけされている場合、insert_timeは回答開始時刻となるため、完了時刻を設ける'), + 'registration_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'session_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム回答した時のセッション値を保存します。', 'charset' => 'utf8'), + 'user_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'ログイン後、登録フォームに回答した人のusersテーブルのid。未ログインの場合NULL'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_answers' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'matrix_choice_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'answer_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '回答した文字列を設定する +選択肢、リストなどの選ぶだけの場合は、選択肢のid値:ラベルを入れる + +選択肢タイプで「その他」を選んだ場合は、入力されたテキストは、ここではなく、other_answer_valueに入れる。 + +複数選択肢 +これらの場合は、(id値):(ラベル)を|つなぎで並べる。 +', 'charset' => 'utf8'), + 'other_answer_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '選択しタイプで「その他」を選んだ場合、入力されたテキストはここに入る。', 'charset' => 'utf8'), + 'registration_answer_summary_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'registration_question_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_answer_registration_answer_summary1_idx' => array('column' => 'registration_answer_summary_id', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_choices' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'matrix_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'マトリックスタイプの場合の行列区分 | 0:行 | 1:列'), + 'other_choice_type' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 4, 'unsigned' => false, 'comment' => 'その他欄か否か、また、その他欄の入力エリアタイプ | 0:その他欄でない | 1:テキストタイプを伴ったその他欄 | 2:テキストエリアタイプを伴ったその他欄 + +'), + 'choice_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => '選択肢並び順'), + 'choice_label' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '\'選択肢ラベル\'', 'charset' => 'utf8'), + 'choice_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '選択肢の値 デフォルトでidと同じ値が入る(将来、選択肢の値を任意に設定して重みアンケができるよう)', 'charset' => 'utf8'), + 'skip_page_sequence' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'registrationsのskip_flagがスキップ有りの時、スキップ先のページ'), + 'jump_route_number' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'registration_questionsのis_jumpが有りのとき、分岐先のルート'), + 'graph_color' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 16, 'collate' => 'utf8_general_ci', 'comment' => 'グラフ描画時の色', 'charset' => 'utf8'), + 'registration_question_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_choice_registration_question1_idx' => array('column' => 'registration_question_id', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_frame_display_registrations' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'registration_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_frame_display_registrations_registration_idx' => array('column' => 'frame_key', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_frame_settings' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'display_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '0:単一表示(default)|1:リスト表示'), + 'display_num_per_page' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 3, 'unsigned' => false, 'comment' => 'リスト表示の場合、1ページ当たりに表示する登録フォーム件数'), + 'sort_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '表示並び順 0:新着順 1:回答期間順(降順) 2:登録フォームステータス順(昇順) 3:タイトル順(昇順)'), + 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_frame_settings_frames1_idx' => array('column' => 'frame_key', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_pages' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'registration_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'page_title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'ページ名', 'charset' => 'utf8'), + 'route_number' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false), + 'page_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => 'ページ表示順'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_pages_registrations1_idx' => array('column' => 'registration_id', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_questions' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'question_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => '質問表示順'), + 'question_value' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'question_type' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '質問タイプ | 1:択一選択 | 2:複数選択 | 3:テキスト | 4:テキストエリア | 5:マトリクス(択一) | 6:マトリクス(複数) | 7:日付・時刻 | 8:リスト +'), + 'description' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'is_require' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '回答必須フラグ | 0:不要 | 1:必須'), + 'question_type_option' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '1: 数値 | 2:日付(未実装) | 3:時刻(未実装) | 4:メール(未実装) | 5:URL(未実装) | 6:電話番号(未実装) | HTML5チェックで将来的に実装されそうなものに順次対応'), + 'is_choice_random' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '選択肢表示順序ランダム化 | 質問タイプが1:択一選択 2:複数選択 6:マトリクス(択一) 7:マトリクス(複数) のとき有効 ただし、6,7については行がランダムになるだけで列はランダム化されない'), + 'is_skip' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '登録フォーム回答のスキップ有無 0:スキップ 無し 1:スキップ有り'), + 'is_jump' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '登録フォーム回答の分岐'), + 'is_range' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '範囲設定しているか否か'), + 'min' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 32, 'collate' => 'utf8_general_ci', 'comment' => '最小値 question_typeがテキストで数値タイプのときのみ有効 ', 'charset' => 'utf8'), + 'max' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 32, 'collate' => 'utf8_general_ci', 'comment' => '最大値 question_typeがテキストで数値タイプのときのみ有効 ', 'charset' => 'utf8'), + 'is_result_display' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => '集計結果表示をするか否か | 0:しない | 1:する'), + 'result_display_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '表示形式デファイン値が|区切りで保存される | 0:棒グラフ(マトリクスのときは自動的に積み上げ棒グラフ) | 1:円グラフ | 2:表 +'), + 'registration_page_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_question_registration_page1_idx' => array('column' => 'registration_page_id', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registration_settings' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'use_workflow' => array('type' => 'boolean', 'null' => false, 'default' => '1'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_blocks_settings_blocks1_idx' => array('column' => 'block_key', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + 'registrations' => array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'is_active' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '公開中データか否か'), + 'is_latest' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '最新編集データであるか否か'), + 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'public status, 1: public, 2: public pending, 3: draft during 4: remand | 公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し |'), + 'title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォームタイトル', 'charset' => 'utf8'), + 'sub_title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォームサブタイトル', 'charset' => 'utf8'), + 'public_type' => array('type' => 'integer', 'null' => false, 'default' => '1', 'length' => 4, 'unsigned' => false), + 'publish_start' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'publish_end' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'is_no_member_allow' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '非会員の回答を許可するか | 0:許可しない | 1:許可する'), + 'is_anonymity' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '会員回答であっても匿名扱いとするか否か | 0:非匿名 | 1:匿名'), + 'is_key_pass_use' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'キーフレーズによる回答ガードを設けるか | 0:キーフレーズガードは用いない | 1:キーフレーズガードを用いる'), + 'key_phrase' => array('type' => 'string', 'null' => true, 'default' => 'NetCommons', 'length' => 128, 'collate' => 'utf8_general_ci', 'comment' => 'キーフレーズ', 'charset' => 'utf8'), + 'is_repeat_allow' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'is_total_show' => array('type' => 'boolean', 'null' => true, 'default' => '1', 'comment' => '集計結果を表示するか否か | 0:表示しない | 1:表示する'), + 'total_show_timing' => array('type' => 'integer', 'null' => true, 'default' => '0', 'length' => 4, 'unsigned' => false, 'comment' => '集計結果を表示するタイミング | 0:登録フォーム回答後、すぐ | 1:期間設定'), + 'total_show_start_period' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'total_comment' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '集計表示ページの先頭に書くメッセージコメント', 'charset' => 'utf8'), + 'is_image_authentication' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'SPAMガード項目を表示するか否か | 0:表示しない | 1:表示する'), + 'thanks_content' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム最後に表示するお礼メッセージ', 'charset' => 'utf8'), + 'is_open_mail_send' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '登録フォーム開始メールを送信するか(現在未使用) | 0:しない | 1:する'), + 'open_mail_subject' => array('type' => 'string', 'null' => true, 'default' => 'Registration to you has arrived', 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム開始メールタイトル(現在未使用)', 'charset' => 'utf8'), + 'open_mail_body' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム開始通知メール本文(現在未使用)', 'charset' => 'utf8'), + 'is_answer_mail_send' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '登録フォーム回答時に編集者、編集長にメールで知らせるか否か | 0:知らせない| 1:知らせる +'), + 'is_page_random' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'ページ表示順序ランダム化(※将来機能) +選択肢分岐機能との兼ね合いを考えなくてはならないため、現時点での機能盛り込みは見送る'), + 'import_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'export_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registrations_blocks1_idx' => array('column' => 'block_id', 'unique' => 0), + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'), + ), + ), + ), + 'down' => array( + 'drop_table' => array( + 'registration_answer_summaries', 'registration_answers', 'registration_choices', 'registration_frame_display_registrations', 'registration_frame_settings', 'registration_pages', 'registration_questions', 'registration_settings', 'registrations' + ), + ), + ); + +/** + * Before migration callback + * + * @param string $direction Direction of migration process (up or down) + * @return bool Should process continue + */ + public function before($direction) { + return true; + } + +/** + * After migration callback + * + * @param string $direction Direction of migration process (up or down) + * @return bool Should process continue + */ + public function after($direction) { + return true; + } +} diff --git a/Config/Schema/empty b/Config/Schema/empty new file mode 100644 index 0000000..e69de29 diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php new file mode 100644 index 0000000..2f1e5ec --- /dev/null +++ b/Config/Schema/schema.php @@ -0,0 +1,304 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ +/** + * Schema file + * + * @author AllCreator + * @package NetCommons\Registration\Config\Schema + * @SuppressWarnings(PHPMD.LongVariable) + * @SuppressWarnings(PHPMD.TooManyFields) + */ +class RegistrationsSchema extends CakeSchema { + +/** + * Database connection + * + * @var string + */ + public $connection = 'master'; + +/** + * before + * + * @param array $event event + * @return bool + */ + public function before($event = array()) { + return true; + } + +/** + * after + * + * @param array $event event + * @return void + */ + public function after($event = array()) { + } + +/** + * registration_answer_summaries table + * + * @var array + */ + public $registration_answer_summaries = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'answer_status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '回答状態 1ページずつ表示するような登録フォームの場合、途中状態か否か | 0:回答未完了 | 1:回答完了'), + 'test_status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'テスト時の回答かどうか 0:本番回答 | 1:テスト時回答'), + 'answer_number' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '回答回数 ログインして回答している人物の場合に限定して回答回数をカウントする'), + 'answer_time' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '回答完了の時刻 ページわけされている場合、insert_timeは回答開始時刻となるため、完了時刻を設ける'), + 'registration_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'session_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム回答した時のセッション値を保存します。', 'charset' => 'utf8'), + 'user_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'ログイン後、登録フォームに回答した人のusersテーブルのid。未ログインの場合NULL'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_answers table + * + * @var array + */ + public $registration_answers = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'matrix_choice_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'answer_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '回答した文字列を設定する +選択肢、リストなどの選ぶだけの場合は、選択肢のid値:ラベルを入れる + +選択肢タイプで「その他」を選んだ場合は、入力されたテキストは、ここではなく、other_answer_valueに入れる。 + +複数選択肢 +これらの場合は、(id値):(ラベル)を|つなぎで並べる。 +', 'charset' => 'utf8'), + 'other_answer_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '選択しタイプで「その他」を選んだ場合、入力されたテキストはここに入る。', 'charset' => 'utf8'), + 'registration_answer_summary_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'registration_question_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_answer_registration_answer_summary1_idx' => array('column' => 'registration_answer_summary_id', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_choices table + * + * @var array + */ + public $registration_choices = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'matrix_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'マトリックスタイプの場合の行列区分 | 0:行 | 1:列'), + 'other_choice_type' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 4, 'unsigned' => false, 'comment' => 'その他欄か否か、また、その他欄の入力エリアタイプ | 0:その他欄でない | 1:テキストタイプを伴ったその他欄 | 2:テキストエリアタイプを伴ったその他欄 + +'), + 'choice_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => '選択肢並び順'), + 'choice_label' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '\'選択肢ラベル\'', 'charset' => 'utf8'), + 'choice_value' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '選択肢の値 デフォルトでidと同じ値が入る(将来、選択肢の値を任意に設定して重みアンケができるよう)', 'charset' => 'utf8'), + 'skip_page_sequence' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'registrationsのskip_flagがスキップ有りの時、スキップ先のページ'), + 'jump_route_number' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'registration_questionsのis_jumpが有りのとき、分岐先のルート'), + 'graph_color' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 16, 'collate' => 'utf8_general_ci', 'comment' => 'グラフ描画時の色', 'charset' => 'utf8'), + 'registration_question_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_choice_registration_question1_idx' => array('column' => 'registration_question_id', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_frame_display_registrations table + * + * @var array + */ + public $registration_frame_display_registrations = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'registration_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_frame_display_registrations_registration_idx' => array('column' => 'frame_key', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_frame_settings table + * + * @var array + */ + public $registration_frame_settings = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'display_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '0:単一表示(default)|1:リスト表示'), + 'display_num_per_page' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 3, 'unsigned' => false, 'comment' => 'リスト表示の場合、1ページ当たりに表示する登録フォーム件数'), + 'sort_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '表示並び順 0:新着順 1:回答期間順(降順) 2:登録フォームステータス順(昇順) 3:タイトル順(昇順)'), + 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_frame_settings_frames1_idx' => array('column' => 'frame_key', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_pages table + * + * @var array + */ + public $registration_pages = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'registration_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'page_title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'ページ名', 'charset' => 'utf8'), + 'route_number' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false), + 'page_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => 'ページ表示順'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_pages_registrations1_idx' => array('column' => 'registration_id', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_questions table + * + * @var array + */ + public $registration_questions = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'question_sequence' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'comment' => '質問表示順'), + 'question_value' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'question_type' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '質問タイプ | 1:択一選択 | 2:複数選択 | 3:テキスト | 4:テキストエリア | 5:マトリクス(択一) | 6:マトリクス(複数) | 7:日付・時刻 | 8:リスト +'), + 'description' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'is_require' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '回答必須フラグ | 0:不要 | 1:必須'), + 'question_type_option' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '1: 数値 | 2:日付(未実装) | 3:時刻(未実装) | 4:メール(未実装) | 5:URL(未実装) | 6:電話番号(未実装) | HTML5チェックで将来的に実装されそうなものに順次対応'), + 'is_choice_random' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '選択肢表示順序ランダム化 | 質問タイプが1:択一選択 2:複数選択 6:マトリクス(択一) 7:マトリクス(複数) のとき有効 ただし、6,7については行がランダムになるだけで列はランダム化されない'), + 'is_skip' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '登録フォーム回答のスキップ有無 0:スキップ 無し 1:スキップ有り'), + 'is_jump' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '登録フォーム回答の分岐'), + 'is_range' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '範囲設定しているか否か'), + 'min' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 32, 'collate' => 'utf8_general_ci', 'comment' => '最小値 question_typeがテキストで数値タイプのときのみ有効 ', 'charset' => 'utf8'), + 'max' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 32, 'collate' => 'utf8_general_ci', 'comment' => '最大値 question_typeがテキストで数値タイプのときのみ有効 ', 'charset' => 'utf8'), + 'is_result_display' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => '集計結果表示をするか否か | 0:しない | 1:する'), + 'result_display_type' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '表示形式デファイン値が|区切りで保存される | 0:棒グラフ(マトリクスのときは自動的に積み上げ棒グラフ) | 1:円グラフ | 2:表 +'), + 'registration_page_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_question_registration_page1_idx' => array('column' => 'registration_page_id', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registration_blocks_settings table + * + * @var array + */ + public $registration_settings = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'use_workflow' => array('type' => 'boolean', 'null' => false, 'default' => '1'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registration_blocks_settings_blocks1_idx' => array('column' => 'block_key', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * registrations table + * + * @var array + */ + public $registrations = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'language_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'is_active' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '公開中データか否か'), + 'is_latest' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '最新編集データであるか否か'), + 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index'), + 'status' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => 'public status, 1: public, 2: public pending, 3: draft during 4: remand | 公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し |'), + 'title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォームタイトル', 'charset' => 'utf8'), + 'sub_title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォームサブタイトル', 'charset' => 'utf8'), + 'public_type' => array('type' => 'integer', 'null' => false, 'default' => '1', 'length' => 4, 'unsigned' => false), + 'publish_start' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'publish_end' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'is_no_member_allow' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '非会員の回答を許可するか | 0:許可しない | 1:許可する'), + 'is_anonymity' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '会員回答であっても匿名扱いとするか否か | 0:非匿名 | 1:匿名'), + 'is_key_pass_use' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'キーフレーズによる回答ガードを設けるか | 0:キーフレーズガードは用いない | 1:キーフレーズガードを用いる'), + 'key_phrase' => array('type' => 'string', 'null' => true, 'default' => 'NetCommons', 'length' => 128, 'collate' => 'utf8_general_ci', 'comment' => 'キーフレーズ', 'charset' => 'utf8'), + 'is_repeat_allow' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'is_total_show' => array('type' => 'boolean', 'null' => true, 'default' => '1', 'comment' => '集計結果を表示するか否か | 0:表示しない | 1:表示する'), + 'total_show_timing' => array('type' => 'integer', 'null' => true, 'default' => '0', 'length' => 4, 'unsigned' => false, 'comment' => '集計結果を表示するタイミング | 0:登録フォーム回答後、すぐ | 1:期間設定'), + 'total_show_start_period' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'total_comment' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '集計表示ページの先頭に書くメッセージコメント', 'charset' => 'utf8'), + 'is_image_authentication' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'SPAMガード項目を表示するか否か | 0:表示しない | 1:表示する'), + 'thanks_content' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム最後に表示するお礼メッセージ', 'charset' => 'utf8'), + 'is_open_mail_send' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '登録フォーム開始メールを送信するか(現在未使用) | 0:しない | 1:する'), + 'open_mail_subject' => array('type' => 'string', 'null' => true, 'default' => 'Registration to you has arrived', 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム開始メールタイトル(現在未使用)', 'charset' => 'utf8'), + 'open_mail_body' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '登録フォーム開始通知メール本文(現在未使用)', 'charset' => 'utf8'), + 'is_answer_mail_send' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => '登録フォーム回答時に編集者、編集長にメールで知らせるか否か | 0:知らせない| 1:知らせる +'), + 'is_page_random' => array('type' => 'boolean', 'null' => true, 'default' => '0', 'comment' => 'ページ表示順序ランダム化(※将来機能) +選択肢分岐機能との兼ね合いを考えなくてはならないため、現時点での機能盛り込みは見送る'), + 'import_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'export_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'fk_registrations_blocks1_idx' => array('column' => 'block_id', 'unique' => 0) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +} diff --git a/Console/Command/Task/empty b/Console/Command/Task/empty new file mode 100644 index 0000000..e69de29 diff --git a/Controller/Component/RegistrationsComponent.php b/Controller/Component/RegistrationsComponent.php new file mode 100644 index 0000000..5626bda --- /dev/null +++ b/Controller/Component/RegistrationsComponent.php @@ -0,0 +1,608 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('Component', 'Controller'); + +/** + * RegistrationsComponent + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationsComponent extends Component { + +/** + * コンテンツキーがパスに含まれる位置 + * + * @var int + */ + const REGISTRATION_KEY_PASS_INDEX = 1; + +/** + * バリデートタイプ + * ウィザード画面で形成中の判定をしてほしいときに使う + */ + const REGISTRATION_VALIDATE_TYPE = 'duringSetup'; + +/** + * answer max length + * + * @var int + */ + const REGISTRATION_MAX_ANSWER_LENGTH = 60000; + +/** + * default display registration item count + * + * @var int + */ + const REGISTRATION_DEFAULT_DISPLAY_NUM_PER_PAGE = 10; + +/** + * registration create options + * + * @var string + */ + const REGISTRATION_CREATE_OPT_NEW = 'create'; + const REGISTRATION_CREATE_OPT_REUSE = 'reuse'; + const REGISTRATION_CREATE_OPT_TEMPLATE = 'template'; + +/** + * registration view filter + * + * @var string + */ + const REGISTRATION_ANSWER_VIEW_ALL = 'viewall'; + const REGISTRATION_ANSWER_UNANSWERED = 'unanswered'; + const REGISTRATION_ANSWER_ANSWERED = 'answered'; + const REGISTRATION_ANSWER_TEST = 'test'; + +/** + * status registration status started + * + * @var string + */ + const STATUS_STARTED = '0'; + +/** + * status registration status not start + * + * @var string + */ + const STATUS_NOT_START = '1'; + +/** + * status registration status stopped + * + * @var string + */ + const STATUS_STOPPED = '2'; + +/** + * permission. not permit + * + * @var string + */ + const PERMISSION_NOT_PERMIT = '0'; + +/** + * permission. permit + * + * @var string + */ + const PERMISSION_PERMIT = '1'; + +/** + * uses. not use + * + * @var string + */ + const USES_NOT_USE = '0'; + +/** + * uses. use + * + * @var string + */ + const USES_USE = '1'; + +/** + * expression. not show + * + * @var string + */ + const EXPRESSION_NOT_SHOW = '0'; + +/** + * expression. show + * + * @var string + */ + const EXPRESSION_SHOW = '1'; + +/** + * action. not act + * + * @var string + */ + const ACTION_NOT_ACT = '0'; + +/** + * action. act + * + * @var string + */ + const ACTION_ACT = '1'; + +/** + * type. selection + * + * @var string + */ + const TYPE_SELECTION = '1'; + +/** + * type. multiple selection + * + * @var string + */ + const TYPE_MULTIPLE_SELECTION = '2'; + +/** + * type. text + * + * @var string + */ + const TYPE_TEXT = '3'; + +/** + * type. text area + * + * @var string + */ + const TYPE_TEXT_AREA = '4'; + +/** + * type. Matrix (selection list) + * + * @var string + */ + const TYPE_MATRIX_SELECTION_LIST = '5'; + +/** + * type. Matrix (multiple) + * + * @var string + */ + const TYPE_MATRIX_MULTIPLE = '6'; + +/** + * type. date and time + * + * @var string + */ + const TYPE_DATE_AND_TIME = '7'; + +/** + * type. single select box + * + * @var string + */ + const TYPE_SINGLE_SELECT_BOX = '8'; + +/** + * types list + * + * @var array + */ + static public $typesList = array( + self::TYPE_SELECTION, + self::TYPE_MULTIPLE_SELECTION, + self::TYPE_TEXT, + self::TYPE_TEXT_AREA, + self::TYPE_MATRIX_SELECTION_LIST, + self::TYPE_MATRIX_MULTIPLE, + self::TYPE_DATE_AND_TIME, + self::TYPE_SINGLE_SELECT_BOX + ); + +/** + * requires. not require + * + * @var string + */ + const REQUIRES_NOT_REQUIRE = '0'; + +/** + * requires. require + * + * @var string + */ + const REQUIRES_REQUIRE = '1'; + +/** + * type option. numeric value + * + * @var string + */ + const TYPE_OPTION_NUMERIC = '1'; + +/** + * type option. date + * + * @var string + */ + const TYPE_OPTION_DATE = '2'; + +/** + * type option. time + * + * @var string + */ + const TYPE_OPTION_TIME = '3'; + +/** + * type option. email + * + * @var string + */ + const TYPE_OPTION_EMAIL = '4'; + +/** + * type option. url + * + * @var string + */ + const TYPE_OPTION_URL = '5'; + +/** + * type option. phone number + * + * @var string + */ + const TYPE_OPTION_PHONE_NUMBER = '6'; + +/** + * type option. time + * + * @var string + */ + const TYPE_OPTION_DATE_TIME = '7'; + +/** + * type options list + * + * @var array + */ + static public $typeOptionsList = array( + self::TYPE_OPTION_NUMERIC, + self::TYPE_OPTION_DATE, + self::TYPE_OPTION_TIME, + self::TYPE_OPTION_EMAIL, + self::TYPE_OPTION_URL, + self::TYPE_OPTION_PHONE_NUMBER + ); + +/** + * result display type. bar chart + * + * @var string + */ + const RESULT_DISPLAY_TYPE_BAR_CHART = '0'; + +/** + * result display type. pie chart + * + * @var string + */ + const RESULT_DISPLAY_TYPE_PIE_CHART = '1'; + +/** + * result display type. table + * + * @var string + */ + const RESULT_DISPLAY_TYPE_TABLE = '2'; + +/** + * result display type list + * + * @var array + */ + static public $resultDispTypesList = array( + self::RESULT_DISPLAY_TYPE_BAR_CHART, + self::RESULT_DISPLAY_TYPE_PIE_CHART, + self::RESULT_DISPLAY_TYPE_TABLE + ); + +/** + * matrix type. row or no matrix + * + * @var string + */ + const MATRIX_TYPE_ROW_OR_NO_MATRIX = '0'; + +/** + * matrix type. column + * + * @var string + */ + const MATRIX_TYPE_COLUMN = '1'; + +/** + * other choice type. no other field + * + * @var string + */ + const OTHER_CHOICE_TYPE_NO_OTHER_FILED = '0'; + +/** + * other choice type. other field with text + * + * @var string + */ + const OTHER_CHOICE_TYPE_OTHER_FIELD_WITH_TEXT = '1'; + +/** + * other choice type. other field with textarea + * + * @var string + */ + const OTHER_CHOICE_TYPE_OTHER_FIELD_WITH_TEXTAREA = '2'; + +/** + * display type. single + * + * @var string + */ + const DISPLAY_TYPE_SINGLE = '0'; + +/** + * display type. list + * + * @var string + */ + const DISPLAY_TYPE_LIST = '1'; + +/** + * display_sort_type. new arrivals + * + * @var string + */ + const DISPLAY_SORT_TYPE_NEW_ARRIVALS = '0'; + +/** + * display_sort_type. response time (descending) + * + * @var string + */ + const DISPLAY_SORT_TYPE_RESPONSE_TIME_DESC = '1'; + +/** + * display_sort_type. survey status order (ascending) + * + * @var string + */ + const DISPLAY_SORT_TYPE_SURVEY_STATUS_ORDER_ASC = '2'; + +/** + * display_sort_type. by title (ascending order) + * + * @var string + */ + const DISPLAY_SORT_TYPE_BY_TITLE_ASC = '3'; + +/** + * display_sort_types list + * + * @var array + */ + static public $displaySortTypesList = array( + self::DISPLAY_SORT_TYPE_NEW_ARRIVALS, + self::DISPLAY_SORT_TYPE_RESPONSE_TIME_DESC, + self::DISPLAY_SORT_TYPE_SURVEY_STATUS_ORDER_ASC, + self::DISPLAY_SORT_TYPE_BY_TITLE_ASC + ); + +/** + * skip_flag. no_skip + * + * @var string + */ + const SKIP_FLAGS_NO_SKIP = '0'; + +/** + * skip_flag. skip + * + * @var string + */ + const SKIP_FLAGS_SKIP = '1'; + +/** + * skip_flag. goto end + * + * @var integer + */ + const SKIP_GO_TO_END = 99999; +/** + * first page sequence + * + * @var integer + */ + const FIRST_PAGE_SEQUENCE = 0; + +/** + * test answer status, peform( means on air or HONBAN ) + * + * @var string + */ + const TEST_ANSWER_STATUS_PEFORM = '0'; + +/** + * test answer status, test + * + * @var string + */ + const TEST_ANSWER_STATUS_TEST = '1'; + +/** + * percentage unit + * @var string + */ + const PERCENTAGE_UNIT = '%'; + +/** + * not operation(=nop) mark + * @var string + */ + const NOT_OPERATION_MARK = '--'; + +/** + * answer delimiter + * + * @var string + */ + const ANSWER_DELIMITER = '|'; + const ANSWER_VALUE_DELIMITER = ':'; + +/** + * registration period stat + * + * @var integer + */ + const REGISTRATION_PERIOD_STAT_IN = 1; + const REGISTRATION_PERIOD_STAT_BEFORE = 2; + const REGISTRATION_PERIOD_STAT_END = 3; + +/** + * registration sort type + * + * @var integer + */ + const REGISTRATION_SORT_MODIFIED = 0; + const REGISTRATION_SORT_CREATED = 1; + const REGISTRATION_SORT_TITLE = 2; + const REGISTRATION_SORT_END = 3; + +/** + * registration template exoprt file name + * + * @var string + */ + const REGISTRATION_TEMPLATE_EXPORT_FILENAME = 'ExportRegistration.zip'; + const REGISTRATION_TEMPLATE_FILENAME = 'Registrations.zip'; + const REGISTRATION_JSON_FILENAME = 'Registrations.json'; + const REGISTRATION_FINGER_PRINT_FILENAME = 'finger_print.txt'; + +/** + * getDisplayNumberOptions + * + * @return array + */ + public static function getDisplayNumberOptions() { + return array( + 5 => 5 . __d('registrations', 'item'), + 10 => 10 . __d('registrations', 'item'), + 20 => 20 . __d('registrations', 'item'), + 50 => 50 . __d('registrations', 'item'), + 100 => 100 . __d('registrations', 'item'), + ); + } + +/** + * getSortOrders + * + * @return array + */ + public static function getSortOrders() { + return array( + self::REGISTRATION_SORT_MODIFIED => __d('registrations', 'New Modified'), + self::REGISTRATION_SORT_CREATED => __d('registrations', 'Registration order'), + self::REGISTRATION_SORT_TITLE => __d('registrations', 'Title'), + self::REGISTRATION_SORT_END => __d('registrations', 'End period'), + ); + } + +/** + * 登録フォーム質問タイプのデータ配列を返す + * + * @return array 質問タイプの定値とそれに相応するラベル + */ + public function getQuestionTypeOptionsWithLabel() { + return array( + self::TYPE_SELECTION => __d('registrations', 'Single choice'), + self::TYPE_MULTIPLE_SELECTION => __d('registrations', 'Multiple choice'), + self::TYPE_TEXT => __d('registrations', 'Single text'), + self::TYPE_TEXT_AREA => __d('registrations', 'Multiple text'), + self::TYPE_MATRIX_SELECTION_LIST => __d('registrations', 'Single choice matrix'), + self::TYPE_MATRIX_MULTIPLE => __d('registrations', 'Multiple choice matrix'), + self::TYPE_DATE_AND_TIME => __d('registrations', 'Date and time'), + self::TYPE_SINGLE_SELECT_BOX => __d('registrations', 'List select') + ); + } + +/** + * isSingleInputType + * + * @param int $type registration type + * @return bool + */ + public static function isOnlyInputType($type) { + // text, textarea, date などの単純入力タイプであるか + if ($type == self::TYPE_TEXT) { + return true; + } + if ($type == self::TYPE_TEXT_AREA) { + return true; + } + if ($type == self::TYPE_DATE_AND_TIME) { + return true; + } + return false; + } + +/** + * isSelectionInputType + * + * @param int $type registration type + * @return bool + */ + public static function isSelectionInputType($type) { + // 択一選択、複数選択、リスト選択 などの単純選択タイプであるか + if ($type == self::TYPE_SELECTION) { + return true; + } + if ($type == self::TYPE_MULTIPLE_SELECTION) { + return true; + } + if ($type == self::TYPE_SINGLE_SELECT_BOX) { + return true; + } + return false; + } + +/** + * isMatrixInputType + * + * @param int $type registration type + * @return bool + */ + public static function isMatrixInputType($type) { + // マトリクス選択タイプであるか + if ($type == self::TYPE_MATRIX_SELECTION_LIST) { + return true; + } + if ($type == self::TYPE_MATRIX_MULTIPLE) { + return true; + } + return false; + } +} diff --git a/Controller/Component/RegistrationsOwnAnswerComponent.php b/Controller/Component/RegistrationsOwnAnswerComponent.php new file mode 100644 index 0000000..e901db1 --- /dev/null +++ b/Controller/Component/RegistrationsOwnAnswerComponent.php @@ -0,0 +1,188 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('Component', 'Controller'); + +/** + * RegistrationsOwnAnswerComponent + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationsOwnAnswerComponent extends Component { + +/** + * Answered registration keys + * + * 回答済み登録フォームキー配列 + * + * @var array + */ + private $__ownAnsweredKeys = null; + +/** + * 指定された登録フォームに該当する回答中登録フォームのサマリを取得する + * + * @param string $registrationKey 回答済に追加する登録フォームキー + * @return progressive Answer Summary id list + */ + public function getProgressiveSummaryOfThisUser($registrationKey) { + // 戻り値初期化 + $summary = false; + $answerSummary = ClassRegistry::init('Registrations.RegistrationAnswerSummary'); + // 未ログインの人の場合はセッションにある回答中データを参照する + if (! Current::read('User.id')) { + $session = $this->_Collection->load('Session'); + $summaryId = $session->read('Registrations.progressiveSummary.' . $registrationKey); + if ($summaryId) { + $summary = $answerSummary->findById($summaryId); + } + return $summary; + } + // ログインユーザーはDBから探す + $conditions = array( + 'answer_status' => RegistrationsComponent::ACTION_NOT_ACT, + 'registration_key' => $registrationKey, + 'user_id' => Current::read('User.id'), + ); + $summary = $answerSummary->find('first', array( + 'conditions' => $conditions, + 'order' => 'RegistrationAnswerSummary.created DESC' // 最も新しいものを一つ選ぶ + )); + return $summary; + } +/** + * 指定された登録フォームに対応する回答中サマリを作成 + * + * @param array $registration 登録フォーム + * @return progressive Answer Summary data + */ + public function forceGetProgressiveAnswerSummary($registration) { + $summary = $this->getProgressiveSummaryOfThisUser($registration['Registration']['key']); + if (! $summary) { + $answerSummary = ClassRegistry::init('Registrations.RegistrationAnswerSummary'); + $session = $this->_Collection->load('Session'); + $summary = $answerSummary->forceGetProgressiveAnswerSummary($registration, Current::read('User.id'), $session->id()); + if ($summary) { + $this->saveProgressiveSummaryOfThisUser($registration['Registration']['key'], $summary['RegistrationAnswerSummary']['id']); + } + } + + return $summary; + } + +/** + * 指定された登録フォームのサマリIDを回答中サマリIDとしてセッションに記録 + * + * @param string $registrationKey 回答中の登録フォームキー + * @param int $summaryId 回答中のサマリのID + * @return void + */ + public function saveProgressiveSummaryOfThisUser($registrationKey, $summaryId) { + $session = $this->_Collection->load('Session'); + $session->write('Registrations.progressiveSummary.' . $registrationKey, $summaryId); + } +/** + * セッションから指定された登録フォームの回答中サマリIDを削除 + * + * @param string $registrationKey 登録フォームキー + * @return void + */ + public function deleteProgressiveSummaryOfThisUser($registrationKey) { + $session = $this->_Collection->load('Session'); + $session->delete('Registrations.progressiveSummary.' . $registrationKey); + } + +/** + * 回答済み登録フォームリストを取得する + * + * @return Answered Registration keys list + */ + public function getOwnAnsweredKeys() { + if (isset($this->__ownAnsweredKeys)) { + return $this->__ownAnsweredKeys; + } + + $this->__ownAnsweredKeys = array(); + + if (! Current::read('User.id')) { + $session = $this->_Collection->load('Session'); + $blockId = Current::read('Block.id'); + $ownAnsweredKeys = $session->read('Registrations.ownAnsweredKeys.' . $blockId); + if (isset($ownAnsweredKeys)) { + $this->__ownAnsweredKeys = explode(',', $ownAnsweredKeys); + } + + return $this->__ownAnsweredKeys; + } + + $answerSummary = ClassRegistry::init('Registrations.RegistrationAnswerSummary'); + $conditions = array( + 'user_id' => Current::read('User.id'), + 'answer_status' => RegistrationsComponent::ACTION_ACT, + 'test_status' => RegistrationsComponent::TEST_ANSWER_STATUS_PEFORM, + 'answer_number' => 1 + ); + $ownAnsweredKeys = $answerSummary->find( + 'list', + array( + 'conditions' => $conditions, + 'fields' => array('RegistrationAnswerSummary.registration_key'), + 'recursive' => -1 + ) + ); + $this->__ownAnsweredKeys = array_values($ownAnsweredKeys); // idの使用を防ぐ(いらない?) + + return $this->__ownAnsweredKeys; + } +/** + * 登録フォーム回答済みかどうかを返す + * + * @param string $registrationKey 回答済に追加する登録フォームキー + * @return bool + */ + public function checkOwnAnsweredKeys($registrationKey) { + // まだ回答済データが初期状態のときはまずは確保 + if ($this->__ownAnsweredKeys === null) { + $this->getOwnAnsweredKeys(); + } + if (in_array($registrationKey, $this->__ownAnsweredKeys)) { + return true; + } + return false; + } +/** + * セッションの回答済み登録フォームリストに新しい登録フォームを追加する + * + * @param string $registrationKey 回答済に追加する登録フォームキー + * @return void + */ + public function saveOwnAnsweredKeys($registrationKey) { + // まだ回答済データが初期状態のときはまずは確保 + if ($this->__ownAnsweredKeys === null) { + $this->getOwnAnsweredKeys(); + } + // 回答済み登録フォーム配列に追加 + $this->__ownAnsweredKeys[] = $registrationKey; + // ログイン状態の人の場合はこれ以上の処理は不要 + if (Current::read('User.id')) { + return; + } + // 未ログインの人の場合はセッションに書いておく + $session = $this->_Collection->load('Session'); + $blockId = Current::read('Block.id'); + $session->write('Registrations.ownAnsweredKeys.' . $blockId, implode(',', $this->__ownAnsweredKeys)); + + // 回答中登録フォームからは削除しておく + $this->deleteProgressiveSummaryOfThisUser($registrationKey); + } + +} diff --git a/Controller/Component/empty b/Controller/Component/empty new file mode 100644 index 0000000..e69de29 diff --git a/Controller/RegistrationAddController.php b/Controller/RegistrationAddController.php new file mode 100644 index 0000000..68469fb --- /dev/null +++ b/Controller/RegistrationAddController.php @@ -0,0 +1,106 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationsAddController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationAddController extends RegistrationsAppController { + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Files.FileModel', // FileUpload + 'PluginManager.Plugin', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'Files.FileUpload', // FileUpload + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'add' => 'content_creatable', + ), + ), + 'Registrations.Registrations', + ); + +/** + * use helpers + * + * @var array + */ + public $helpers = array( + 'Registrations.RegistrationStatusLabel', + 'Registrations.RegistrationUtil' + ); + +/** + * add registration display method + * + * @return void + */ + public function add() { + // NetCommonsお約束:投稿権限のある人物しかこのアクションにアクセスできない + // それは$componentsの組み込みでallow => add => content_creatableで担保される + // アクション処理内でチェックする必要はない + + // POSTされたデータを読み取り + if ($this->request->isPost()) { + // Postデータをもとにした新登録フォームデータの取得をModelに依頼する + $actionModel = ClassRegistry::init('Registrations.ActionRegistrationAdd', 'true'); + if ($registration = $actionModel->createRegistration($this->request->data)) { + $tm = $this->_getRegistrationEditSessionIndex(); + // 作成中登録フォームデータをセッションキャッシュに書く + $this->Session->write('Registrations.registrationEdit.' . $tm, $registration); + + // 次の画面へリダイレクト + $this->redirect(NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_edit', + 'action' => 'edit_question', + Current::read('Block.id'), + 'frame_id' => Current::read('Frame.id'), + 's_id' => $tm, + ))); + return; + } else { + // データに不備があった場合 + $this->NetCommons->handleValidationError($actionModel->validationErrors); + } + } + + // 過去データ 取り出し + $pastRegistrations = $this->Registration->getRegistrationsList(array(), array('limit' => 1000), array('recursive' => -1)); + $this->set('pastRegistrations', $pastRegistrations); + + // + // NetCommonsお約束:投稿のデータはrequest dataに設定する + // + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + // create_optionが未設定のときは初期値として「NEW」を設定する + if (! $this->request->data('ActionRegistrationAdd.create_option')) { + $this->request->data('ActionRegistrationAdd.create_option', RegistrationsComponent::REGISTRATION_CREATE_OPT_NEW); + } + } +} \ No newline at end of file diff --git a/Controller/RegistrationAnswerSummariesController.php b/Controller/RegistrationAnswerSummariesController.php new file mode 100644 index 0000000..afe4494 --- /dev/null +++ b/Controller/RegistrationAnswerSummariesController.php @@ -0,0 +1,117 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationAnswerSummariesController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationAnswerSummariesController extends RegistrationsAppController { + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Registrations.Registration', + 'Registrations.RegistrationPage', + 'Registrations.RegistrationQuestion', + 'Registrations.RegistrationChoice', + 'Registrations.RegistrationAnswerSummary', + 'Registrations.RegistrationAnswer', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'NetCommons.Permission', + 'Registrations.Registrations', + ); + +/** + * use helpers + * + */ + public $helpers = array( + 'Workflow.Workflow', + ); + +/** + * target registration data + * + */ + private $__registration = null; + +/** + * beforeFilter + * + * @return void + */ + public function beforeFilter() { + parent::beforeFilter(); + + // ゲストアクセスOKのアクションを設定 + $this->Auth->allow('view'); + + // NetCommonsお約束:編集画面へのURLに編集対象のコンテンツキーが含まれている + // まずは、そのキーを取り出す + // 登録フォームキー + $registrationKey = $this->_getRegistrationKeyFromPass(); + + // キーで指定された登録フォームデータを取り出しておく + $conditions = $this->Registration->getBaseCondition( + array('Registration.key' => $registrationKey) + ); + // 集計結果の表示は登録フォーム公開時期とは異なるので + $conditions = Hash::remove($conditions, 'public_type'); + $conditions = Hash::remove($conditions, 'publish_start'); + $conditions = Hash::remove($conditions, 'publish_end'); + + $this->__registration = $this->Registration->find('first', array( + 'conditions' => $conditions, + )); + if (! $this->__registration) { + $this->setAction('throwBadRequest'); + return; + } + + //集計表示していいかどうかの判断 + + if (! $this->isAbleToDisplayAggregatedData($this->__registration)) { + $this->setAction('throwBadRequest'); + return; + } + } + +/** + * result method + * + * @return void + */ + public function view() { + $registration = $this->__registration; + + //集計処理を行います。 + $questions = $this->RegistrationAnswerSummary->getAggregate($registration); + + //画面用データをセットする。 + $this->set('registration', $registration); + $this->set('questions', $questions); + } + +} \ No newline at end of file diff --git a/Controller/RegistrationAnswersController.php b/Controller/RegistrationAnswersController.php new file mode 100644 index 0000000..7c91f3b --- /dev/null +++ b/Controller/RegistrationAnswersController.php @@ -0,0 +1,334 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationAnswersController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationAnswersController extends RegistrationsAppController { + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Registrations.RegistrationPage', + 'Registrations.RegistrationAnswerSummary', + 'Registrations.RegistrationAnswer', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'NetCommons.Permission', + 'Registrations.Registrations', + 'Registrations.RegistrationsOwnAnswer', + 'AuthorizationKeys.AuthorizationKey' => array( + 'operationType' => 'none', + 'targetAction' => 'view', + 'model' => 'Registration', + 'contentId' => 0), + 'VisualCaptcha.VisualCaptcha' => array( + 'operationType' => 'none', + 'targetAction' => 'view'), + ); + +/** + * use helpers + * + */ + public $helpers = [ + 'NetCommons.Date', + 'Workflow.Workflow', + 'Registrations.RegistrationAnswer' + ]; + +/** + * target registration data + * + */ + private $__registration = null; + +/** + * target isAbleToAnswer Action + * + */ + private $__ableToAnswerAction = ['view', 'confirm']; + +/** + * beforeFilter + * NetCommonsお約束:できることならControllerのbeforeFilterで実行可/不可の判定して流れを変える + * + * @return void + */ + public function beforeFilter() { + // ゲストアクセスOKのアクションを設定 + $this->Auth->allow('view', 'confirm', 'thanks', 'no_more_answer'); + + // 親クラスのbeforeFilterを済ませる + parent::beforeFilter(); + + // NetCommonsお約束:編集画面へのURLに編集対象のコンテンツキーが含まれている + // まずは、そのキーを取り出す + // 登録フォームキー + $registrationKey = $this->_getRegistrationKeyFromPass(); + + // キーで指定された登録フォームデータを取り出しておく + $conditions = $this->Registration->getBaseCondition( + array('Registration.key' => $registrationKey) + ); + + $this->__registration = $this->Registration->find('first', array( + 'conditions' => $conditions, + )); + if (! $this->__registration) { + $this->setAction('throwBadRequest'); + return; + } + + // 以下のisAbleto..の内部関数にてNetCommonsお約束である編集権限、参照権限チェックを済ませています + // 閲覧可能か + if (!$this->isAbleTo($this->__registration)) { + // 不可能な時は「回答できません」画面を出すだけ + $this->setAction('no_more_answer'); + return; + } + if (in_array($this->action, $this->__ableToAnswerAction)) { + // 回答可能か + if (!$this->isAbleToAnswer($this->__registration)) { + // 回答が不可能な時は「回答できません」画面を出すだけ + $this->setAction('no_more_answer'); + return; + } + } + // 回答の初めのページであることが各種認証行う条件 + if (!$this->request->isPost() || !isset($this->request->data['RegistrationPage']['page_sequence'])) { + // 認証キーコンポーネントお約束: + // 取り出した登録フォームが認証キー確認を求めているなら、operationTypeをすり替える + if ($this->__registration['Registration']['is_key_pass_use'] == RegistrationsComponent::USES_USE) { + $this->AuthorizationKey->operationType = 'redirect'; + $this->AuthorizationKey->contentId = $this->__registration['Registration']['id']; + } + // 画像認証コンポーネントお約束: + // 取り出した登録フォームが画像認証ありならば、operationTypeをすり替える + if ($this->__registration['Registration']['is_image_authentication'] == RegistrationsComponent::USES_USE) { + $this->VisualCaptcha->operationType = 'redirect'; + } + } + } +/** + * test_mode + * + * テストモード回答のとき、一番最初に表示するページ + * 一覧表示画面で「テスト」ボタンがここへ誘導するようになっている。 + * どのような登録フォームであるのかの各種属性設定をわかりやすくまとめて表示する表紙的な役割を果たす。 + * + * あくまで作成者の便宜のために表示しているものであるので、最初のページだったら必ずここを表示といったような + * 強制的redirectなどは設定しない。なので強制URL-Hackしたらこの画面をスキップすることだって可能。 + * 作成者への「便宜」のための親切心ページなのでスキップしたい人にはそうさせてあげるのでよいと考える。 + * + * @return void + */ + public function test_mode() { + $status = $this->__registration['Registration']['status']; + // テストモード確認画面からのPOSTや、現在の登録フォームデータのステータスが公開状態の時 + // 次へリダイレクト + if ($this->request->isPost() || $status == WorkflowComponent::STATUS_PUBLISHED) { + $this->redirect(NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_answers', + 'action' => 'view', + Current::read('Block.id'), + $this->_getRegistrationKey($this->__registration), + 'frame_id' => Current::read('Frame.id') + ))); + return; + } + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + $this->set('registration', $this->__registration); + } + +/** + * view method + * Display the question of the registration , to accept the answer input + * + * @return void + */ + public function view() { + $registration = $this->__registration; + $registrationKey = $this->_getRegistrationKey($this->__registration); + + // 選択肢ランダム表示対応 + $this->__shuffleChoice($registration); + + // ページの指定のない場合はFIRST_PAGE_SEQUENCEをデフォルトとする + $nextPageSeq = RegistrationsComponent::FIRST_PAGE_SEQUENCE; // default + + // POSTチェック + if ($this->request->isPost()) { + // 回答データがある場合は回答をDBに書きこむ + if (isset($this->data['RegistrationAnswer'])) { + $summary = $this->RegistrationsOwnAnswer->forceGetProgressiveAnswerSummary($this->__registration); + if (! $summary) { + // 保存エラーの場合は今のページを再表示 + $nextPageSeq = $this->data['RegistrationPage']['page_sequence']; + } else { + if (! $this->RegistrationAnswer->saveAnswer($this->data, $registration, $summary)) { + // 保存エラーの場合は今のページを再表示 + $nextPageSeq = $this->data['RegistrationPage']['page_sequence']; + } else { + // 回答データがあり、無事保存できたら次ページを取得する + $nextPageSeq = $this->RegistrationPage->getNextPage( + $registration, + $this->data['RegistrationPage']['page_sequence'], + $this->data['RegistrationAnswer']); + } + } + } + // 次ページはもう存在しない + if ($nextPageSeq === false) { + // 確認画面へ + $url = NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_answers', + 'action' => 'confirm', + Current::read('Block.id'), + $registrationKey, + 'frame_id' => Current::read('Frame.id'), + )); + $this->redirect($url); + return; + } + } + if (! ($this->request->isPost() && $nextPageSeq == $this->data['RegistrationPage']['page_sequence'])) { + $summary = $this->RegistrationsOwnAnswer->getProgressiveSummaryOfThisUser($registrationKey); + $setAnswers = $this->RegistrationAnswer->getProgressiveAnswerOfThisSummary($summary); + $this->set('answers', $setAnswers); + $this->request->data['RegistrationAnswer'] = $setAnswers; + + // 入力される回答データですがsetで設定するデータとして扱います + // 誠にCake流儀でなくて申し訳ないのですが、様々な種別のAnswerデータを + // 特殊な文字列加工して統一化した形状でDBに入れている都合上、このような仕儀になっています + } else { + $this->set('answers', $this->request->data['RegistrationAnswer']); + } + + // 質問情報をView変数にセット + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + $this->request->data['RegistrationPage'] = $registration['RegistrationPage'][$nextPageSeq]; + $this->set('registration', $registration); + $this->set('questionPage', $registration['RegistrationPage'][$nextPageSeq]); + $this->NetCommons->handleValidationError($this->RegistrationAnswer->validationErrors); + } +/** + * confirm method + * + * @return void + */ + public function confirm() { + // 解答入力画面で表示していたときのシャッフルを取り出す + $this->__shuffleChoice($this->__registration); + + // 回答中サマリレコード取得 + $summary = $this->RegistrationsOwnAnswer->getProgressiveSummaryOfThisUser( + $this->_getRegistrationKey($this->__registration)); + if (!$summary) { + $this->setAction('throwBadRequest'); + return; + } + + // POSTチェック + if ($this->request->isPost()) { + // サマリの状態を完了にして確定する + $summary['RegistrationAnswerSummary']['answer_status'] = RegistrationsComponent::ACTION_ACT; + $summary['RegistrationAnswerSummary']['answer_time'] = (new NetCommonsTime())->getNowDatetime(); + $this->RegistrationAnswerSummary->save($summary['RegistrationAnswerSummary']); + $this->RegistrationsOwnAnswer->saveOwnAnsweredKeys($this->_getRegistrationKey($this->__registration)); + + // ありがとう画面へ行く + $url = NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_answers', + 'action' => 'thanks', + Current::read('Block.id'), + $this->_getRegistrationKey($this->__registration), + 'frame_id' => Current::read('Frame.id'), + )); + $this->redirect($url); + } + + // 回答情報取得 + // 回答情報並べ替え + $setAnswers = $this->RegistrationAnswer->getProgressiveAnswerOfThisSummary($summary); + + // 質問情報をView変数にセット + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + $this->set('registration', $this->__registration); + $this->request->data['RegistrationAnswer'] = $setAnswers; + $this->set('answers', $setAnswers); + } +/** + * thanks method + * + * @return void + */ + public function thanks() { + // 後始末 + // 回答中にたまっていたセッションキャッシュをクリア + $this->Session->delete('Registrations.' . $this->__registration['Registration']['key']); + + // View変数にセット + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + $this->set('registration', $this->__registration); + $this->set('ownAnsweredKeys', $this->RegistrationsOwnAnswer->getOwnAnsweredKeys()); + } +/** + * no_more_answer method + * 条件によって回答できない登録フォームにアクセスしたときに表示 + * + * @return void + */ + public function no_more_answer() { + } +/** + * _shuffleChoice + * shuffled choices and write into session + * + * @param array &$registration 登録フォーム + * @return void + */ + private function __shuffleChoice(&$registration) { + foreach ($registration['RegistrationPage'] as &$page) { + foreach ($page['RegistrationQuestion'] as &$q) { + $choices = $q['RegistrationChoice']; + if ($q['is_choice_random'] == RegistrationsComponent::USES_USE) { + $sessionPath = 'Registrations.' . $registration['Registration']['key'] . '.RegistrationQuestion.' . $q['key'] . '.RegistrationChoice'; + if ($this->Session->check($sessionPath)) { + $choices = $this->Session->read($sessionPath); + } else { + shuffle($choices); + $this->Session->write($sessionPath, $choices); + } + } + $q['RegistrationChoice'] = $choices; + } + } + } +} diff --git a/Controller/RegistrationBlockRolePermissionsController.php b/Controller/RegistrationBlockRolePermissionsController.php new file mode 100644 index 0000000..6ab7ec8 --- /dev/null +++ b/Controller/RegistrationBlockRolePermissionsController.php @@ -0,0 +1,104 @@ + + * @author Shohei Nakajima + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationBlocksController', 'Registrations.Controller'); + +/** + * RegistrationBlockRolePermissions Controller + * + * @author Shohei Nakajima + * @package NetCommons\Registrations\Controller + */ +class RegistrationBlockRolePermissionsController extends RegistrationBlocksController { + +/** + * layout + * + * @var array + */ + public $layout = 'NetCommons.setting'; + +/** + * use models + * + * @var array + */ + public $uses = array( + 'Registrations.RegistrationSetting', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'Blocks.BlockTabs' => array( + 'mainTabs' => array( + 'block_index' => array('url' => array('controller' => 'registration_blocks')), + 'role_permissions' => array('url' => array('controller' => 'registration_block_role_permissions')), + //'frame_settings' => array('url' => array('controller' => 'registration_frame_settings')), + ), + ), + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'edit' => 'block_permission_editable', + ), + ), + ); + +/** + * use helpers + * + * @var array + */ + public $helpers = array( + 'Blocks.BlockRolePermissionForm', + 'NetCommons.Date', + ); + +/** + * edit + * + * @return void + */ + public function edit() { + $registrationSetting = $this->RegistrationSetting->getSetting(); + if (! $registrationSetting) { + $this->setAction('throwBadRequest'); + return false; + } + $permissions = $this->Workflow->getBlockRolePermissions( + array('content_creatable', 'content_publishable', 'content_comment_creatable', 'content_comment_publishable') + ); + $this->set('roles', $permissions['Roles']); + if ($this->request->isPost()) { + if ($this->RegistrationSetting->saveRegistrationSetting($this->request->data)) { + $this->NetCommons->setFlashNotification(__d('net_commons', 'Successfully saved.'), array( + 'class' => 'success', + )); + $this->redirect(NetCommonsUrl::backToIndexUrl('default_setting_action')); + return; + } + $this->NetCommons->handleValidationError($this->RegistrationSetting->validationErrors); + $this->request->data['BlockRolePermission'] = Hash::merge( + $permissions['BlockRolePermissions'], + $this->request->data['BlockRolePermission'] + ); + return; + } + $this->request->data['RegistrationSetting'] = $registrationSetting['RegistrationSetting']; + $this->request->data['Block'] = $registrationSetting['Block']; + $this->request->data['BlockRolePermission'] = $permissions['BlockRolePermissions']; + $this->request->data['Frame'] = Current::read('Frame'); + } +} diff --git a/Controller/RegistrationBlocksController.php b/Controller/RegistrationBlocksController.php new file mode 100644 index 0000000..5ecc432 --- /dev/null +++ b/Controller/RegistrationBlocksController.php @@ -0,0 +1,253 @@ + + * @author Ryo Ozawa + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); +App::uses('TemporaryFolder', 'Files.Utility'); +App::uses('CsvFileWriter', 'Files.Utility'); +App::uses('ZipDownloader', 'Files.Utility'); + +/** + * BlocksController + * + * @author Ryo Ozawa + * @package NetCommons\Registrations\Controller + */ +class RegistrationBlocksController extends RegistrationsAppController { + +/** + * csv download item count handling unit + * + * @var int + */ + const REGISTRATION_CSV_UNIT_NUMBER = 1000; + +/** + * layout + * + * @var array + */ + public $layout = 'NetCommons.setting'; + +/** + * use models + * + * @var array + */ + public $uses = array( + 'Registrations.Registration', + 'Registrations.RegistrationFrameSetting', + 'Registrations.RegistrationAnswerSummary', + 'Registrations.RegistrationAnswerSummaryCsv', + 'Blocks.Block', + 'Registrations.RegistrationExport', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'Blocks.BlockTabs' => array( + 'mainTabs' => array( + 'block_index' => array('url' => array('controller' => 'registration_blocks')), + 'role_permissions' => array('url' => array('controller' => 'registration_block_role_permissions')), + //'frame_settings' => array('url' => array('controller' => 'registration_frame_settings')), + ), + ), + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'index,add,edit,delete' => 'block_editable', + ), + ), + 'Paginator', + ); + +/** + * use helpers + * + * @var array + */ + public $helpers = array( + 'Session', + 'Blocks.BlockForm', + 'NetCommons.NetCommonsForm', + 'NetCommons.Date', + ); + +/** + * beforeFilter + * + * @return void + */ + public function beforeFilter() { + parent::beforeFilter(); + $this->Auth->deny('index'); + } + +/** + * index + * + * @return void + */ + public function index() { + // 条件設定値取得 + // 条件設定値取得 + $conditions = $this->Registration->getBaseCondition(); + + // データ取得 + $this->paginate = array( + 'conditions' => $conditions, + 'page' => 1, + 'sort' => RegistrationsComponent::DISPLAY_SORT_TYPE_NEW_ARRIVALS, + 'limit' => RegistrationsComponent::REGISTRATION_DEFAULT_DISPLAY_NUM_PER_PAGE, + 'direction' => 'desc', + 'recursive' => 0, + ); + $registration = $this->paginate('Registration'); + if (! $registration) { + $this->view = 'not_found'; + return; + } + + $this->set('registrations', $registration); + } + +/** + * download + * + * @return void + * @throws InternalErrorException + */ + public function download() { + // NetCommonsお約束:コンテンツ操作のためのURLには対象のコンテンツキーが必ず含まれている + // まずは、そのキーを取り出す + // 登録フォームキー + $registrationKey = $this->_getRegistrationKeyFromPass(); + // キー情報をもとにデータを取り出す + $registration = $this->RegistrationAnswerSummaryCsv->getRegistrationForAnswerCsv($registrationKey); + if (! $registration) { + $this->setAction('throwBadRequest'); + return; + } + // 圧縮用パスワードキーを求める + if (! empty($this->request->data['AuthorizationKey']['authorization_key'])) { + $zipPassword = $this->request->data['AuthorizationKey']['authorization_key']; + } else { + $this->NetCommons->setFlashNotification(__d('registrations', 'Setting of password is required always to download answers.'), + array('interval' => NetCommonsComponent::ALERT_VALIDATE_ERROR_INTERVAL)); + $this->redirect(NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_blocks', + 'action' => 'index', + 'frame_id' => Current::read('Frame.id')))); + return; + } + + try { + $tmpFolder = new TemporaryFolder(); + $csvFile = new CsvFileWriter(array( + 'folder' => $tmpFolder->path + )); + // 回答データを一気に全部取得するのは、データ爆発の可能性があるので + // REGISTRATION_CSV_UNIT_NUMBER分に制限して取得する + $offset = 0; + do { + $datas = $this->RegistrationAnswerSummaryCsv->getAnswerSummaryCsv($registration, self::REGISTRATION_CSV_UNIT_NUMBER, $offset); + // CSV形式で書きこみ + foreach ($datas as $data) { + $csvFile->add($data); + } + $dataCount = count($datas); // データ数カウント + $offset += $dataCount; // 次の取得開始位置をずらす + } while ($dataCount == self::REGISTRATION_CSV_UNIT_NUMBER); + // データ取得数が制限値分だけとれている間は繰り返す + + } catch (Exception $e) { + // NetCommonsお約束:エラーメッセージのFlash表示 + $this->NetCommons->setFlashNotification(__d('registrations', 'download error'), + array('interval' => NetCommonsComponent::ALERT_VALIDATE_ERROR_INTERVAL)); + $this->redirect(NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_blocks', + 'action' => 'index', + 'frame_id' => Current::read('Frame.id')))); + return; + } + // Downloadの時はviewを使用しない + $this->autoRender = false; + // ダウンロードファイル名決定 登録フォーム名称をつける + $zipFileName = $registration['Registration']['title'] . '.zip'; + $downloadFileName = $registration['Registration']['title'] . '.csv'; + // 出力 + return $csvFile->zipDownload(rawurlencode($zipFileName), $downloadFileName, $zipPassword); + } + +/** + * export + * + * template file about registration export action + * + * @return void + */ + public function export() { + // NetCommonsお約束:コンテンツ操作のためのURLには対象のコンテンツキーが必ず含まれている + // まずは、そのキーを取り出す + // 登録フォームキー + $registrationKey = $this->_getRegistrationKeyFromPass(); + // キー情報をもとにデータを取り出す + $registration = $this->RegistrationAnswerSummaryCsv->getRegistrationForAnswerCsv($registrationKey); + if (! $registration) { + $this->setAction('throwBadRequest'); + return; + } + + try { + // zipファイル準備 + $zipFile = new ZipDownloader(); + + // Export用のデータ配列を取得する + $zipData = $this->RegistrationExport->getExportData($registrationKey); + + // Export用ファイルデータをZIPファイルに出力する + // ※この中でWYSISWYGエディタデータは適宜処理されている + $this->RegistrationExport->putToZip($zipFile, $zipData); + + // アーカイブ閉じる + $zipFile->close(); + } catch(Exception $e) { + $this->Session->setFlash(__d('registrations', 'export error') . $e->getMessage(), + array('interval' => NetCommonsComponent::ALERT_VALIDATE_ERROR_INTERVAL)); + $this->redirect(NetCommonsUrl::actionUrl(array( + 'controller' => 'registration_blocks', + 'action' => 'index', + 'frame_id' => Current::read('Frame.id')))); + return; + } + // 大外枠zipファイル準備 + $zipWrapperFile = new ZipDownloader(); + // 登録フォームデータファイルのフィンガープリントを得る + $fingerPrint = sha1_file($zipFile->path, false); + // フィンガープリントをアーカイブに加える + $zipWrapperFile->addFromString(RegistrationsComponent::REGISTRATION_FINGER_PRINT_FILENAME, $fingerPrint); + // 本体ファイルを + $zipWrapperFile->addFile($zipFile->path, RegistrationsComponent::REGISTRATION_TEMPLATE_FILENAME); + // export-key 設定 + $this->Registration->saveExportKey($registration['Registration']['id'], $fingerPrint); + + // viewを使用しない + $this->autoRender = false; + + // ダウンロード出力ファイル名確定 + $exportFileName = $registration['Registration']['title'] . '.zip'; + // 出力 + return $zipWrapperFile->download(rawurlencode($exportFileName)); + } +} \ No newline at end of file diff --git a/Controller/RegistrationEditController.php b/Controller/RegistrationEditController.php new file mode 100644 index 0000000..18eaf83 --- /dev/null +++ b/Controller/RegistrationEditController.php @@ -0,0 +1,345 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationEditController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationEditController extends RegistrationsAppController { + +/** + * edit registration session key + * + * @var int + */ + const REGISTRATION_EDIT_SESSION_INDEX = 'Registrations.registrationEdit.'; + +/** + * use model + * + * @var array + */ + public $uses = array( + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'edit,edit_question,edit_result,delete' => 'content_creatable', + ), + ), + 'Registrations.Registrations', + ); + +/** + * use helpers + * + */ + public $helpers = array( + 'Workflow.Workflow', + 'Registrations.QuestionEdit' + ); + +/** + * target registration  + * + */ + protected $_registration = null; + +/** + * session index + * + */ + protected $_sessionIndex = null; + +/** + * beforeFilter + * + * @return void + */ + public function beforeFilter() { + parent::beforeFilter(); + // NetCommonsお約束:編集画面へのURLに編集対象のコンテンツキーが含まれている + // まずは、そのキーを取り出す + // 登録フォームキー + $registrationKey = $this->_getRegistrationKeyFromPass(); + + // セッションインデックスパラメータ + $sessionName = self::REGISTRATION_EDIT_SESSION_INDEX . $this->_getRegistrationEditSessionIndex(); + + if ($this->request->isPost() || $this->request->isPut()) { + // ウィザード画面なのでセッションに記録された前画面データが必要 + $this->_registration = $this->Session->read($sessionName); + if (! $this->_registration) { + // セッションタイムアウトの場合 + return; + } + } else { + // redirectで来るか、もしくは本当に直接のURL指定で来るかのどちらか + // セッションに記録された値がある場合はそちらを優先 + if ($this->Session->check($sessionName)) { + $this->_registration = $this->Session->read($sessionName); + } elseif (! empty($registrationKey)) { + // 登録フォームキーの指定がある場合は過去データ編集と判断 + // 指定された登録フォームデータを取得 + // NetCommonsお約束:履歴を持つタイプのコンテンツデータはgetWorkflowContentsで取り出す + $this->_registration = $this->Registration->getWorkflowContents('first', array( + 'recursive' => 0, + 'conditions' => array( + $this->Registration->alias . '.key' => $registrationKey + ) + )); + // NetCommonsお約束:編集の場合には改めて編集権限をチェックする必要がある + // getWorkflowContentsはとりあえず自分が「見られる」コンテンツデータを取ってきてしまうので + if (! $this->Registration->canEditWorkflowContent($this->_registration)) { + $this->_registration = null; + } + } + } + } + +/** + * edit question method + * + * @throws BadRequestException + * @return void + */ + public function edit_question() { + // 処理対象の登録フォームデータが見つかっていない場合、エラー + if (empty($this->_registration)) { + $this->throwBadRequest(); + return false; + } + + // Postの場合 + if ($this->request->isPost()) { + + $postRegistration = $this->request->data; + + // 登録フォームデータに作成されたPost質問データをかぶせる + // (質問作成画面では質問データ属性全てをPOSTしているのですり替えでOK) + $registration = $this->_registration; + $registration['Registration'] = Hash::merge($this->_registration['Registration'], $postRegistration['Registration']); + + // 発行後の登録フォームは質問情報は書き換えない + // 未発行の場合はPostデータを上書き設定して + if ($this->Registration->hasPublished($registration) == 0) { + $registration['RegistrationPage'] = $postRegistration['RegistrationPage']; + } else { + // booleanの値がPOST時と同じようになるように調整 + $registration['RegistrationPage'] = RegistrationsAppController::changeBooleansToNumbers($registration['RegistrationPage']); + } + + // バリデート + $this->Registration->set($registration); + if (! $this->Registration->validates(array('validate' => 'duringSetup'))) { + $this->__setupViewParameters($registration, ''); + return; + } + + // バリデートがOKであればPOSTで出来上がったデータをセッションキャッシュに書く + $this->Session->write(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_sessionIndex, $registration); + + // 次の画面へリダイレクト + $this->redirect($this->_getActionUrl('edit_result')); + } else { + // 登録フォームデータが取り出せている場合、それをキャッシュに書く + $this->Session->write( + self::REGISTRATION_EDIT_SESSION_INDEX . $this->_getRegistrationEditSessionIndex(), + $this->_sorted($this->_registration)); + $this->__setupViewParameters($this->_registration, ''); + } + } + +/** + * edit_result + * + * @throws BadRequestException + * @return void + */ + public function edit_result() { + // 処理対象の登録フォームデータが見つかっていない場合、エラー + if (empty($this->_registration)) { + $this->throwBadRequest(); + return; + } + + if ($this->request->isPost()) { + + $postRegistration = $this->request->data; + + // 集計設定画面では集計に纏わる情報のみがPOSTされるので安心してマージ + $registration = Hash::merge($this->_registration, $postRegistration); + // バリデート + $this->Registration->set($registration); + if (! $this->Registration->validates(array('validate' => 'duringSetup'))) { + $this->__setupViewParameters($registration, $this->_getActionUrl('edit_question')); + return; + } + // それをキャッシュに書く + $this->Session->write(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_getRegistrationEditSessionIndex(), $registration); + + // 次の画面へリダイレクト + $this->redirect($this->_getActionUrl('edit')); + + } else { + $this->Session->write(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_getRegistrationEditSessionIndex(), $this->_registration); + $this->__setupViewParameters($this->_registration, $this->_getActionUrl('edit_question')); + } + } + +/** + * edit method + * + * @throws BadRequestException + * @return void + */ + public function edit() { + // 処理対象の登録フォームデータが見つかっていない場合、エラー + if (empty($this->_registration)) { + $this->throwBadRequest(); + return; + } + + if ($this->request->isPost() || $this->request->isPut()) { + $postRegistration = $this->request->data; + + $beforeStatus = $this->_registration['Registration']['status']; + + // 設定画面では登録フォーム本体に纏わる情報のみがPOSTされる + $registration = Hash::merge($this->_registration, $postRegistration); + + // 指示された編集状態ステータス + $registration['Registration']['status'] = $this->Workflow->parseStatus(); + + // それをDBに書く + $saveRegistration = $this->Registration->saveRegistration($registration); + // エラー + if ($saveRegistration == false) { + $registration['Registration']['status'] = $beforeStatus; + $this->__setupViewParameters($registration, $this->_getActionUrl('edit_result')); + return; + } + // 成功時 セッションに書き溜めた編集情報を削除 + $this->Session->delete(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_getRegistrationEditSessionIndex()); + // ページトップへリダイレクト + $this->redirect(NetCommonsUrl::backToPageUrl()); + + } else { + // 指定されて取り出した登録フォームデータをセッションキャッシュに書く + $this->Session->write($this->_getRegistrationEditSessionIndex(), $this->_registration); + $this->__setupViewParameters($this->_registration, $this->_getActionUrl('edit_result')); + } + } + +/** + * delete method + * + * @return void + */ + public function delete() { + if (! $this->request->isDelete()) { + $this->throwBadRequest(); + return; + } + + //削除権限チェック + if (! $this->Registration->canDeleteWorkflowContent($this->_registration)) { + $this->throwBadRequest(); + return; + } + + // 削除処理 + if (! $this->Registration->deleteRegistration($this->request->data)) { + $this->throwBadRequest(); + return; + } + + $this->Session->delete(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_sessionIndex); + + $this->redirect(NetCommonsUrl::backToPageUrl()); + } + +/** + * cancel method + * + * @return void + */ + public function cancel() { + $this->Session->delete(self::REGISTRATION_EDIT_SESSION_INDEX . $this->_sessionIndex); + $this->redirect(NetCommonsUrl::backToPageUrl()); + } +/** + * _getActionUrl method + * + * @param string $method 遷移先アクション名 + * @return void + */ + protected function _getActionUrl($method) { + return NetCommonsUrl::actionUrl(array( + 'controller' => Inflector::underscore($this->name), + 'action' => $method, + Current::read('Block.id'), + $this->_getRegistrationKey($this->_registration), + 'frame_id' => Current::read('Frame.id'), + 's_id' => $this->_getRegistrationEditSessionIndex() + )); + } +/** + * __setupViewParameters method + * + * @param array $registration 登録フォームデータ + * @param string $backUrl BACKボタン押下時の戻るパス + * @return void + */ + private function __setupViewParameters($registration, $backUrl) { + $isPublished = $this->Registration->hasPublished($registration); + + // エラーメッセージはページ、質問、選択肢要素のそれぞれの場所に割り当てる + $this->NetCommons->handleValidationError($this->Registration->validationErrors); + $flatError = Hash::flatten($this->Registration->validationErrors); + $newFlatError = array(); + foreach ($flatError as $key => $val) { + if (preg_match('/^(.*)\.(.*)\.(.*)$/', $key, $matches)) { + $newFlatError[$matches[1] . '.error_messages.' . $matches[2] . '.' . $matches[3]] = $val; + } + } + $registration = Hash::merge($registration, Hash::expand($newFlatError)); + + $this->set('backUrl', $backUrl); + $this->set('postUrl', array('url' => $this->_getActionUrl($this->action))); + $this->set('cancelUrl', $this->_getActionUrl('cancel')); + $this->set('questionTypeOptions', $this->Registrations->getQuestionTypeOptionsWithLabel()); + $this->set('newPageLabel', __d('registrations', 'page')); + $this->set('newQuestionLabel', __d('registrations', 'New Question')); + $this->set('newChoiceLabel', __d('registrations', 'new choice')); + $this->set('newChoiceColumnLabel', __d('registrations', 'new column choice')); + $this->set('newChoiceOtherLabel', __d('registrations', 'other choice')); + $this->set('isPublished', $isPublished); + $this->request->data = $registration; + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + + // ? FUJI いる? + //$this->set('contentStatus', $registration['Registration']['status']); + //$this->set('comments', $this->Registration->getCommentsByContentKey($registration['Registration']['key'])); + } +} diff --git a/Controller/RegistrationFrameSettingsController.php b/Controller/RegistrationFrameSettingsController.php new file mode 100644 index 0000000..7ab9572 --- /dev/null +++ b/Controller/RegistrationFrameSettingsController.php @@ -0,0 +1,135 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationBlocksController', 'Registrations.Controller'); + +/** + * RegistrationFrameSettingsController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationFrameSettingsController extends RegistrationBlocksController { + +/** + * layout + * + * @var array + */ + public $layout = 'NetCommons.setting'; + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Blocks.Block', + 'Frames.Frame', + 'Registrations.Registration', + 'Registrations.RegistrationFrameSetting', + 'Registrations.RegistrationFrameDisplayRegistration', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'Blocks.BlockTabs' => array( + 'mainTabs' => array( + 'block_index' => array('url' => array('controller' => 'registration_blocks')), + 'role_permissions' => array('url' => array('controller' => 'registration_block_role_permissions')), + //'frame_settings' => array('url' => array('controller' => 'registration_frame_settings')), + ), + ), + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'edit' => 'page_editable', + ), + ), + 'Registrations.Registrations', + 'Paginator', + ); + +/** + * use helpers + * + * @var array + */ + public $helpers = array( + 'NetCommons.Date', + 'Registrations.RegistrationUtil' + ); + +/** + * edit method + * + * @return void + */ + public function edit() { + // Postデータ登録 + if ($this->request->isPut() || $this->request->isPost()) { + if ($this->RegistrationFrameSetting->saveFrameSettings($this->request->data)) { + $this->NetCommons->setFlashNotification(__d('net_commons', 'Successfully saved.'), array( + 'class' => 'success', + )); + $this->redirect(NetCommonsUrl::backToPageUrl()); + return; + } + $this->NetCommons->handleValidationError($this->RegistrationFrameSetting->validationErrors); + } + + $conditions = array( + 'block_id' => Current::read('Block.id'), + 'is_latest' => true, + ); + $this->paginate = array( + 'fields' => array('Registration.*', 'RegistrationFrameDisplayRegistration.*'), + 'conditions' => $conditions, + 'page' => 1, + 'sort' => RegistrationsComponent::DISPLAY_SORT_TYPE_NEW_ARRIVALS, + 'limit' => 1000, + 'direction' => 'desc', + 'recursive' => -1, + 'joins' => array( + array( + 'table' => 'registration_frame_display_registrations', + 'alias' => 'RegistrationFrameDisplayRegistration', + 'type' => 'LEFT', + 'conditions' => array( + 'RegistrationFrameDisplayRegistration.registration_key = Registration.key', + 'RegistrationFrameDisplayRegistration.frame_key' => Current::read('Frame.key'), + ), + ) + ) + ); + $registrations = $this->paginate('Registration'); + + $frame = $this->RegistrationFrameSetting->find('first', array( + 'conditions' => array( + 'frame_key' => Current::read('Frame.key'), + ), + 'order' => 'RegistrationFrameSetting.id DESC' + )); + if (!$frame) { + $frame = $this->RegistrationFrameSetting->getDefaultFrameSetting(); + } + + $this->set('registrations', $registrations); + $this->set('registrationFrameSettings', $frame['RegistrationFrameSetting']); + $this->request->data['RegistrationFrameSetting'] = $frame['RegistrationFrameSetting']; + $this->request->data['Frame'] = Current::read('Frame'); + $this->request->data['Block'] = Current::read('Block'); + } +} \ No newline at end of file diff --git a/Controller/RegistrationsAppController.php b/Controller/RegistrationsAppController.php new file mode 100644 index 0000000..78850fc --- /dev/null +++ b/Controller/RegistrationsAppController.php @@ -0,0 +1,274 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationsAppController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationsAppController extends AppController { + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Registrations.Registration', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'Security', + 'Pages.PageLayout', + 'Registrations.Registrations', + 'Registrations.RegistrationsOwnAnswer', + ); + +/** + * _sorted method + * to sort a given array by key + * + * @param array $obj data array + * @return array ソート後配列 + */ + protected function _sorted($obj) { + // シーケンス順に並び替え、かつ、インデックス値は0オリジン連番に変更 + // ページ配列もないのでそのまま戻す + if (!Hash::check($obj, 'RegistrationPage.{n}')) { + return $obj; + } + $obj['RegistrationPage'] = Hash::sort($obj['RegistrationPage'], '{n}.page_sequence', 'asc', 'numeric'); + + foreach ($obj['RegistrationPage'] as &$page) { + if (!Hash::check($page, 'RegistrationQuestion.{n}')) { + $page['RegistrationQuestion'] = Hash::sort($page['RegistrationQuestion'], '{n}.question_sequence', 'asc', 'numeric'); + + foreach ($page['RegistrationQuestion'] as &$question) { + if (!Hash::check($question, 'RegistrationChoice.{n}')) { + $question['RegistrationChoice'] = Hash::sort($question['RegistrationChoice'], '{n}.choice_sequence', 'asc', 'numeric'); + } + } + } + } + return $obj; + } + +/** + * changeBooleansToNumbers method + * to change the Boolean value of a given array to 0,1 + * + * @param array $data data array + * @return array + */ + public static function changeBooleansToNumbers(Array $data) { + // Note the order of arguments and the & in front of $value + array_walk_recursive($data, 'self::converter'); + return $data; + } + +/** + * __converter method + * to change the Boolean value to 0,1 + * + * @param array &$value value + * @param string $key key + * @return void + * @SuppressWarnings("unused") + */ + public static function converter(&$value, $key) { + if (is_bool($value)) { + $value = ($value ? '1' : '0'); + } + } + +/** + * isAbleTo + * Whether access to survey of the specified ID + * Forced URL hack guard + * And against the authority of the state of the specified registration respondents put a guard + * It is not in the public state + * Out of period + * Stopped + * Repeatedly answer + * You are not logged in to not forgive other than member + * + * @param array $registration 対象となる登録フォームデータ + * @return bool + */ + public function isAbleTo($registration) { + // 指定の登録フォームの状態と回答者の権限を照らし合わせてガードをかける + // 編集権限を持っていない場合 + // 公開状態にない + // 期間外 + // 停止中 + // 繰り返し回答 + // 会員以外には許してないのに未ログインである + + // 編集権限を持っている場合 + // 公開状態にない場合はALL_OK + // + //  公開状態になっている場合は + // 期間外 + // 停止中 + // 繰り返し回答 + // 会員以外には許してないのに未ログインである + + // 公開状態が「公開」になっている場合は編集権限の有無にかかわらず共通だ + // なのでまずは公開状態だけを確認する + + // 編集権限があればオールマイティOKなのでこの後の各種チェックは不要! + if ($this->Registration->canEditWorkflowContent($registration)) { + return true; + } + // 編集権限がない場合は、もろもろのチェックを行うこと + + // 読み取り権限がない? + if (! $this->Registration->canReadWorkflowContent()) { + // それはだめだ + return false; + } + + // 基本、権限上、見ることができるコンテンツだ + // しかし、登録フォーム独自の条件部分のチェックを行う必要がある + // 期間外 + if ($registration['Registration']['public_type'] == WorkflowBehavior::PUBLIC_TYPE_LIMITED + && $registration['Registration']['period_range_stat'] != RegistrationsComponent::REGISTRATION_PERIOD_STAT_IN) { + return false; + } + + // 会員以外には許していないのに未ログイン + if ($registration['Registration']['is_no_member_allow'] == RegistrationsComponent::PERMISSION_NOT_PERMIT) { + if (! Current::read('User.id')) { + return false; + } + } + + return true; + } +/** + * isAbleToAnswer 指定されたIDに回答できるかどうか + * 強制URLハックのガード + * 指定の登録フォームの状態と回答者の権限を照らし合わせてガードをかける + * 公開状態にない + * 期間外 + * 停止中 + * 繰り返し回答 + * 会員以外には許してないのに未ログインである + * + * @param array $registration 対象となる登録フォームデータ + * @return bool + */ + public function isAbleToAnswer($registration) { + if ($registration['Registration']['status'] != WorkflowComponent::STATUS_PUBLISHED) { + return true; + } + // 繰り返し回答を許していないのにすでに回答済みか + if ($registration['Registration']['is_repeat_allow'] == RegistrationsComponent::PERMISSION_NOT_PERMIT) { + if ($this->RegistrationsOwnAnswer->checkOwnAnsweredKeys($registration['Registration']['key'])) { + return false; + } + } + + return true; + } +/** + * isAbleToDisplayAggregatedData 指定されたIDを集計表示していいいかどうか? + * + * @param int $registration Registration + * @return bool + */ + public function isAbleToDisplayAggregatedData($registration) { + // 集計表示許さているか + if ($registration['Registration']['is_total_show'] != RegistrationsComponent::EXPRESSION_SHOW) { + return false; + } + + // 編集権限がある場合は無条件に許可 + if ($this->Registration->canEditWorkflowContent($registration)) { + return true; + } + + // 集計表示に期間設定しているか + // 期間設定がある + if ($registration['Registration']['total_show_timing'] == RegistrationsComponent::USES_USE) { + $nowDatetime = (new NetCommonsTime())->getNowDatetime(); + // まだ公開期間ではない + if (strtotime($nowDatetime) < strtotime($registration['Registration']['total_show_start_period'])) { + return false; + } + } + + // していない または 公開期間内 + // 本人回答があるかどうがか表示有無の判断基準 + if (! $this->RegistrationsOwnAnswer->checkOwnAnsweredKeys($registration['Registration']['key'])) { + //本人による「回答」データなし + return false; // 見てはいけない + } + //本人による「回答」データあり + return true; // みてよし + } + +/** + * _getRegistrationKeyFromPass + * + * @return string + */ + protected function _getRegistrationKeyFromPass() { + if (isset($this->params['pass'][RegistrationsComponent::REGISTRATION_KEY_PASS_INDEX])) { + if (strpos($this->params['pass'][RegistrationsComponent::REGISTRATION_KEY_PASS_INDEX], 's_id:') === 0) { + return ''; + } + return $this->params['pass'][RegistrationsComponent::REGISTRATION_KEY_PASS_INDEX]; + } + return ''; + } + +/** + * _getRegistrationEditSessionIndex + * + * @return string + */ + protected function _getRegistrationEditSessionIndex() { + if (isset($this->_sessionIndex) && $this->_sessionIndex !== null) { + return $this->_sessionIndex; + } + if (isset($this->params['named']['s_id'])) { + $tm = $this->params['named']['s_id']; + } else { + $tm = Security::hash(microtime(true), 'md5'); + } + $this->_sessionIndex = $tm; + return $tm; + } + +/** + * _getRegistrationKey + * + * @param array $registration Registration data + * @return string + */ + protected function _getRegistrationKey($registration) { + if (isset($registration['Registration']['key'])) { + return $registration['Registration']['key']; + } else { + return ''; + } + } + +} diff --git a/Controller/RegistrationsController.php b/Controller/RegistrationsController.php new file mode 100644 index 0000000..d135cb5 --- /dev/null +++ b/Controller/RegistrationsController.php @@ -0,0 +1,156 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppController', 'Controller'); + +/** + * RegistrationsController + * + * @author Allcreator + * @package NetCommons\Registrations\Controller + */ +class RegistrationsController extends RegistrationsAppController { + +/** + * use model + * + * @var array + */ + public $uses = array( + 'Registrations.RegistrationFrameSetting', + 'Registrations.RegistrationFrameDisplayRegistration', + ); + +/** + * use components + * + * @var array + */ + public $components = array( + 'NetCommons.Permission' => array( + //アクセスの権限 + 'allow' => array( + 'edit,delete' => 'content_creatable', + ), + ), + 'Registrations.Registrations', + 'Registrations.RegistrationsOwnAnswer', + 'Paginator', + ); + +/** + * use helpers + * + * @var array + */ + public $helpers = array( + 'Workflow.Workflow', + 'NetCommons.Date', + 'NetCommons.DisplayNumber', + 'NetCommons.Button', + 'Registrations.RegistrationStatusLabel', + 'Registrations.RegistrationUtil' + ); + +/** + * beforeFilter + * + * @return void + */ + public function beforeFilter() { + parent::beforeFilter(); + } + +/** + * index method + * + * @return void + */ + public function index() { + // 表示方法設定値取得 + list(, $displayNum, $sort, $dir) = + $this->RegistrationFrameSetting->getRegistrationFrameSetting(Current::read('Frame.key')); + + // 条件設定値取得 + $conditions = $this->Registration->getCondition(); + + // データ取得 + $this->Paginator->settings = array_merge( + $this->Paginator->settings, + array( + 'conditions' => $conditions, + 'page' => 1, + 'sort' => $sort, + 'limit' => $displayNum, + 'direction' => $dir, + 'recursive' => 0, + ) + ); + if (!isset($this->params['named']['answer_status'])) { + $this->request->params['named']['answer_status'] = RegistrationsComponent::REGISTRATION_ANSWER_VIEW_ALL; + } + $registration = $this->paginate('Registration', $this->_getPaginateFilter()); + $this->set('registrations', $registration); + + $this->__setOwnAnsweredKeys(); + + if (count($registration) == 0) { + $this->view = 'Registrations/noRegistration'; + } + } + +/** + * _getPaginateFilter method + * + * @return array + */ + protected function _getPaginateFilter() { + $filter = array(); + + if ($this->request->params['named']['answer_status'] == RegistrationsComponent::REGISTRATION_ANSWER_TEST) { + $filter = array( + 'Registration.status !=' => WorkflowComponent::STATUS_PUBLISHED + ); + return $filter; + } + + $filterCondition = array('Registration.key' => $this->RegistrationsOwnAnswer->getOwnAnsweredKeys()); + if ($this->request->params['named']['answer_status'] == RegistrationsComponent::REGISTRATION_ANSWER_UNANSWERED) { + $filter = array( + 'NOT' => $filterCondition + ); + } elseif ($this->request->params['named']['answer_status'] == RegistrationsComponent::REGISTRATION_ANSWER_ANSWERED) { + $filter = array( + $filterCondition + ); + } + + return $filter; + } + +/** + * Set view value of answered registration keys + * + * @return void + */ + private function __setOwnAnsweredKeys() { + if ($this->request->params['named']['answer_status'] == RegistrationsComponent::REGISTRATION_ANSWER_UNANSWERED) { + $this->set('ownAnsweredKeys', array()); + + return; + } + + $this->set('ownAnsweredKeys', $this->RegistrationsOwnAnswer->getOwnAnsweredKeys()); + } + +} \ No newline at end of file diff --git a/Lib/empty b/Lib/empty new file mode 100644 index 0000000..e69de29 diff --git a/Locale/jpn/LC_MESSAGES/registrations.po b/Locale/jpn/LC_MESSAGES/registrations.po new file mode 100644 index 0000000..cd74bea --- /dev/null +++ b/Locale/jpn/LC_MESSAGES/registrations.po @@ -0,0 +1,935 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"PO-Revision-Date: 2015-12-22 17:20+0900\n" +"Last-Translator: NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"POT-Creation-Date: \n" +"Language: ja\n" +"X-Generator: Poedit 1.8.6\n" + +#: /Controller/RegistrationBlocksController.php:148 +msgid "Setting of password is required always to download answers." +msgstr "回答データをダウンロードする場合は必ず圧縮パスワードの設定が必要です。" + +#: /Controller/RegistrationBlocksController.php:178 +msgid "download error" +msgstr "ダウンロードエラー" + +#: /Controller/RegistrationBlocksController.php:228 +msgid "export error" +msgstr "エクスポートエラー" + +#: /Controller/RegistrationEditController.php:331 +msgid "page" +msgstr "ページ" + +#: /Controller/RegistrationEditController.php:332 +#: /Model/RegistrationQuestion.php:220 +msgid "New Question" +msgstr "新規質問" + +#: /Controller/RegistrationEditController.php:333 +#: /Model/RegistrationChoice.php:140 +msgid "new choice" +msgstr "新規選択肢" + +#: /Controller/RegistrationEditController.php:334 +msgid "new column choice" +msgstr "新規選択肢(列)" + +#: /Controller/RegistrationEditController.php:335 +msgid "other choice" +msgstr "その他" + +#: /Controller/Component/RegistrationsComponent.php:512;513;514;515;516 +msgid "item" +msgstr "件" + +#: /Controller/Component/RegistrationsComponent.php:527 +msgid "New Modified" +msgstr "新着順" + +#: /Controller/Component/RegistrationsComponent.php:528 +msgid "Registration order" +msgstr "登録順" + +#: /Controller/Component/RegistrationsComponent.php:529 +#: /Model/ActionRegistrationAdd.php:60 /Model/Registration.php:98 +#: /View/Elements/FrameSettings/edit_display_registration.ctp:34 +#: /View/RegistrationBlocks/index.ctp:37 /View/RegistrationEdit/edit.ctp:46 +msgid "Title" +msgstr "タイトル" + +#: /Controller/Component/RegistrationsComponent.php:530 +msgid "End period" +msgstr "期限順" + +#: /Controller/Component/RegistrationsComponent.php:541 +msgid "Single choice" +msgstr "択一選択" + +#: /Controller/Component/RegistrationsComponent.php:542 +msgid "Multiple choice" +msgstr "複数選択" + +#: /Controller/Component/RegistrationsComponent.php:543 +msgid "Single text" +msgstr "1行テキスト" + +#: /Controller/Component/RegistrationsComponent.php:544 +msgid "Multiple text" +msgstr "複数行テキスト" + +#: /Controller/Component/RegistrationsComponent.php:545 +msgid "Single choice matrix" +msgstr "択一選択マトリクス" + +#: /Controller/Component/RegistrationsComponent.php:546 +msgid "Multiple choice matrix" +msgstr "複数選択マトリクス" + +#: /Controller/Component/RegistrationsComponent.php:547 +msgid "Date and time" +msgstr "日付と時間" + +#: /Controller/Component/RegistrationsComponent.php:548 +msgid "List select" +msgstr "リスト選択" + +#: /Model/ActionRegistrationAdd.php:54 +msgid "Please choose create option." +msgstr "作成方法を選択してください。" + +#: /Model/ActionRegistrationAdd.php:66;70 +msgid "Please select past registration." +msgstr "過去の登録フォームを選んでください。" + +#: /Model/ActionRegistrationAdd.php:254 +msgid "file upload error." +msgstr "ファイルアップロードエラー" + +#: /Model/ActionRegistrationAdd.php:263;270;277 +msgid "illegal import file." +msgstr "不正なインポートファイルです。" + +#: /Model/ActionRegistrationAdd.php:290 +msgid "version is different." +msgstr "エクスポートした登録フォームと現在お使いの登録フォームではバージョンが異なります。" + +#: /Model/Registration.php:110;136 +msgid "if you set the period, please set time." +msgstr "期間を設定する場合は、日時を設定してください。" + +#: /Model/Registration.php:116;122;142 +msgid "Invalid datetime format." +msgstr "入力された期間が不正です。正しい日付を入力してください。" + +#: /Model/Registration.php:126 +msgid "start period must be smaller than end period" +msgstr "開始日時は終了日時より前の日時を指定する必要があります。" + +#: /Model/Registration.php:164 +msgid "if you set the use key phrase period, please set key phrase text." +msgstr "認証キーを使う場合、キーフレーズを設定してください" + +#: /Model/Registration.php:168;184 +msgid "Authentication key setting , image authentication , either only one can not be selected." +msgstr "認証キーと画像認証を同時に使うことはできません。どちらか一つにしてください。" + +#: /Model/Registration.php:199 +msgid "please set at least one page." +msgstr "少なくとも1ページは作成してください。" + +#: /Model/RegistrationAnswer.php:118 +msgid "Input required" +msgstr "必須項目です。" + +#: /Model/RegistrationAnswer.php:122 +msgid "the answer is too long. Please enter under %d letters." +msgstr "回答が長すぎます。%d文字以下にしてください。" + +#: /Model/RegistrationAnswerSummaryCsv.php:152 +msgid "Respondent" +msgstr "回答者" + +#: /Model/RegistrationAnswerSummaryCsv.php:153 +msgid "Answer Date" +msgstr "回答日" + +#: /Model/RegistrationAnswerSummaryCsv.php:154 +msgid "Number" +msgstr "回答回数" + +#: /Model/RegistrationAnswerSummaryCsv.php:191 +msgid "Anonymity" +msgstr "匿名" + +#: /Model/RegistrationChoice.php:80 +msgid "Please input choice text." +msgstr "選択肢内容を入力してください。" + +#: /Model/RegistrationChoice.php:84 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:71 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:89 +msgid "You can not use the character of |, : for choice text " +msgstr "選択肢に「|」、「:」を使ってはいけません" + +#: /Model/RegistrationChoice.php:103 +msgid "choice sequence is illegal." +msgstr "選択肢の順番が不正です。最初からやり直してください。" + +#: /Model/RegistrationChoice.php:108 +msgid "First character is \"#\". And input the hexadecimal numbers by six digits." +msgstr "最初の1文字目は\"#\"です。続けて16進数6桁で指定してください。" + +#: /Model/RegistrationChoice.php:196 +msgid "Invalid skip page. Please set forward page." +msgstr "スキップページの指定が不正です。質問があるページよりも先のページを設定してください。" + +#: /Model/RegistrationChoice.php:200 +msgid "Invalid skip page. page does not exist." +msgstr "スキップページが不正です。指定されたページが存在しません。" + +#: /Model/RegistrationPage.php:85 +msgid "First Page" +msgstr "1ページ" + +#: /Model/RegistrationPage.php:198 +msgid "page sequence is illegal." +msgstr "ページの順番が不正です。最初からやり直してください。" + +#: /Model/RegistrationPage.php:230 +msgid "please set at least one question." +msgstr "1ページ中に少なくとも1つは質問を作成してください。" + +#: /Model/RegistrationQuestion.php:97 +msgid "question sequence is illegal." +msgstr "質問の順番が不正です。最初からやり直してください。" + +#: /Model/RegistrationQuestion.php:109 +msgid "Please input question text." +msgstr "質問文を入力してください。" + +#: /Model/RegistrationQuestion.php:155;165 +msgid "Please enter both the maximum and minimum values." +msgstr "上限値と下限値の両方を入力してください。" + +#: /Model/RegistrationQuestion.php:159 +msgid "Please enter smaller value than max." +msgstr "最大値よりも小さな値を入力してください。" + +#: /Model/RegistrationQuestion.php:169 +msgid "Please enter bigger value than min." +msgstr "最小値よりも大きな値を入力してください。" + +#: /Model/RegistrationQuestion.php:318 +msgid "please set at least one choice." +msgstr "少なくとも1つは選択肢を作成してください。" + +#: /Model/RegistrationQuestion.php:329 +msgid "please set at least one choice at row and column." +msgstr "行と列には、それぞれ1つ以上の選択肢が必要です。" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:75 +msgid "Please enter a valid date in YY-MM-DD format." +msgstr "日付を正しいフォーマット YY-MM-DD で入力してください。" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:80 +msgid "Please enter the time." +msgstr "時間を入力してください。" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:85 +msgid "Please enter a valid date and time." +msgstr "正しい日付と時間を設定してください。" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:104 +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:69 +msgid "Please enter the answer between %s and %s." +msgstr "回答は%sから%sの範囲で入力してください。" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:113;119 +#: /Model/Behavior/RegistrationAnswerSingleListBehavior.php:90 +msgid "Invalid choice" +msgstr "不正な選択です" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:143 +msgid "Please enter something in other item" +msgstr "その他の内容を入力してください。" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:181 +msgid "Please answer about all rows." +msgstr "回答するときは全ての行に対して回答をしてください。" + +#: /Model/Behavior/RegistrationAnswerSingleListBehavior.php:98 +msgid "Please enter something, if you chose the other item" +msgstr "その他を選択する場合は、内容を入力してください。" + +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:64 +msgid "Number required" +msgstr "数字を入力してください。" + +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:76 +msgid "Please enter the answer between %s letters and %s letters." +msgstr "回答は%s文字から%s文字の範囲で入力してください。" + +#: /View/Elements/ng_status_label.ctp:18 +#: /View/Helper/RegistrationStatusLabelHelper.php:49 +msgid "Before public" +msgstr "公開前" + +#: /View/Elements/ng_status_label.ctp:19 +#: /View/Helper/RegistrationStatusLabelHelper.php:53 +msgid "End" +msgstr "終了" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:15 +msgid "Note: Which may not be 100% because of rounding of numeric total." +msgstr "注: 四捨五入しているため、合計は必ずしも100%にはなりません。" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:20 +msgid "Note: Matrix if the number in parentheses is a percentage of the total number of responses." +msgstr "注: 表中の割合は、全回答数に占める割合です。" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:26 +msgid "Note: If multiple selection is possible, total more than 100% to be." +msgstr ": 複数選択式の場合、合計が100%を超える場合があります。" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:21 +msgid "The total number of answers: " +msgstr "全回答数:" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:29 +msgid "Select one" +msgstr "択一選択" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:32 +msgid "Select more than one" +msgstr "複数選択" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:35 +msgid "Matrix (selection list)" +msgstr "マトリクス(択一選択)" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:38 +msgid "Matrix (multiple)" +msgstr "マトリクス(複数選択)" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:41 +msgid "List selection" +msgstr "リスト選択" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:44 +msgid "Not selection" +msgstr "未選択" + +#: /View/Elements/AnswerSummaries/aggregate_matrix_table.ctp:18 +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:17 +msgid "Item name" +msgstr "アイテム名" + +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:18 +msgid "Aggregate value" +msgstr "回答数" + +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:19 +msgid "The percentage" +msgstr "割合" + +#: /View/Elements/Answers/answer_test_mode_header.ctp:31 +msgid "Test Mode" +msgstr "一時保存(テストモード)" + +#: /View/Elements/Answers/answer_test_mode_header.ctp:34 +msgid "This registration is being temporarily stored . You can registration test before performed in this page . If you want to modify or change the registration , you will be able to edit by pressing the [ Edit question ] button in the upper-right corner ." +msgstr "この登録フォームは一時保存中です。このページで実施前の登録フォームテストをすることができます。
登録フォームを修正・変更したい場合は、上部にある編集ボタンを押すと編集することができます。" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:12 +msgid "select display registrations." +msgstr "表示したい登録フォーム" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:18 +msgid "Display" +msgstr "表示" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:31 +#: /View/RegistrationBlocks/index.ctp:34 +msgid "Status" +msgstr "状態" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:37 +msgid "Implementation date" +msgstr "実施期間" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:40 +msgid "Aggregates" +msgstr "集計結果" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:84 +#: /View/Elements/RegistrationAdd/create_reuse.ctp:50 +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:69 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:88 +#: /View/RegistrationAnswers/test_mode.ctp:28;41 +#: /View/RegistrationEdit/edit.ctp:81 /View/Registrations/index.ctp:36 +msgid " - " +msgstr "~" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:90 +msgid "On" +msgstr "表示" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:12 +msgid "Registration display setting" +msgstr "登録フォーム表示設定" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:17 +msgid "Show only one registration" +msgstr "登録フォームを単独で表示" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:18 +msgid "Show registrations list" +msgstr "登録フォームを一覧表示" + +#: /View/Elements/FrameSettings/edit_list_display_option.ctp:15 +msgid "Visible registration row" +msgstr "1ページあたりの表示件数" + +#: /View/Elements/FrameSettings/edit_list_display_option.ctp:26 +msgid "Visible row order" +msgstr "表示順" + +#: /View/Elements/RegistrationAdd/create_new.ctp:14 +msgid "Create new registration" +msgstr "新規に登録フォーム作成" + +#: /View/Elements/RegistrationAdd/create_new.ctp:21 +msgid "Registration title" +msgstr "登録フォームタイトル" + +#: /View/Elements/RegistrationAdd/create_new.ctp:23 +msgid "Please input registration title" +msgstr "登録フォームタイトルを入力して下さい" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:14 +msgid "Re-use past registration" +msgstr "過去の登録フォームを流用して作成" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:25 +msgid "Past registration" +msgstr "過去の登録フォーム" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:34 +msgid "Refine by entering the part of the registration name" +msgstr "ここに登録フォーム名の一部を入力すると、下のリストの内容を絞り込むことができます" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:52 +msgid "Implementation" +msgstr "実施" + +#: /View/Elements/RegistrationAdd/create_template.ctp:13 +msgid "Create from Template" +msgstr "テンプレートを読み込んで作成" + +#: /View/Elements/RegistrationAdd/create_template.ctp:23 +msgid "Registration template file" +msgstr "登録フォームテンプレートファイル" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:14 +msgid "Set questions" +msgstr "質問の作成" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:15 +msgid "Set result display" +msgstr "集計結果表示の設定" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:16 +msgid "Set registration" +msgstr "登録フォームの設定" + +#: /View/Elements/RegistrationEdit/registration_title.ctp:14 +msgid "If you want to change the registration title, please edit in \"Set registration\" step." +msgstr "タイトルを変更したい場合は、「登録フォームの設定」にて再編集できます。" + +#: /View/Elements/RegistrationEdit/Edit/delete_form.ctp:31 +msgid "Registration" +msgstr "登録フォーム" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:16 +msgid "copy to another page" +msgstr "質問をコピー" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:20 +msgid "destination page number" +msgstr "コピー先ページ番号" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:28 +msgid "Do you want to delete this question ?" +msgstr "この質問を削除してもよろしいですか?" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:58 +msgid "Skip" +msgstr "スキップ" + +#: /View/Elements/RegistrationEdit/EditQuestion/add_question_button.ctp:18 +msgid "Add Question" +msgstr "質問の追加" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/choice.ctp:14 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/choice.ctp:18 +msgid "(This is [other] choice. Area to enter the text is automatically granted at the time of implementation.)" +msgstr "(「その他」の選択肢です。)" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:21 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:30 +msgid "Date" +msgstr "日付" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:22 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:31 +msgid "Time" +msgstr "時間" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:23 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:32 +msgid "Date and Time" +msgstr "日付と時間" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:49 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:59 +msgid "set range to answer date and time" +msgstr "期間を設定する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/matrix_choice_option.ctp:16 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:24 +msgid "Line choices" +msgstr "行の選択肢" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/matrix_choice_option.ctp:27 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:52 +msgid "Column choices" +msgstr "列の選択肢" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/simple_choice_option.ctp:26 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:30 +msgid "randomaize choices" +msgstr "選択肢をランダムに表示する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/simple_choice_option.ctp:37 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:41 +msgid "set page skip" +msgstr "スキップロジックを設定する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:24 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:32 +msgid "Numeric" +msgstr "回答を数値で求める" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:37 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:44 +msgid "Please check if you want to set limit(or length) value." +msgstr "範囲(文字数)を指定する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:42 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:57 +msgid "Minimum" +msgstr "最小値" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:50 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:73 +msgid "Maximum" +msgstr "最大値" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:28;47 +msgid "Add line choices" +msgstr "行の選択肢を追加する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:55;78 +msgid "Add column choices" +msgstr "列の選択肢" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:62 +msgid "Do you want to delete this choice ?" +msgstr "この選択肢を削除してもよろしいですか?" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:91 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:103 +msgid "add another choice" +msgstr "その他の選択肢を追加する" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:20;98 +msgid "add choices" +msgstr "選択肢の追加" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:64 +msgid "goto end" +msgstr "終了へ" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:68 +msgid "(new page will be created)" +msgstr "(新しいページはすでに作成されています)" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:69 +msgid "create new page for this skip" +msgstr "このスキップのためのページを作成する" + +#: /View/Elements/RegistrationEdit/EditResult/accordion_heading.ctp:23 +msgid "There is an error" +msgstr "エラーがあります" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:13 +msgid "display type" +msgstr "表示形式" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:28 +msgid "Bar Chart" +msgstr "棒グラフ" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:36 +msgid "Pie Chart" +msgstr "円グラフ" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:44 +msgid "Table" +msgstr "表" + +#: /View/Elements/RegistrationEdit/EditResult/graph_color_set.ctp:13 +msgid "graph color" +msgstr "グラフ色設定" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:14 +msgid "aggregate display" +msgstr "集計結果の表示" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:29 +msgid "The results of this question will not be displayed" +msgstr "集計結果を表示しない" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:38 +msgid "The results of this question will be displayed" +msgstr "集計結果を表示する" + +#: /View/Elements/Registrations/add_button.ctp:23 +msgid "Create article" +msgstr "新規に登録フォームを作成する" + +#: /View/Elements/Registrations/answer_status.ctp:13 +msgid "View All" +msgstr "全て表示" + +#: /View/Elements/Registrations/answer_status.ctp:14 +msgid "Unanswered" +msgstr "未回答" + +#: /View/Elements/Registrations/answer_status.ctp:15 +msgid "Answered" +msgstr "回答済み" + +#: /View/Elements/Registrations/answer_status.ctp:18 +#: /View/Helper/RegistrationUtilHelper.php:90 +msgid "Test" +msgstr "テスト" + +#: /View/Elements/Registrations/answer_status.ctp:30 +msgid "Answer status" +msgstr "回答状態" + +#: /View/Elements/Registrations/detail_for_editor.ctp:24 +msgid "Author" +msgstr "作成者" + +#: /View/Elements/Registrations/detail_for_editor.ctp:26 +msgid "Modified by" +msgstr "修正者" + +#: /View/Elements/Registrations/detail_for_editor.ctp:32 +msgid "Pages" +msgstr "ページ数" + +#: /View/Elements/Registrations/detail_for_editor.ctp:34 +msgid "Questions" +msgstr "質問数" + +#: /View/Elements/Registrations/detail_for_editor.ctp:36 +msgid "Answers" +msgstr "回答数" + +#: /View/Helper/RegistrationAnswerHelper.php:181 +msgid "Please enter a number between %s and %s" +msgstr "%s から %s の間の数値を入力してください" + +#: /View/Helper/RegistrationAnswerHelper.php:183 +msgid "Please enter between %s letters and %s letters" +msgstr "%s文字から%s文字の入力をしてください" + +#: /View/Helper/RegistrationAnswerHelper.php:235 +msgid "Please choose one" +msgstr "一つ選択してください" + +#: /View/Helper/RegistrationAnswerHelper.php:314;323;331 +msgid "Please enter at %s to %s" +msgstr "%s から %sまでの間で入力してください" + +#: /View/Helper/RegistrationStatusLabelHelper.php:31 +msgid "Undefined" +msgstr "未設定" + +#: /View/Helper/RegistrationUtilHelper.php:110 +msgid "Answer" +msgstr "回答" + +#: /View/Helper/RegistrationUtilHelper.php:127 +msgid "Unpublished" +msgstr "未公開" + +#: /View/Helper/RegistrationUtilHelper.php:131 +msgid "Finished" +msgstr "回答済" + +#: /View/RegistrationAdd/add.ctp:27 +msgid "You can create a new registration. Please choose how to create." +msgstr "新しい登録フォームを作成します。作成方法を選んでください。" + +#: /View/RegistrationAnswerSummaries/view.ctp:86 +#: /View/RegistrationAnswers/no_more_answer.ctp:14 +msgid "Back to Top" +msgstr "Topに戻る" + +#: /View/RegistrationAnswers/confirm.ctp:22 +msgid "Please confirm your answers." +msgstr "回答内容を確認してください。" + +#: /View/RegistrationAnswers/confirm.ctp:64 +msgid "Start over" +msgstr "最初からやり直す" + +#: /View/RegistrationAnswers/no_more_answer.ctp:12 +msgid "you will not be able to answer this registration." +msgstr "この登録フォームには回答することはできません。" + +#: /View/RegistrationAnswers/test_mode.ctp:25 +#: /View/RegistrationEdit/edit.ctp:58 +msgid "Registration answer period" +msgstr "登録フォーム回答期間" + +#: /View/RegistrationAnswers/test_mode.ctp:31 +msgid "do not set the answer period" +msgstr "回答期間を制限しない" + +#: /View/RegistrationAnswers/test_mode.ctp:38 +#: /View/RegistrationEdit/edit.ctp:92 +msgid "Counting result display start date" +msgstr "集計結果公開期間" + +#: /View/RegistrationAnswers/test_mode.ctp:43 +msgid "do not set the aggregate display period" +msgstr "公開期間を制限しない" + +#: /View/RegistrationAnswers/test_mode.ctp:50 +#: /View/RegistrationEdit/edit.ctp:113 +msgid "Registration method" +msgstr "登録フォーム方式" + +#: /View/RegistrationAnswers/test_mode.ctp:54 +#: /View/RegistrationEdit/edit.ctp:117 +msgid "accept the non-members answer" +msgstr "非会員の回答を受け付ける" + +#: /View/RegistrationAnswers/test_mode.ctp:56 +msgid "do not accept the non-members answer" +msgstr "非会員の回答を受け付けない" + +#: /View/RegistrationAnswers/test_mode.ctp:62 +#: /View/RegistrationEdit/edit.ctp:120 +msgid "use key phrase" +msgstr "認証キーを使う" + +#: /View/RegistrationAnswers/test_mode.ctp:64 +msgid "key phrase" +msgstr "認証キー" + +#: /View/RegistrationAnswers/test_mode.ctp:68 +msgid "do not use key phrase" +msgstr "認証キーは使わない" + +#: /View/RegistrationAnswers/test_mode.ctp:74 +#: /View/RegistrationEdit/edit.ctp:129 +msgid "anonymous answer" +msgstr "匿名の回答とする" + +#: /View/RegistrationAnswers/test_mode.ctp:76 +msgid "register answer" +msgstr "記名式回答とする" + +#: /View/RegistrationAnswers/test_mode.ctp:82 +#: /View/RegistrationEdit/edit.ctp:132 +msgid "forgive the repetition of the answer" +msgstr "繰り返しの回答をさせる" + +#: /View/RegistrationAnswers/test_mode.ctp:84 +msgid "do not forgive the repetition of the answer" +msgstr "繰り返し回答は許さない" + +#: /View/RegistrationAnswers/test_mode.ctp:90 +#: /View/RegistrationEdit/edit.ctp:135 +msgid "do image authentication" +msgstr "画像認証を行う" + +#: /View/RegistrationAnswers/test_mode.ctp:92 +msgid "do not image authentication" +msgstr "画像認証は行わない" + +#: /View/RegistrationAnswers/test_mode.ctp:98 +#: /View/RegistrationEdit/edit.ctp:140 +msgid "Deliver e-mail when submitted" +msgstr "提出されたらメールで通知する" + +#: /View/RegistrationAnswers/test_mode.ctp:100 +msgid "do not deliver e-mail when submitted" +msgstr "回答時のメール通知は行わない" + +#: /View/RegistrationAnswers/test_mode.ctp:106 +msgid "Deliver e-mail when started" +msgstr "登録フォームが開始されたらメールで通知する" + +#: /View/RegistrationAnswers/test_mode.ctp:108 +msgid "do not deliver e-mail when started" +msgstr "登録フォームの開始時のメール通知は行わない" + +#: /View/RegistrationAnswers/test_mode.ctp:117 +msgid "Start the test answers of this registration" +msgstr "この登録フォームのテスト回答を始める" + +#: /View/RegistrationAnswers/thanks.ctp:32 +msgid "Back to page" +msgstr "登録フォーム一覧に戻る" + +#: /View/RegistrationAnswers/thanks.ctp:37 +msgid "Aggregate" +msgstr "集計結果を表示する" + +#: /View/RegistrationBlockRolePermissions/noRegistrationBlock.ctp:19 +msgid "There is no registration. First, please create a registration." +msgstr "登録フォームがまだありません。初めに登録フォームを作成してください。" + +#: /View/RegistrationBlocks/index.ctp:43 +msgid "Answer CSV" +msgstr "回答CSV" + +#: /View/RegistrationBlocks/index.ctp:46 +msgid "Templates" +msgstr "テンプレート" + +#: /View/RegistrationEdit/edit.ctp:51 +msgid "Sub Title" +msgstr "サブタイトル" + +#: /View/RegistrationEdit/edit.ctp:53 +msgid "Please enter if there is a sub title" +msgstr "サブタイトルを入力してください" + +#: /View/RegistrationEdit/edit.ctp:63 +msgid "set the answer period" +msgstr "回答期間を設定する" + +#: /View/RegistrationEdit/edit.ctp:71 +msgid "After approval will be immediately published . Stop of the registration to select the stop from the registration data list ." +msgstr "承認後即時公開されます。登録フォームの停止は登録フォームデータ一覧から停止を選びます。" + +#: /View/RegistrationEdit/edit.ctp:97 +msgid "set the aggregate display period" +msgstr "公開期間を設定する" + +#: /View/RegistrationEdit/edit.ctp:99 +msgid "If not set , it will be displayed after the respondent answers." +msgstr "設定しない場合、回答者が回答した後すぐに表示されます。" + +#: /View/RegistrationEdit/edit.ctp:108 +msgid "Result will display at this time." +msgstr "から集計結果を表示する" + +#: /View/RegistrationEdit/edit.ctp:144 +msgid "Registration open mail" +msgstr "登録フォーム開始メール" + +#: /View/RegistrationEdit/edit.ctp:148 +msgid "Deliver e-mail when registration has opened" +msgstr "登録フォームが開始されたらメールで通知する" + +#: /View/RegistrationEdit/edit.ctp:153 +msgid "open mail subject" +msgstr "開始メールタイトル" + +#: /View/RegistrationEdit/edit.ctp:156 +msgid "open mail text" +msgstr "開始メール本文" + +#: /View/RegistrationEdit/edit.ctp:162 +msgid "Thanks page message settings" +msgstr "サンクスページメッセージ設定" + +#: /View/RegistrationEdit/edit_question.ctp:88 +msgid "Required" +msgstr "必須" + +#: /View/RegistrationEdit/edit_question.ctp:95 +msgid "set answer to this question is required" +msgstr "この質問の回答を必須とする" + +#: /View/RegistrationEdit/edit_question.ctp:98 +msgid "question title" +msgstr "質問タイトル" + +#: /View/RegistrationEdit/edit_question.ctp:106 +msgid "question sentence" +msgstr "質問文" + +#: /View/RegistrationEdit/edit_question.ctp:116 +msgid "Question type" +msgstr "質問の形式" + +#: /View/RegistrationEdit/edit_question.ctp:165 +msgid "Do you want to delete this page?" +msgstr "このページを削除してよろしいですか?" + +#: /View/RegistrationEdit/edit_question.ctp:166 +msgid "Delete this page" +msgstr "このページを削除" + +#: /View/RegistrationEdit/edit_question.ctp:174 +msgid "Add Page" +msgstr "ページの追加" + +#: /View/RegistrationEdit/edit_result.ctp:48 +msgid "Published aggregate results" +msgstr "集計結果の公開" + +#: /View/RegistrationEdit/edit_result.ctp:51 +msgid "not disclose the total result" +msgstr "集計結果を公開しない" + +#: /View/RegistrationEdit/edit_result.ctp:51 +msgid "publish aggregate result" +msgstr "集計結果を公開する" + +#: /View/RegistrationEdit/edit_result.ctp:65 +msgid "Text to be displayed in the aggregate results page" +msgstr "解説文の設定" + +#: /View/RegistrationEdit/edit_result.ctp:78 +msgid "Question you want to display the aggregate results" +msgstr "集計結果を表示する質問" + +#: /View/Registrations/noRegistration.ctp:28 +msgid "no registration" +msgstr "登録フォームがありません。" + +#: /View/Registrations/noRegistration.ctp:33 +msgid "Please create new registration by pressing the \"+\" button." +msgstr "+ボタンをクリックして登録フォームを作成してください。" diff --git a/Locale/registrations.pot b/Locale/registrations.pot new file mode 100644 index 0000000..531bca1 --- /dev/null +++ b/Locale/registrations.pot @@ -0,0 +1,937 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" +"Last-Translator: NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: /Controller/RegistrationBlocksController.php:148 +msgid "Setting of password is required always to download answers." +msgstr "" + +#: /Controller/RegistrationBlocksController.php:178 +msgid "download error" +msgstr "" + +#: /Controller/RegistrationBlocksController.php:228 +msgid "export error" +msgstr "" + +#: /Controller/RegistrationEditController.php:331 +msgid "page" +msgstr "" + +#: /Controller/RegistrationEditController.php:332 +#: /Model/RegistrationQuestion.php:220 +msgid "New Question" +msgstr "" + +#: /Controller/RegistrationEditController.php:333 +#: /Model/RegistrationChoice.php:140 +msgid "new choice" +msgstr "" + +#: /Controller/RegistrationEditController.php:334 +msgid "new column choice" +msgstr "" + +#: /Controller/RegistrationEditController.php:335 +msgid "other choice" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:512;513;514;515;516 +msgid "item" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:527 +msgid "New Modified" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:528 +msgid "Registration order" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:529 +#: /Model/ActionRegistrationAdd.php:60 +#: /Model/Registration.php:98 +#: /View/Elements/FrameSettings/edit_display_registration.ctp:34 +#: /View/RegistrationBlocks/index.ctp:37 +#: /View/RegistrationEdit/edit.ctp:46 +msgid "Title" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:530 +msgid "End period" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:541 +msgid "Single choice" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:542 +msgid "Multiple choice" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:543 +msgid "Single text" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:544 +msgid "Multiple text" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:545 +msgid "Single choice matrix" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:546 +msgid "Multiple choice matrix" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:547 +msgid "Date and time" +msgstr "" + +#: /Controller/Component/RegistrationsComponent.php:548 +msgid "List select" +msgstr "" + +#: /Model/ActionRegistrationAdd.php:54 +msgid "Please choose create option." +msgstr "" + +#: /Model/ActionRegistrationAdd.php:66;70 +msgid "Please select past registration." +msgstr "" + +#: /Model/ActionRegistrationAdd.php:254 +msgid "file upload error." +msgstr "" + +#: /Model/ActionRegistrationAdd.php:263;270;277 +msgid "illegal import file." +msgstr "" + +#: /Model/ActionRegistrationAdd.php:290 +msgid "version is different." +msgstr "" + +#: /Model/Registration.php:110;136 +msgid "if you set the period, please set time." +msgstr "" + +#: /Model/Registration.php:116;122;142 +msgid "Invalid datetime format." +msgstr "" + +#: /Model/Registration.php:126 +msgid "start period must be smaller than end period" +msgstr "" + +#: /Model/Registration.php:164 +msgid "if you set the use key phrase period, please set key phrase text." +msgstr "" + +#: /Model/Registration.php:168;184 +msgid "Authentication key setting , image authentication , either only one can not be selected." +msgstr "" + +#: /Model/Registration.php:199 +msgid "please set at least one page." +msgstr "" + +#: /Model/RegistrationAnswer.php:118 +msgid "Input required" +msgstr "" + +#: /Model/RegistrationAnswer.php:122 +msgid "the answer is too long. Please enter under %d letters." +msgstr "" + +#: /Model/RegistrationAnswerSummaryCsv.php:152 +msgid "Respondent" +msgstr "" + +#: /Model/RegistrationAnswerSummaryCsv.php:153 +msgid "Answer Date" +msgstr "" + +#: /Model/RegistrationAnswerSummaryCsv.php:154 +msgid "Number" +msgstr "" + +#: /Model/RegistrationAnswerSummaryCsv.php:191 +msgid "Anonymity" +msgstr "" + +#: /Model/RegistrationChoice.php:80 +msgid "Please input choice text." +msgstr "" + +#: /Model/RegistrationChoice.php:84 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:71 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:89 +msgid "You can not use the character of |, : for choice text " +msgstr "" + +#: /Model/RegistrationChoice.php:103 +msgid "choice sequence is illegal." +msgstr "" + +#: /Model/RegistrationChoice.php:108 +msgid "First character is \"#\". And input the hexadecimal numbers by six digits." +msgstr "" + +#: /Model/RegistrationChoice.php:196 +msgid "Invalid skip page. Please set forward page." +msgstr "" + +#: /Model/RegistrationChoice.php:200 +msgid "Invalid skip page. page does not exist." +msgstr "" + +#: /Model/RegistrationPage.php:85 +msgid "First Page" +msgstr "" + +#: /Model/RegistrationPage.php:198 +msgid "page sequence is illegal." +msgstr "" + +#: /Model/RegistrationPage.php:230 +msgid "please set at least one question." +msgstr "" + +#: /Model/RegistrationQuestion.php:97 +msgid "question sequence is illegal." +msgstr "" + +#: /Model/RegistrationQuestion.php:109 +msgid "Please input question text." +msgstr "" + +#: /Model/RegistrationQuestion.php:155;165 +msgid "Please enter both the maximum and minimum values." +msgstr "" + +#: /Model/RegistrationQuestion.php:159 +msgid "Please enter smaller value than max." +msgstr "" + +#: /Model/RegistrationQuestion.php:169 +msgid "Please enter bigger value than min." +msgstr "" + +#: /Model/RegistrationQuestion.php:318 +msgid "please set at least one choice." +msgstr "" + +#: /Model/RegistrationQuestion.php:329 +msgid "please set at least one choice at row and column." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:75 +msgid "Please enter a valid date in YY-MM-DD format." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:80 +msgid "Please enter the time." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:85 +msgid "Please enter a valid date and time." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerDatetimeBehavior.php:104 +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:69 +msgid "Please enter the answer between %s and %s." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:113;119 +#: /Model/Behavior/RegistrationAnswerSingleListBehavior.php:90 +msgid "Invalid choice" +msgstr "" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:143 +msgid "Please enter something in other item" +msgstr "" + +#: /Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php:181 +msgid "Please answer about all rows." +msgstr "" + +#: /Model/Behavior/RegistrationAnswerSingleListBehavior.php:98 +msgid "Please enter something, if you chose the other item" +msgstr "" + +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:64 +msgid "Number required" +msgstr "" + +#: /Model/Behavior/RegistrationAnswerTextBehavior.php:76 +msgid "Please enter the answer between %s letters and %s letters." +msgstr "" + +#: /View/Elements/ng_status_label.ctp:18 +#: /View/Helper/RegistrationStatusLabelHelper.php:49 +msgid "Before public" +msgstr "" + +#: /View/Elements/ng_status_label.ctp:19 +#: /View/Helper/RegistrationStatusLabelHelper.php:53 +msgid "End" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:15 +msgid "Note: Which may not be 100% because of rounding of numeric total." +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:20 +msgid "Note: Matrix if the number in parentheses is a percentage of the total number of responses." +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_footer.ctp:26 +msgid "Note: If multiple selection is possible, total more than 100% to be." +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:21 +msgid "The total number of answers: " +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:29 +msgid "Select one" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:32 +msgid "Select more than one" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:35 +msgid "Matrix (selection list)" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:38 +msgid "Matrix (multiple)" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:41 +msgid "List selection" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_common_header.ctp:44 +msgid "Not selection" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_matrix_table.ctp:18 +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:17 +msgid "Item name" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:18 +msgid "Aggregate value" +msgstr "" + +#: /View/Elements/AnswerSummaries/aggregate_table.ctp:19 +msgid "The percentage" +msgstr "" + +#: /View/Elements/Answers/answer_test_mode_header.ctp:31 +msgid "Test Mode" +msgstr "" + +#: /View/Elements/Answers/answer_test_mode_header.ctp:34 +msgid "This registration is being temporarily stored . You can registration test before performed in this page . If you want to modify or change the registration , you will be able to edit by pressing the [ Edit question ] button in the upper-right corner ." +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:12 +msgid "select display registrations." +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:18 +msgid "Display" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:31 +#: /View/RegistrationBlocks/index.ctp:34 +msgid "Status" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:37 +msgid "Implementation date" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:40 +msgid "Aggregates" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:84 +#: /View/Elements/RegistrationAdd/create_reuse.ctp:50 +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:69 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:88 +#: /View/RegistrationAnswers/test_mode.ctp:28;41 +#: /View/RegistrationEdit/edit.ctp:81 +#: /View/Registrations/index.ctp:36 +msgid " - " +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_registration.ctp:90 +msgid "On" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:12 +msgid "Registration display setting" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:17 +msgid "Show only one registration" +msgstr "" + +#: /View/Elements/FrameSettings/edit_display_type.ctp:18 +msgid "Show registrations list" +msgstr "" + +#: /View/Elements/FrameSettings/edit_list_display_option.ctp:15 +msgid "Visible registration row" +msgstr "" + +#: /View/Elements/FrameSettings/edit_list_display_option.ctp:26 +msgid "Visible row order" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_new.ctp:14 +msgid "Create new registration" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_new.ctp:21 +msgid "Registration title" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_new.ctp:23 +msgid "Please input registration title" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:14 +msgid "Re-use past registration" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:25 +msgid "Past registration" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:34 +msgid "Refine by entering the part of the registration name" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_reuse.ctp:52 +msgid "Implementation" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_template.ctp:13 +msgid "Create from Template" +msgstr "" + +#: /View/Elements/RegistrationAdd/create_template.ctp:23 +msgid "Registration template file" +msgstr "" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:14 +msgid "Set questions" +msgstr "" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:15 +msgid "Set result display" +msgstr "" + +#: /View/Elements/RegistrationEdit/edit_flow_chart.ctp:16 +msgid "Set registration" +msgstr "" + +#: /View/Elements/RegistrationEdit/registration_title.ctp:14 +msgid "If you want to change the registration title, please edit in \"Set registration\" step." +msgstr "" + +#: /View/Elements/RegistrationEdit/Edit/delete_form.ctp:31 +msgid "Registration" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:16 +msgid "copy to another page" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:20 +msgid "destination page number" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:28 +msgid "Do you want to delete this question ?" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/accordion_heading.ctp:58 +msgid "Skip" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/add_question_button.ctp:18 +msgid "Add Question" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/choice.ctp:14 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/choice.ctp:18 +msgid "(This is [other] choice. Area to enter the text is automatically granted at the time of implementation.)" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:21 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:30 +msgid "Date" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:22 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:31 +msgid "Time" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:23 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:32 +msgid "Date and Time" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/date_option.ctp:49 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/date_option.ctp:59 +msgid "set range to answer date and time" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/matrix_choice_option.ctp:16 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:24 +msgid "Line choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/matrix_choice_option.ctp:27 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:52 +msgid "Column choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/simple_choice_option.ctp:26 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:30 +msgid "randomaize choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/simple_choice_option.ctp:37 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:41 +msgid "set page skip" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:24 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:32 +msgid "Numeric" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:37 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:44 +msgid "Please check if you want to set limit(or length) value." +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:42 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:57 +msgid "Minimum" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_after_published/text_option.ctp:50 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/text_option.ctp:73 +msgid "Maximum" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:28;47 +msgid "Add line choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:55;78 +msgid "Add column choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:62 +msgid "Do you want to delete this choice ?" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/matrix_choice_option.ctp:91 +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:103 +msgid "add another choice" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:20;98 +msgid "add choices" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:64 +msgid "goto end" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:68 +msgid "(new page will be created)" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditQuestion/options_before_published/simple_choice_option.ctp:69 +msgid "create new page for this skip" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/accordion_heading.ctp:23 +msgid "There is an error" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:13 +msgid "display type" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:28 +msgid "Bar Chart" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:36 +msgid "Pie Chart" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/display_type_set.ctp:44 +msgid "Table" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/graph_color_set.ctp:13 +msgid "graph color" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:14 +msgid "aggregate display" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:29 +msgid "The results of this question will not be displayed" +msgstr "" + +#: /View/Elements/RegistrationEdit/EditResult/is_display_set.ctp:38 +msgid "The results of this question will be displayed" +msgstr "" + +#: /View/Elements/Registrations/add_button.ctp:23 +msgid "Create article" +msgstr "" + +#: /View/Elements/Registrations/answer_status.ctp:13 +msgid "View All" +msgstr "" + +#: /View/Elements/Registrations/answer_status.ctp:14 +msgid "Unanswered" +msgstr "" + +#: /View/Elements/Registrations/answer_status.ctp:15 +msgid "Answered" +msgstr "" + +#: /View/Elements/Registrations/answer_status.ctp:18 +#: /View/Helper/RegistrationUtilHelper.php:90 +msgid "Test" +msgstr "" + +#: /View/Elements/Registrations/answer_status.ctp:30 +msgid "Answer status" +msgstr "" + +#: /View/Elements/Registrations/detail_for_editor.ctp:24 +msgid "Author" +msgstr "" + +#: /View/Elements/Registrations/detail_for_editor.ctp:26 +msgid "Modified by" +msgstr "" + +#: /View/Elements/Registrations/detail_for_editor.ctp:32 +msgid "Pages" +msgstr "" + +#: /View/Elements/Registrations/detail_for_editor.ctp:34 +msgid "Questions" +msgstr "" + +#: /View/Elements/Registrations/detail_for_editor.ctp:36 +msgid "Answers" +msgstr "" + +#: /View/Helper/RegistrationAnswerHelper.php:181 +msgid "Please enter a number between %s and %s" +msgstr "" + +#: /View/Helper/RegistrationAnswerHelper.php:183 +msgid "Please enter between %s letters and %s letters" +msgstr "" + +#: /View/Helper/RegistrationAnswerHelper.php:235 +msgid "Please choose one" +msgstr "" + +#: /View/Helper/RegistrationAnswerHelper.php:314;323;331 +msgid "Please enter at %s to %s" +msgstr "" + +#: /View/Helper/RegistrationStatusLabelHelper.php:31 +msgid "Undefined" +msgstr "" + +#: /View/Helper/RegistrationUtilHelper.php:110 +msgid "Answer" +msgstr "" + +#: /View/Helper/RegistrationUtilHelper.php:127 +msgid "Unpublished" +msgstr "" + +#: /View/Helper/RegistrationUtilHelper.php:131 +msgid "Finished" +msgstr "" + +#: /View/RegistrationAdd/add.ctp:27 +msgid "You can create a new registration. Please choose how to create." +msgstr "" + +#: /View/RegistrationAnswerSummaries/view.ctp:86 +#: /View/RegistrationAnswers/no_more_answer.ctp:14 +msgid "Back to Top" +msgstr "" + +#: /View/RegistrationAnswers/confirm.ctp:22 +msgid "Please confirm your answers." +msgstr "" + +#: /View/RegistrationAnswers/confirm.ctp:64 +msgid "Start over" +msgstr "" + +#: /View/RegistrationAnswers/no_more_answer.ctp:12 +msgid "you will not be able to answer this registration." +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:25 +#: /View/RegistrationEdit/edit.ctp:58 +msgid "Registration answer period" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:31 +msgid "do not set the answer period" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:38 +#: /View/RegistrationEdit/edit.ctp:92 +msgid "Counting result display start date" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:43 +msgid "do not set the aggregate display period" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:50 +#: /View/RegistrationEdit/edit.ctp:113 +msgid "Registration method" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:54 +#: /View/RegistrationEdit/edit.ctp:117 +msgid "accept the non-members answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:56 +msgid "do not accept the non-members answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:62 +#: /View/RegistrationEdit/edit.ctp:120 +msgid "use key phrase" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:64 +msgid "key phrase" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:68 +msgid "do not use key phrase" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:74 +#: /View/RegistrationEdit/edit.ctp:129 +msgid "anonymous answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:76 +msgid "register answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:82 +#: /View/RegistrationEdit/edit.ctp:132 +msgid "forgive the repetition of the answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:84 +msgid "do not forgive the repetition of the answer" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:90 +#: /View/RegistrationEdit/edit.ctp:135 +msgid "do image authentication" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:92 +msgid "do not image authentication" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:98 +#: /View/RegistrationEdit/edit.ctp:140 +msgid "Deliver e-mail when submitted" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:100 +msgid "do not deliver e-mail when submitted" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:106 +msgid "Deliver e-mail when started" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:108 +msgid "do not deliver e-mail when started" +msgstr "" + +#: /View/RegistrationAnswers/test_mode.ctp:117 +msgid "Start the test answers of this registration" +msgstr "" + +#: /View/RegistrationAnswers/thanks.ctp:32 +msgid "Back to page" +msgstr "" + +#: /View/RegistrationAnswers/thanks.ctp:37 +msgid "Aggregate" +msgstr "" + +#: /View/RegistrationBlockRolePermissions/noRegistrationBlock.ctp:19 +msgid "There is no registration. First, please create a registration." +msgstr "" + +#: /View/RegistrationBlocks/index.ctp:43 +msgid "Answer CSV" +msgstr "" + +#: /View/RegistrationBlocks/index.ctp:46 +msgid "Templates" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:51 +msgid "Sub Title" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:53 +msgid "Please enter if there is a sub title" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:63 +msgid "set the answer period" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:71 +msgid "After approval will be immediately published . Stop of the registration to select the stop from the registration data list ." +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:97 +msgid "set the aggregate display period" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:99 +msgid "If not set , it will be displayed after the respondent answers." +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:108 +msgid "Result will display at this time." +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:144 +msgid "Registration open mail" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:148 +msgid "Deliver e-mail when registration has opened" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:153 +msgid "open mail subject" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:156 +msgid "open mail text" +msgstr "" + +#: /View/RegistrationEdit/edit.ctp:162 +msgid "Thanks page message settings" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:88 +msgid "Required" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:95 +msgid "set answer to this question is required" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:98 +msgid "question title" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:106 +msgid "question sentence" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:116 +msgid "Question type" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:165 +msgid "Do you want to delete this page?" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:166 +msgid "Delete this page" +msgstr "" + +#: /View/RegistrationEdit/edit_question.ctp:174 +msgid "Add Page" +msgstr "" + +#: /View/RegistrationEdit/edit_result.ctp:48 +msgid "Published aggregate results" +msgstr "" + +#: /View/RegistrationEdit/edit_result.ctp:51 +msgid "not disclose the total result" +msgstr "" + +#: /View/RegistrationEdit/edit_result.ctp:51 +msgid "publish aggregate result" +msgstr "" + +#: /View/RegistrationEdit/edit_result.ctp:65 +msgid "Text to be displayed in the aggregate results page" +msgstr "" + +#: /View/RegistrationEdit/edit_result.ctp:78 +msgid "Question you want to display the aggregate results" +msgstr "" + +#: /View/Registrations/noRegistration.ctp:28 +msgid "no registration" +msgstr "" + +#: /View/Registrations/noRegistration.ctp:33 +msgid "Please create new registration by pressing the \"+\" button." +msgstr "" + diff --git a/Model/ActionRegistrationAdd.php b/Model/ActionRegistrationAdd.php new file mode 100644 index 0000000..bca215d --- /dev/null +++ b/Model/ActionRegistrationAdd.php @@ -0,0 +1,386 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); +App::uses('TemporaryUploadFile', 'Files.Utility'); +App::uses('UnZip', 'Files.Utility'); +App::uses('WysIsWygDownloader', 'Registrations.Utility'); + +/** + * Summary for ActionRegistrationAdd Model + */ +class ActionRegistrationAdd extends RegistrationsAppModel { + +/** + * Use table config + * + * @var bool + */ + public $useTable = 'registrations'; + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + $this->validate = Hash::merge($this->validate, array( + 'create_option' => array( + 'rule' => array( + 'inList', array( + RegistrationsComponent::REGISTRATION_CREATE_OPT_NEW, + RegistrationsComponent::REGISTRATION_CREATE_OPT_REUSE, + RegistrationsComponent::REGISTRATION_CREATE_OPT_TEMPLATE)), + 'message' => __d('registrations', 'Please choose create option.'), + 'required' => true + ), + 'title' => array( + 'rule' => array( + 'requireWhen', 'create_option', RegistrationsComponent::REGISTRATION_CREATE_OPT_NEW), + 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('registrations', 'Title')), + 'required' => false, + ), + 'past_registration_id' => array( + 'requireWhen' => array( + 'rule' => array('requireWhen', 'create_option', RegistrationsComponent::REGISTRATION_CREATE_OPT_REUSE), + 'message' => __d('registrations', 'Please select past registration.'), + ), + 'checkPastRegistration' => array( + 'rule' => array('checkPastRegistration'), + 'message' => __d('registrations', 'Please select past registration.'), + ), + ), + )); + + return parent::beforeValidate($options); + } + +/** + * createRegistration + * 登録フォームデータを作成する + * + * @param array $data 作成する登録フォームデータ + * @return array|bool + */ + public function createRegistration($data) { + // 渡されたRegistrationデータを自Modelデータとする + $this->set($data); + // データチェック + if ($this->validates()) { + // Postデータの内容に問題がない場合は、そのデータをもとに新しい登録フォームデータを作成 + $registration = $this->getNewRegistration(); + return $registration; + } else { + return false; + } + } + +/** + * requireWhen + * + * @param mixed $check チェック対象入力データ + * @param string $sourceField チェック対象フィールド名 + * @param mix $sourceValue チェック値 + * @return bool + */ + public function requireWhen($check, $sourceField, $sourceValue) { + // チェックすべきかどうかの判定データが、指定の状態かチェック + if ($this->data['ActionRegistrationAdd'][$sourceField] != $sourceValue) { + // 指定状態でなければ問題なし + return true; + } + // 指定の状態であれば、チェック対象データがちゃんと入っているか確認する + // Validation::notBlank($check); + if (! array_shift($check)) { + // 指定のデータが指定の値になっている場合は、このデータ空っぽの場合はエラー + return false; + } + return true; + } + +/** + * checkPastRegistration + * + * @param mix $check チェック対象入力データ + * @return bool + */ + public function checkPastRegistration($check) { + if ($this->data['ActionRegistrationAdd']['create_option'] != RegistrationsComponent::REGISTRATION_CREATE_OPT_REUSE) { + return true; + } + $this->Registration = ClassRegistry::init('Registrations.Registration', true); + $cnt = $this->Registration->find('count', array('id' => $check)); + if ($cnt == 0) { + return false; + } + return true; + } + +/** + * getNewRegistration + * + * @return array + */ + public function getNewRegistration() { + $this->Registration = ClassRegistry::init('Registrations.Registration', true); + $this->RegistrationPage = ClassRegistry::init('Registrations.RegistrationPage', true); + $this->RegistrationQuestion = ClassRegistry::init('Registrations.RegistrationQuestion', true); + $createOption = $this->data['ActionRegistrationAdd']['create_option']; + + // 指定された作成のオプションによって処理分岐 + if ($createOption == RegistrationsComponent::REGISTRATION_CREATE_OPT_NEW) { + // 空の新規作成 + $registration = $this->_createNew(); + } elseif ($createOption == RegistrationsComponent::REGISTRATION_CREATE_OPT_REUSE) { + // 過去データからの作成 + $registration = $this->_createFromReuse(); + } elseif ($createOption == RegistrationsComponent::REGISTRATION_CREATE_OPT_TEMPLATE) { + // テンプレートファイルからの作成 + $registration = $this->_createFromTemplate(); + } + return $registration; + } +/** + * _createNew + * + * @return array RegistrationData + */ + protected function _createNew() { + // 登録フォームデータを新規に作成する + // 新規作成の場合、タイトル文字のみ画面で設定されPOSTされる + // Titleをもとに、登録フォームデータ基本構成を作成し返す + + // デフォルトデータをもとに新規作成 + $registration = $this->_getDefaultRegistration(array( + 'title' => $this->data['ActionRegistrationAdd']['title'])); + // 登録フォームデータを返す + return $registration; + } +/** + * _createFromReuse + * + * @return array RegistrationData + */ + protected function _createFromReuse() { + // 登録フォームデータを過去の登録フォームデータをもとにして作成する + // 過去からの作成の場合、参考にする過去の登録フォームのidのみPOSTされてくる + // (orgin_idではなくidである点に注意!) + // idをもとに、過去の登録フォームデータを取得し、 + // そのデータから今回作成する登録フォームデータ基本構成を作成し返す + + // 過去の登録フォームのコピー・クローンで作成 + $registration = $this->_getRegistrationCloneById($this->data['ActionRegistrationAdd']['past_registration_id']); + return $registration; + } +/** + * _getDefaultRegistration + * get default data of registrations + * + * @param array $addData add data to Default data + * @return array + */ + protected function _getDefaultRegistration($addData) { + $registration = array(); + $registration['Registration'] = Hash::merge( + array( + 'block_id' => Current::read('Block.id'), + 'title' => '', + 'key' => '', + 'status' => WorkflowComponent::STATUS_IN_DRAFT, + 'is_total_show' => RegistrationsComponent::EXPRESSION_SHOW, + 'public_type' => WorkflowBehavior::PUBLIC_TYPE_PUBLIC, + 'is_key_pass_use' => RegistrationsComponent::USES_NOT_USE, + 'total_show_timing' => RegistrationsComponent::USES_NOT_USE, + ), + $addData); + + $registration['RegistrationPage'][0] = $this->RegistrationPage->getDefaultPage($registration); + return $registration; + } +/** + * _getRegistrationCloneById 指定されたIDにの登録フォームデータのクローンを取得する + * + * @param int $registrationId 登録フォームID(編集なのでoriginではなくRAWなIDのほう + * @return array + */ + protected function _getRegistrationCloneById($registrationId) { + $registration = $this->Registration->find('first', array( + 'conditions' => array('Registration.id' => $registrationId), + )); + + if (!$registration) { + return $this->getDefaultRegistration(array('title' => '')); + } + // ID値のみクリア + $this->Registration->clearRegistrationId($registration); + + return $registration; + } +/** + * _createFromTemplate + * + * @return array RegistrationData + */ + protected function _createFromTemplate() { + // 登録フォームデータをUPLOADされた登録フォームテンプレートファイルのデータをもとにして作成する + // テンプレートからの作成の場合、テンプレートファイルがUPLOADされてくる + // アップされたファイルをもとに、登録フォームデータを解凍、取得し、 + // そのデータから今回作成する登録フォームデータ基本構成を作成し返す + + // アップロードファイルを受け取り、 + $uploadFile = new TemporaryUploadFile(Hash::get($this->data, 'ActionRegistrationAdd.template_file')); + // エラーチェック + if (! $uploadFile) { + $this->validationErrors['Registration']['template_file'] = __d('registrations', 'file upload error.'); + return null; + } + + // アップロードファイル解凍 + $unZip = new UnZip($uploadFile->path); + $temporaryFolder = $unZip->extract(); + // エラーチェック + if (! $temporaryFolder) { + $this->validationErrors['Registration']['template_file'] = __d('registrations', 'illegal import file.'); + return null; + } + + // フィンガープリント確認 + $fingerPrint = $this->__checkFingerPrint($temporaryFolder->path); + if ($fingerPrint === false) { + $this->validationErrors['Registration']['template_file'] = __d('registrations', 'illegal import file.'); + return null; + } + + // 登録フォームテンプレートファイル本体をテンポラリフォルダに展開する。 + $registrationZip = new UnZip($temporaryFolder->path . DS . RegistrationsComponent::REGISTRATION_TEMPLATE_FILENAME); + if (! $registrationZip->extract()) { + $this->validationErrors['Registration']['template_file'] = __d('registrations', 'illegal import file.'); + return null; + } + + // jsonファイルを読み取り、PHPオブジェクトに変換 + $jsonFilePath = $registrationZip->path . DS . RegistrationsComponent::REGISTRATION_JSON_FILENAME; + $jsonFile = new File($jsonFilePath); + $jsonData = $jsonFile->read(); + $jsonRegistration = json_decode($jsonData, true); + + // 初めにファイルに記載されている登録フォームプラグインのバージョンと + // 現サイトの登録フォームプラグインのバージョンを突合し、差分がある場合はインポート処理を中断する。 + if ($this->__checkVersion($jsonRegistration) === false) { + $this->validationErrors['Registration']['template_file'] = __d('registrations', 'version is different.'); + return null; + } + + // バージョンが一致した場合、登録フォームデータをメモリ上に構築 + $registrations = $this->_getRegistrations( + $registrationZip->path, + $jsonRegistration['Registrations'], + $fingerPrint); + + // 現在の言語環境にマッチしたデータを返す + return $registrations[0]; + } + +/** + * _getRegistrations + * + * @param string $folderPath path string to import zip file exist + * @param array $registrations registration data in import json file + * @param string $importKey import key (hash string) + * @return array RegistrationData + */ + protected function _getRegistrations($folderPath, $registrations, $importKey) { + $wysiswyg = new WysIsWygDownloader(); + + foreach ($registrations as &$q) { + // WysIsWygのデータを入れなおす + $flatRegistration = Hash::flatten($q); + foreach ($flatRegistration as $key => &$value) { + $model = null; + if (strpos($key, 'RegistrationQuestion.') !== false) { + $model = $this->RegistrationQuestion; + } elseif (strpos($key, 'RegistrationPage.') !== false) { + $model = $this->RegistrationPage; + } elseif (strpos($key, 'Registration.') !== false) { + $model = $this->Registration; + } + if (!$model) { + continue; + } + $columnName = substr($key, strrpos($key, '.') + 1); + + if ($model->hasField($columnName)) { + if ($model->getColumnType($columnName) == 'text') { + // keyと同じ名前のフォルダの下にあるkeyの名前のZIPファイルを渡して + // その返ってきた値をこのカラムに設定 + $value = $wysiswyg->getFromWysIsWygZIP($folderPath . DS . $value, $model->alias . '.' . $columnName); + } + } + } + $q = Hash::expand($flatRegistration); + $q['Registration']['import_key'] = $importKey; + } + return $registrations; + } +/** + * __checkFingerPrint + * + * @param string $folderPath folder path + * @return string finger print string + */ + private function __checkFingerPrint($folderPath) { + // フィンガープリントファイルを取得 + $file = new File($folderPath . DS . RegistrationsComponent::REGISTRATION_FINGER_PRINT_FILENAME, false); + $fingerPrint = $file->read(); + + // ファイル内容から算出されるハッシュ値と指定されたフットプリント値を比較し + // 同一であれば正当性が保証されたと判断する(フォーマットチェックなどは行わない) + $registrationZipFile = $folderPath . DS . RegistrationsComponent::REGISTRATION_TEMPLATE_FILENAME; + if (sha1_file($registrationZipFile, false) != $fingerPrint) { + return false; + } + $file->close(); + return $fingerPrint; + } +/** + * __checkVersion + * + * @param array $jsonData バージョンが含まれたJson + * @return bool + */ + private function __checkVersion($jsonData) { + // バージョン情報を取得するためComposer情報を得る + $Plugin = ClassRegistry::init('Plugins.Plugin'); + $composer = $Plugin->getComposer('netcommons/registrations'); + if (!$composer) { + return false; + } + if (!isset($jsonData['version'])) { + return false; + } + if ($composer['version'] != $jsonData['version']) { + return false; + } + return true; + } +} diff --git a/Model/Behavior/RegistrationAnswerBehavior.php b/Model/Behavior/RegistrationAnswerBehavior.php new file mode 100644 index 0000000..b7f5d3c --- /dev/null +++ b/Model/Behavior/RegistrationAnswerBehavior.php @@ -0,0 +1,199 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('ModelBehavior', 'Model'); + +/** + * Answer Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerBehavior extends ModelBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = null; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = false; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = false; + +/** + * setup + * + * @param Model $Model モデル + * @param array $settings 設定値 + * @return void + */ + public function setup(Model $Model, $settings = array()) { + $this->settings[$Model->alias] = $settings; + } + +/** + * beforeSave is called before a model is saved. Returning false from a beforeSave callback + * will abort the save operation. + * 選択肢系の回答の場合、answer_value に [id:value|id:value....]の形で収めなくてはいけない + * 保存前に整える + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False if the operation should abort. Any other result will continue. + * @see Model::save() + */ + public function beforeSave(Model $model, $options = array()) { + if (isset($model->data['RegistrationAnswer']['multi_answer_values'])) { + $model->data['RegistrationAnswer']['answer_value'] = $model->data['RegistrationAnswer']['multi_answer_values']; + } + // elseif (isset($this->data['RegistrationAnswer']['matrix_answer_values'])) { + return true; + } + +/** + * After find callback. Can be used to modify any results returned by find. + * + * @param Model $model Model using this behavior + * @param mixed $results The results of the find operation + * @param bool $primary Whether this model is being queried directly (vs. being queried as an association) + * @return mixed An array value will replace the value of $results - any other value will be ignored. + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) + */ + public function afterFind(Model $model, $results, $primary = false) { + // afterFind 選択肢系の回答の場合、answer_value に [id:value|id:value....]の形で収まっているので + // それをデータ入力画面から渡されるデータ形式と同じにする + foreach ($results as &$val) { + if (isset($val['RegistrationAnswer']['answer_value']) && isset($val['RegistrationQuestion']['question_type'])) { + if ($val['RegistrationQuestion']['question_type'] != $this->_myType) { + continue; + } + if ($this->_isTypeAnsChgArr) { + $val['RegistrationAnswer']['answer_values'] = array(); + $answers = explode(RegistrationsComponent::ANSWER_DELIMITER, trim($val['RegistrationAnswer']['answer_value'], RegistrationsComponent::ANSWER_DELIMITER)); + $val['RegistrationAnswer']['answer_values'] = Hash::combine( + array_map('explode', + array_fill(0, count($answers), RegistrationsComponent::ANSWER_VALUE_DELIMITER), + $answers), + '{n}.0', '{n}.1'); + $val['RegistrationAnswer']['answer_value'] = array_map(array($this, 'setDelimiter'), $answers); + + // array_mapで配列化するのでSingle選択のときはFlatに戻す必要がある + if ($this->_isTypeAnsArrShiftUp) { + $val['RegistrationAnswer']['answer_value'] = $val['RegistrationAnswer']['answer_value'][0]; + } + } + } + } + return $results; + } + +/** + * setDelimiter + * + * @param string $answer answer data + * @return string + */ + public function setDelimiter($answer) { + return '|' . $answer; + } + +/** + * _decomposeAnswerValue + * get decompose answer value by delimiter + * + * @param mix &$dst 加工データ + * @param mix $src 入力データ + * @return void + */ + protected function _decomposeAnswerValue(&$dst, $src) { + // dstがまだ配列型になっていないなら + if (!is_array($dst)) { + $dst = array(); // 初期化 + } + $answers = explode(RegistrationsComponent::ANSWER_VALUE_DELIMITER, trim($src, RegistrationsComponent::ANSWER_DELIMITER)); + $dst[$answers[0]] = isset($answers[1]) ? $answers[1] : ''; + } + +/** + * _setupOtherAnswerValue + * その他オプションにチェックが入っていないのにその他欄に何か書いてあったら空にする + * + * @param Model $model Model using this behavior + * @param array $question 質問データ + * @return void + */ + protected function _setupOtherAnswerValue(Model $model, $question) { + $choice = Hash::extract($question['RegistrationChoice'], '{n}[other_choice_type!=' . RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED . ']'); + if (! $choice) { + return; + } + $key = $choice[0]['key']; + if (! Hash::check($model->data, 'RegistrationAnswer.answer_values.' . $key) && + $model->data['RegistrationAnswer']['matrix_choice_key'] != $key) { + $model->data['RegistrationAnswer']['other_answer_value'] = ''; + } + } + +/** + * answerRequire 回答必須の質問の場合回答されているかの確認 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @return bool + */ + public function answerRequire(&$model, $data, $question) { + if ($question['is_require'] != RegistrationsComponent::REQUIRES_REQUIRE) { + return true; + } + return Validation::notBlank($data['answer_value']); + } + +/** + * answerMaxLength 回答が登録フォームが許す最大長を超えていないかの確認 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param int $max 最大長 + * @return bool + */ + public function answerMaxLength(&$model, $data, $question, $max) { + return true; + } + +/** + * answerValidation 回答内容の正当性 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param array $allAnswers 入力された回答すべて + * @return bool + */ + public function answerValidation(&$model, $data, $question, $allAnswers) { + return true; + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerDatetimeBehavior.php b/Model/Behavior/RegistrationAnswerDatetimeBehavior.php new file mode 100644 index 0000000..330bb46 --- /dev/null +++ b/Model/Behavior/RegistrationAnswerDatetimeBehavior.php @@ -0,0 +1,112 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * Datetime Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerDatetimeBehavior extends RegistrationAnswerBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_DATE_AND_TIME; + +/** + * Answer datetime format + * + * @var array + */ + protected $_datetimeFormat = array( + RegistrationsComponent::TYPE_OPTION_DATE => 'Y-m-d', + RegistrationsComponent::TYPE_OPTION_TIME => 'H:i', + RegistrationsComponent::TYPE_OPTION_DATE_TIME => 'Y-m-d H:i', + ); + +/** + * answerValidation 回答内容の正当性 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param array $allAnswers 入力された回答すべて + * @return bool + */ + public function answerValidation(&$model, $data, $question, $allAnswers) { + if ($question['question_type'] != $this->_myType) { + return true; + } + + $answer = $data['answer_value']; + $ret = true; + if (! $this->_validateDatetime($model, $question['question_type_option'], $answer)) { + $ret = false; + } + if (! $this->_validateTimeRange($model, $question, $answer)) { + $ret = false; + } + return $ret; + } +/** + * _validateDatetime 日付・時間の正当性 + * + * @param object &$model use model + * @param int $questionTypeOption 時間・日付オプション + * @param string $answer 回答データ + * @return bool + */ + protected function _validateDatetime(&$model, $questionTypeOption, $answer) { + if ($questionTypeOption == RegistrationsComponent::TYPE_OPTION_DATE) { + if (! Validation::date($answer, 'ymd')) { + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter a valid date in YY-MM-DD format.')); + return false; + } + } elseif ($questionTypeOption == RegistrationsComponent::TYPE_OPTION_TIME) { + if (! Validation::time($answer)) { + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter the time.')); + return false; + } + } elseif ($questionTypeOption == RegistrationsComponent::TYPE_OPTION_DATE_TIME) { + if (! Validation::datetime($answer, 'ymd')) { + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter a valid date and time.')); + return false; + } + } else { + return false; + } + return true; + } +/** + * _validateDatetime 日付・時間の正当性 + * + * @param object &$model use model + * @param array $question 回答データに対応する質問 + * @param string $answer 回答データ + * @return bool + */ + protected function _validateTimeRange(&$model, $question, $answer) { + if ($question['is_range'] == RegistrationsComponent::USES_USE) { + if (! Validation::range(strtotime($answer), strtotime($question['min']) - 1, strtotime($question['max']) + 1)) { + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter the answer between %s and %s.', + date($this->_datetimeFormat[$question['question_type_option']], strtotime($question['min'])), + date($this->_datetimeFormat[$question['question_type_option']], strtotime($question['max'])))); + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerMatrixMultipleChoiceBehavior.php b/Model/Behavior/RegistrationAnswerMatrixMultipleChoiceBehavior.php new file mode 100644 index 0000000..41511e7 --- /dev/null +++ b/Model/Behavior/RegistrationAnswerMatrixMultipleChoiceBehavior.php @@ -0,0 +1,71 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * MatrixMultipleChoice Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerMatrixMultipleChoiceBehavior extends RegistrationAnswerMatrixSingleChoiceBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_MATRIX_MULTIPLE; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = true; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = false; + +/** + * beforeValidate is called before a model is validated, you can use this callback to + * add behavior validation rules into a models validate array. Returning false + * will allow you to make the validation fail. + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False or null will abort the operation. Any other result will continue. + * @see Model::save() + */ + public function beforeValidate(Model $model, $options = array()) { + $question = $options['question']; + if ($question['question_type'] != $this->_myType) { + return; + } + $model->data['RegistrationAnswer']['matrix_answer_values'] = array(); + $model->data['RegistrationAnswer']['multi_answer_values'] = ''; + $matrixChoiceId = $model->data['RegistrationAnswer']['matrix_choice_key']; + if (is_array($model->data['RegistrationAnswer']['answer_value'])) { + foreach ($model->data['RegistrationAnswer']['answer_value'] as $ans) { + $this->_decomposeAnswerValue($model->data['RegistrationAnswer']['matrix_answer_values'][$matrixChoiceId], $ans); + $model->data['RegistrationAnswer']['multi_answer_values'] .= $ans; + } + } + $this->_setupOtherAnswerValue($model, $question); + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php b/Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php new file mode 100644 index 0000000..39c2ad7 --- /dev/null +++ b/Model/Behavior/RegistrationAnswerMatrixSingleChoiceBehavior.php @@ -0,0 +1,187 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * SingleList Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerMatrixSingleChoiceBehavior extends RegistrationAnswerBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_MATRIX_SELECTION_LIST; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = true; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = true; + +/** + * beforeValidate is called before a model is validated, you can use this callback to + * add behavior validation rules into a models validate array. Returning false + * will allow you to make the validation fail. + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False or null will abort the operation. Any other result will continue. + * @see Model::save() + */ + public function beforeValidate(Model $model, $options = array()) { + $question = $options['question']; + if ($question['question_type'] != $this->_myType) { + return; + } + $model->data['RegistrationAnswer']['matrix_answer_values'] = array(); + $matrixChoiceId = $model->data['RegistrationAnswer']['matrix_choice_key']; + if (isset($model->data['RegistrationAnswer']['answer_value'])) { + $this->_decomposeAnswerValue($model->data['RegistrationAnswer']['answer_values'], + $model->data['RegistrationAnswer']['answer_value']); + $this->_decomposeAnswerValue($model->data['RegistrationAnswer']['matrix_answer_values'][$matrixChoiceId], + $model->data['RegistrationAnswer']['answer_value']); + } + $this->_setupOtherAnswerValue($model, $question); + } + +/** + * answerValidation 回答内容の正当性 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param array $allAnswers 入力された回答すべて + * @return bool + */ + public function answerValidation(&$model, $data, $question, $allAnswers) { + if ($question['question_type'] != $this->_myType) { + return true; + } + $ret = true; + if (isset($model->data['RegistrationAnswer']['matrix_answer_values'])) { + $list = Hash::combine($question['RegistrationChoice'], '{n}.key', '{n}.key'); + if (! $this->checkMatrixAnswerInList($model, $model->data['RegistrationAnswer']['matrix_answer_values'], $list)) { + $ret = false; + } + if (! $this->checkMatrixOtherAnswer($model, $question, $model->data['RegistrationAnswer']['matrix_answer_values'], $model->data['RegistrationAnswer'])) { + $ret = false; + } + if (! $this->checkMatrixAnswerFill($model, $question, $model->data['RegistrationAnswer'], $allAnswers)) { + $ret = false; + } + } + return $ret; + } + +/** + * checkMatrixAnswerInList + * + * @param object &$model use model + * @param string $answers answer value + * @param int $list choice list ( choice key list) + * @return bool + */ + public function checkMatrixAnswerInList(&$model, $answers, $list) { + $ret = true; + foreach ($answers as $matrixRowId => $matrixColAns) { + if (!Validation::inList(strval($matrixRowId), $list)) { + $ret = false; + $model->validationErrors['answer_value'][] = __d('registrations', 'Invalid choice'); + } + $choiceIds = array_keys($matrixColAns); + foreach ($choiceIds as $choiceId) { + if ($choiceId != '' && !Validation::inList(strval($choiceId), $list)) { + $ret = false; + $model->validationErrors['answer_value'][] = __d('registrations', 'Invalid choice'); + } + } + } + return $ret; + } + +/** + * checkMatrixOtherAnswer + * + * @param object &$model use model + * @param array $question question + * @param string $answers answer value + * @param string $otherAnswer other answer string + * @return bool + */ + public function checkMatrixOtherAnswer(&$model, $question, $answers, $otherAnswer) { + // このやり方だと、「その他」行がマトリクスにある時は必ず入力しなきゃいけなくなる? + // 選択肢を何も選択しなかったらAnswerデータが飛んでこないからチェックにかからないか? + $rowIds = array_keys($answers); + foreach ($rowIds as $matrixRowId) { + $results = Hash::extract($question['RegistrationChoice'], '{n}[key=' . $matrixRowId . ']'); + if ($results && $results[0]['other_choice_type'] != RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED) { + if (empty($otherAnswer['other_answer_value'])) { + $model->validationErrors['answer_value'][] = __d('registrations', 'Please enter something in other item'); + return false; + } + } + } + return true; + } + +/** + * checkMatrixAnswerFill + * + * @param object &$model use model + * @param array $question question + * @param string $answers all row answer value + * @param array $allAnswers 入力された回答すべて + * @return array error message + */ + public function checkMatrixAnswerFill(&$model, $question, $answers, $allAnswers) { + if ($model->oneTimeValidateFlag) { // チェック済 + return true; + } + // マトリクスの場合は全行回答するか全行回答しないかでないと集計計算が狂うので + // 全行回答か全行無回答かを確認している + $answerCount = 0; + $noAnswerCount = 0; + $checkAnswer = $allAnswers[$question['key']]; + foreach ($checkAnswer as $ans) { + if (!isset($ans['id'])) { + // id すらないのはblackhole対応のためのhidden要素であるので無視 + continue; + } + if ($ans['answer_value'] == '') { + $noAnswerCount++; + } + $answerCount++; + } + $model->oneTimeValidateFlag = true; // チェックした + if ($noAnswerCount > 0 && $noAnswerCount < $answerCount) { + $model->validationErrors['answer_value'][] = __d('registrations', 'Please answer about all rows.'); + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerMultipleChoiceBehavior.php b/Model/Behavior/RegistrationAnswerMultipleChoiceBehavior.php new file mode 100644 index 0000000..0655c98 --- /dev/null +++ b/Model/Behavior/RegistrationAnswerMultipleChoiceBehavior.php @@ -0,0 +1,70 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * SingleChoice Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerMultipleChoiceBehavior extends RegistrationAnswerSingleListBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_MULTIPLE_SELECTION; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = true; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = false; + +/** + * beforeValidate is called before a model is validated, you can use this callback to + * add behavior validation rules into a models validate array. Returning false + * will allow you to make the validation fail. + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False or null will abort the operation. Any other result will continue. + * @see Model::save() + */ + public function beforeValidate(Model $model, $options = array()) { + $question = $options['question']; + if ($question['question_type'] != $this->_myType) { + return; + } + $model->data['RegistrationAnswer']['answer_values'] = array(); + $model->data['RegistrationAnswer']['multi_answer_values'] = ''; + if (is_array($model->data['RegistrationAnswer']['answer_value'])) { + foreach ($model->data['RegistrationAnswer']['answer_value'] as $a) { + $this->_decomposeAnswerValue($model->data['RegistrationAnswer']['answer_values'], $a); + $model->data['RegistrationAnswer']['multi_answer_values'] .= $a; + } + } + $this->_setupOtherAnswerValue($model, $question); + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerSingleChoiceBehavior.php b/Model/Behavior/RegistrationAnswerSingleChoiceBehavior.php new file mode 100644 index 0000000..fae0b8d --- /dev/null +++ b/Model/Behavior/RegistrationAnswerSingleChoiceBehavior.php @@ -0,0 +1,63 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerSingleListBehavior', 'Registrations.Model/Behavior'); + +/** + * SingleChoice Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerSingleChoiceBehavior extends RegistrationAnswerSingleListBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_SELECTION; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = true; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = true; + +/** + * beforeValidate is called before a model is validated, you can use this callback to + * add behavior validation rules into a models validate array. Returning false + * will allow you to make the validation fail. + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False or null will abort the operation. Any other result will continue. + * @see Model::save() + */ + public function beforeValidate(Model $model, $options = array()) { + $question = $options['question']; + if ($question['question_type'] != $this->_myType) { + return; + } + parent::beforeValidate($model, $options); + $this->_setupOtherAnswerValue($model, $question); + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerSingleListBehavior.php b/Model/Behavior/RegistrationAnswerSingleListBehavior.php new file mode 100644 index 0000000..099584b --- /dev/null +++ b/Model/Behavior/RegistrationAnswerSingleListBehavior.php @@ -0,0 +1,106 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * SingleList Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerSingleListBehavior extends RegistrationAnswerBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_SINGLE_SELECT_BOX; + +/** + * this answer type + * data in database must be changed to array + * + * @var int + */ + protected $_isTypeAnsChgArr = true; + +/** + * this answer type + * data array must be shift up for post data array in screen + * + * @var int + */ + protected $_isTypeAnsArrShiftUp = true; + +/** + * beforeValidate is called before a model is validated, you can use this callback to + * add behavior validation rules into a models validate array. Returning false + * will allow you to make the validation fail. + * + * @param Model $model Model using this behavior + * @param array $options Options passed from Model::save(). + * @return mixed False or null will abort the operation. Any other result will continue. + * @see Model::save() + */ + public function beforeValidate(Model $model, $options = array()) { + $question = $options['question']; + if ($question['question_type'] != $this->_myType) { + return; + } + $model->data['RegistrationAnswer']['answer_values'] = array(); + if (isset($model->data['RegistrationAnswer']['answer_value'])) { + $this->_decomposeAnswerValue($model->data['RegistrationAnswer']['answer_values'], + $model->data['RegistrationAnswer']['answer_value']); + } + } +/** + * answerValidation 回答内容の正当性 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param array $allAnswers 入力された回答すべて + * @return bool + */ + public function answerValidation(&$model, $data, $question, $allAnswers) { + if ($question['question_type'] != $this->_myType) { + return true; + } + $ret = true; + if (isset($model->data['RegistrationAnswer']['answer_values'])) { + // 質問に設定されている選択肢を配列にまとめる + $list = Hash::combine($question['RegistrationChoice'], '{n}.id', '{n}.key'); + + // 選択された選択肢IDすべてについて調査する + $choiceIds = array_keys($model->data['RegistrationAnswer']['answer_values']); + foreach ($choiceIds as $choiceId) { + // 選択されたIDは、ちゃんと用意されている選択肢の中のひとつであるか + if ($choiceId != '' && !Validation::inList(strval($choiceId), $list)) { + $ret = false; + $model->validationErrors['answer_value'][] = __d('registrations', 'Invalid choice'); + } + // チェックされている選択肢が「その他」の項目である場合は + $choice = Hash::extract($question['RegistrationChoice'], '{n}[key=' . $choiceId . ']'); + if ($choice && $choice[0]['other_choice_type'] != RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED) { + // 具体的なテキストが書かれていないといけない + if (empty($model->data['RegistrationAnswer']['other_answer_value'])) { + $ret = false; + $model->validationErrors['answer_value'][] = __d('registrations', 'Please enter something, if you chose the other item'); + } + } + } + } + return $ret; + } + +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerTextAreaBehavior.php b/Model/Behavior/RegistrationAnswerTextAreaBehavior.php new file mode 100644 index 0000000..58e9935 --- /dev/null +++ b/Model/Behavior/RegistrationAnswerTextAreaBehavior.php @@ -0,0 +1,45 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * TextArea Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerTextAreaBehavior extends RegistrationAnswerBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_TEXT_AREA; + +/** + * answerMaxLength 回答が登録フォームが許す最大長を超えていないかの確認 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param int $max 最大長 + * @return bool + */ + public function answerMaxLength(&$model, $data, $question, $max) { + if ($question['question_type'] != $this->_myType) { + return true; + } + return Validation::maxLength($data['answer_value'], $max); + } + +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationAnswerTextBehavior.php b/Model/Behavior/RegistrationAnswerTextBehavior.php new file mode 100644 index 0000000..bfd4fef --- /dev/null +++ b/Model/Behavior/RegistrationAnswerTextBehavior.php @@ -0,0 +1,82 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAnswerBehavior', 'Registrations.Model/Behavior'); + +/** + * Text Behavior + * + * @package Registrations\Registrations\Model\Befavior\Answer + * @author Allcreator + */ +class RegistrationAnswerTextBehavior extends RegistrationAnswerBehavior { + +/** + * this answer type + * + * @var int + */ + protected $_myType = RegistrationsComponent::TYPE_TEXT; + +/** + * answerMaxLength 回答が登録フォームが許す最大長を超えていないかの確認 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param int $max 最大長 + * @return bool + */ + public function answerMaxLength(&$model, $data, $question, $max) { + if ($question['question_type'] != $this->_myType) { + return true; + } + return Validation::maxLength($data['answer_value'], $max); + } + +/** + * answerValidation 回答内容の正当性 + * + * @param object &$model use model + * @param array $data Validation対象データ + * @param array $question 回答データに対応する質問 + * @param array $allAnswers 入力された回答すべて + * @return bool + */ + public function answerValidation(&$model, $data, $question, $allAnswers) { + if ($question['question_type'] != $this->_myType) { + return true; + } + $ret = true; + + // 数値型回答を望まれている場合 + if ($question['question_type_option'] == RegistrationsComponent::TYPE_OPTION_NUMERIC) { + if (!Validation::numeric($data['answer_value'])) { + $ret = false; + $model->validationErrors['answer_value'][] = __d('registrations', 'Number required'); + } + if ($question['is_range'] == RegistrationsComponent::USES_USE) { + if (!Validation::range($data['answer_value'], intval($question['min']), intval($question['max']))) { + $ret = false; + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter the answer between %s and %s.', $question['min'], $question['max'])); + } + } + } else { + if ($question['is_range'] == RegistrationsComponent::USES_USE) { + if (!Validation::minLength($data['answer_value'], intval($question['min'])) || !Validation::maxLength($data['answer_value'], intval($question['max']))) { + $ret = false; + $model->validationErrors['answer_value'][] = sprintf(__d('registrations', 'Please enter the answer between %s letters and %s letters.', $question['min'], $question['max'])); + } + } + } + return $ret; + } +} \ No newline at end of file diff --git a/Model/Behavior/RegistrationValidateBehavior.php b/Model/Behavior/RegistrationValidateBehavior.php new file mode 100644 index 0000000..e78ce3f --- /dev/null +++ b/Model/Behavior/RegistrationValidateBehavior.php @@ -0,0 +1,229 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('ModelBehavior', 'Model'); + +/** + * RegistrationValidate Behavior + * + * @package Registrations\Registrations\Model\Befavior + * @author Allcreator + */ +class RegistrationValidateBehavior extends ModelBehavior { + +/** + * Checks if flag is on, required other fields + * + * @param object &$model use model + * @param array $check check data array + * @param mix $requireValue when check data value equal this value, then require other field + * @param array $others require data field names + * @param string $ope require condition AND or OR or XOR + * @return bool + */ + public function requireOtherFields(&$model, $check, $requireValue, $others, $ope) { + $checkPatterns = array( + 'AND' => array('midstream' => array('chk' => true, 'ret' => false), 'end' => array('ret' => true)), + 'OR' => array('midstream' => array('chk' => false, 'ret' => true), 'end' => array('ret' => false)), + 'XOR' => array('midstream' => array('chk' => false, 'ret' => false), 'end' => array('ret' => true)), + ); + $ope = strtoupper($ope); + $checkPattern = $checkPatterns[$ope]; + $value = array_values($check); + $value = $value[0]; + if ($value != $requireValue) { + return true; + } + foreach ($others as $other) { + $checkData = Hash::get($model->data, $other); + $otherFieldsName = explode('.', $other); + // is_系のフィールドの場合、チェックボックスで実装され、OFFでも0という数値が入ってくる + // そうすると「Blank」判定してほしいのに「ある」と判定されてしまう + // なのでis_で始まるフィールドのデータの設定を確認するときだけは == falseで判定する + if (strncmp('is_', $otherFieldsName[count($otherFieldsName) - 1], 3) === 0) { + $ret = ($checkData == false); + } else { + $ret = Validation::blank($checkData); + } + if ($ret == $checkPattern['midstream']['chk']) { + return $checkPattern['midstream']['ret']; + } + } + return $checkPattern['end']['ret']; + } +/** + * Checks datetime null or datetime + * + * @param object &$model use model + * @param array $check check data array + * @return bool + */ + public function checkDateTime(&$model, $check) { + foreach ($check as $val) { + if (Validation::blank($val)) { + continue; + } + $ret = Validation::datetime($val); + if (!$ret) { + return false; + } + } + return true; + } + +/** + * Used to compare 2 datetime values. + * + * @param object &$model use model + * @param string|array $check datetime string + * @param string $operator Can be either a word or operand + * is greater >, is less <, greater or equal >= + * less or equal <=, is less <, equal to ==, not equal != + * @param string $compare compare datetime string + * @return bool Success + */ + public function checkDateComp(&$model, $check, $operator, $compare) { + // 比較対象がないので比較する必要なし + if (Validation::blank($model->data['Registration'][$compare])) { + return true; + } + + $check2 = strtotime($model->data['Registration'][$compare]); + foreach ($check as $val) { + if (Validation::blank($val)) { + continue; + } + $check1 = strtotime($val); + $ret = Validation::comparison($check1, $operator, $check2); + if (!$ret) { + return false; + } + } + return true; + } + +/** + * checkMinMax + * min and max is require both value + * + * @param object &$model use model + * @param bool $check post data + * @return bool + */ + public function checkMinMax(&$model, $check) { + // 範囲使わない設定のときはチェックしない + if ($model->data['RegistrationQuestion']['is_range'] == RegistrationsComponent::USES_NOT_USE) { + return true; + } + + // 最大値、最小値はテキストで「数値型」の場合と、日付け型の「日」「日時」の場合のみ設定可能 + if (!$this->__checkMinMaxNumeric($model, $check)) { + return false; + } + if (!$this->__checkMinMaxDate($model, $check)) { + return false; + } + if (!$this->__checkMinMaxDateTime($model, $check)) { + return false; + } + if ($model->data['RegistrationQuestion']['min'] >= $model->data['RegistrationQuestion']['max']) { + return false; + } + + return true; + } + +/** + * getPeriodStatus + * get period status now and specified time + * + * @param object &$model use model + * @param bool $check flag data + * @param string $startTime start time + * @param string $endTime end time + * @return int + */ + public function getPeriodStatus(&$model, $check, $startTime, $endTime) { + $ret = RegistrationsComponent::REGISTRATION_PERIOD_STAT_IN; + + if ($check == WorkflowBehavior::PUBLIC_TYPE_LIMITED) { + $nowTime = (new NetCommonsTime())->getNowDatetime(); + $nowTime = strtotime($nowTime); + if ($nowTime < strtotime($startTime)) { + $ret = RegistrationsComponent::REGISTRATION_PERIOD_STAT_BEFORE; + } + if ($nowTime > strtotime($endTime)) { + $ret = RegistrationsComponent::REGISTRATION_PERIOD_STAT_END; + } + } + return $ret; + } + +/** + * __checkMinMaxNumeric + * min and max is require both value + * + * @param object &$model use model + * @param bool $check post data + * @return bool + */ + private function __checkMinMaxNumeric(&$model, $check) { + if ($model->data['RegistrationQuestion']['question_type_option'] == RegistrationsComponent::TYPE_OPTION_NUMERIC) { + if (!Validation::numeric($model->data['RegistrationQuestion']['min'])) { + return false; + } + if (!Validation::numeric($model->data['RegistrationQuestion']['max'])) { + return false; + } + } + return true; + } + +/** + * __checkMinMaxDate + * min and max is require both value + * + * @param object &$model use model + * @param bool $check post data + * @return bool + */ + private function __checkMinMaxDate(&$model, $check) { + if ($model->data['RegistrationQuestion']['question_type_option'] == RegistrationsComponent::TYPE_OPTION_DATE) { + if (!Validation::date($model->data['RegistrationQuestion']['min'])) { + return false; + } + if (!Validation::date($model->data['RegistrationQuestion']['max'])) { + return false; + } + } + return true; + } + +/** + * __checkMinMaxDateTime + * min and max is require both value + * + * @param object &$model use model + * @param bool $check post data + * @return bool + */ + private function __checkMinMaxDateTime(&$model, $check) { + if ($model->data['RegistrationQuestion']['question_type_option'] == RegistrationsComponent::TYPE_OPTION_DATE_TIME) { + if (!Validation::datetime($model->data['RegistrationQuestion']['min'])) { + return false; + } + if (!Validation::datetime($model->data['RegistrationQuestion']['max'])) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Model/Behavior/empty b/Model/Behavior/empty new file mode 100644 index 0000000..e69de29 diff --git a/Model/Datasource/empty b/Model/Datasource/empty new file mode 100644 index 0000000..e69de29 diff --git a/Model/Registration.php b/Model/Registration.php new file mode 100644 index 0000000..86192a1 --- /dev/null +++ b/Model/Registration.php @@ -0,0 +1,565 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for Registration Model + */ +class Registration extends RegistrationsAppModel { + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.OriginalKey', + 'Workflow.Workflow', + 'Workflow.WorkflowComment', + 'AuthorizationKeys.AuthorizationKey', + 'Registrations.RegistrationValidate', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'Block' => array( + 'className' => 'Blocks.Block', + 'foreignKey' => 'block_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + ); + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'RegistrationPage' => array( + 'className' => 'Registrations.RegistrationPage', + 'foreignKey' => 'registration_id', + 'dependent' => true, + 'conditions' => '', + 'fields' => '', + 'order' => array('page_sequence' => 'ASC'), + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + $this->validate = Hash::merge($this->validate, array( + 'block_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + 'message' => __d('net_commons', 'Invalid request.'), + 'on' => 'update', // Limit validation to 'create' or 'update' operations 新規の時はブロックIDがなかったりするから + ) + ), + 'title' => array( + 'rule' => 'notBlank', + 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('registrations', 'Title')), + 'required' => true, + 'allowEmpty' => false, + 'required' => true, + ), + 'public_type' => array( + 'publicTypeCheck' => array( + 'rule' => array('inList', array(WorkflowBehavior::PUBLIC_TYPE_PUBLIC, WorkflowBehavior::PUBLIC_TYPE_LIMITED)), + 'message' => __d('net_commons', 'Invalid request.'), + ), + 'requireOtherFields' => array( + 'rule' => array('requireOtherFields', WorkflowBehavior::PUBLIC_TYPE_LIMITED, array('Registration.publish_start', 'Registration.publish_end'), 'OR'), + 'message' => __d('registrations', 'if you set the period, please set time.') + ) + ), + 'publish_start' => array( + 'checkDateTime' => array( + 'rule' => 'checkDateTime', + 'message' => __d('registrations', 'Invalid datetime format.') + ) + ), + 'publish_end' => array( + 'checkDateTime' => array( + 'rule' => 'checkDateTime', + 'message' => __d('registrations', 'Invalid datetime format.') + ), + 'checkDateComp' => array( + 'rule' => array('checkDateComp', '>=', 'publish_start'), + 'message' => __d('registrations', 'start period must be smaller than end period') + ) + ), + 'total_show_timing' => array( + 'inList' => array( + 'rule' => array('inList', array(RegistrationsComponent::USES_USE, RegistrationsComponent::USES_NOT_USE)), + 'message' => __d('net_commons', 'Invalid request.'), + ), + 'requireOtherFields' => array( + 'rule' => array('requireOtherFields', RegistrationsComponent::USES_USE, array('Registration.total_show_start_period'), 'AND'), + 'message' => __d('registrations', 'if you set the period, please set time.') + ) + ), + 'total_show_start_period' => array( + 'checkDateTime' => array( + 'rule' => 'checkDateTime', + 'message' => __d('registrations', 'Invalid datetime format.') + ) + ), + 'is_no_member_allow' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_anonymity' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_key_pass_use' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + 'requireOtherFieldsKey' => array( + 'rule' => array('requireOtherFields', RegistrationsComponent::USES_USE, array('AuthorizationKey.authorization_key'), 'AND'), + 'message' => __d('registrations', 'if you set the use key phrase period, please set key phrase text.') + ), + 'authentication' => array( + 'rule' => array('requireOtherFields', RegistrationsComponent::USES_USE, array('Registration.is_image_authentication'), 'XOR'), + 'message' => __d('registrations', 'Authentication key setting , image authentication , either only one can not be selected.') + ) + ), + 'is_repeat_allow' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_image_authentication' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + 'authentication' => array( + 'rule' => array('requireOtherFields', RegistrationsComponent::USES_USE, array('Registration.is_key_pass_use'), 'XOR'), + 'message' => __d('registrations', 'Authentication key setting , image authentication , either only one can not be selected.') + ) + ), + 'is_answer_mail_send' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + )); + + parent::beforeValidate($options); + // 最低でも1ページは存在しないとエラー + if (! isset($this->data['RegistrationPage'][0])) { + $this->validationErrors['pickup_error'] = __d('registrations', 'please set at least one page.'); + } else { + // ページデータが存在する場合 + // 配下のページについてバリデート + $validationErrors = array(); + $this->RegistrationPage = ClassRegistry::init('Registrations.RegistrationPage', true); + $maxPageIndex = count($this->data['RegistrationPage']); + $options['maxPageIndex'] = $maxPageIndex; + foreach ($this->data['RegistrationPage'] as $pageIndex => $page) { + // それぞれのページのフィールド確認 + $this->RegistrationPage->create(); + $this->RegistrationPage->set($page); + // ページシーケンス番号の正当性を確認するため、現在の配列インデックスを渡す + $options['pageIndex'] = $pageIndex; + if (! $this->RegistrationPage->validates($options)) { + $validationErrors['RegistrationPage'][$pageIndex] = $this->RegistrationPage->validationErrors; + } + } + $this->validationErrors += $validationErrors; + } + // 引き続き登録フォーム本体のバリデートを実施してもらうためtrueを返す + return true; + } +/** + * AfterFind Callback function + * + * @param array $results found data records + * @param bool $primary indicates whether or not the current model was the model that the query originated on or whether or not this model was queried as an association + * @return mixed + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) + */ + public function afterFind($results, $primary = false) { + if ($this->recursive == -1) { + return $results; + } + $this->RegistrationPage = ClassRegistry::init('Registrations.RegistrationPage', true); + $this->RegistrationAnswerSummary = ClassRegistry::init('Registrations.RegistrationAnswerSummary', true); + + foreach ($results as &$val) { + // この場合はcount + if (! isset($val['Registration']['id'])) { + continue; + } + // この場合はdelete + if (! isset($val['Registration']['key'])) { + continue; + } + + $val['Registration']['period_range_stat'] = $this->getPeriodStatus( + isset($val['Registration']['public_type']) ? $val['Registration']['public_type'] : false, + $val['Registration']['publish_start'], + $val['Registration']['publish_end']); + + // + // ページ配下の質問データも取り出す + // かつ、ページ数、質問数もカウントする + $val['Registration']['page_count'] = 0; + $val['Registration']['question_count'] = 0; + $this->RegistrationPage->setPageToRegistration($val); + + $val['Registration']['all_answer_count'] = $this->RegistrationAnswerSummary->find('count', array( + 'conditions' => array( + 'registration_key' => $val['Registration']['key'], + 'answer_status' => RegistrationsComponent::ACTION_ACT, + 'test_status' => RegistrationsComponent::TEST_ANSWER_STATUS_PEFORM + ), + 'recursive' => -1 + )); + } + return $results; + } + +/** + * After frame save hook + * + * このルームにすでに登録フォームブロックが存在した場合で、かつ、現在フレームにまだブロックが結びついてない場合、 + * すでに存在するブロックと現在フレームを結びつける + * + * @param array $data received post data + * @return mixed On success Model::$data if its not empty or true, false on failure + * @throws InternalErrorException + */ + public function afterFrameSave($data) { + // すでに結びついている場合は何もしないでよい + if (!empty($data['Frame']['block_id'])) { + return $data; + } + $frame = $data['Frame']; + // ルームに存在するブロックを探す + $block = $this->Block->find('first', array( + 'conditions' => array( + 'Block.room_id' => $frame['room_id'], + 'Block.plugin_key' => $frame['plugin_key'], + ) + )); + // まだない場合 + if (empty($block)) { + // 作成する + $block = $this->Block->save(array( + 'room_id' => $frame['room_id'], + 'language_id' => $frame['language_id'], + 'plugin_key' => $frame['plugin_key'], + )); + if (! $block) { + return false; + } + Current::$current['Block'] = $block['Block']; + } + + $this->loadModels([ + 'Frame' => 'Frames.Frame', + 'RegistrationSetting' => 'Registrations.RegistrationSetting', + ]); + $data['Frame']['block_id'] = $block['Block']['id']; + if (! $this->Frame->save($data)) { + return false; + } + Current::$current['Frame']['block_id'] = $block['Block']['id']; + + $blockSetting = $this->RegistrationSetting->create(); + $blockSetting['RegistrationSetting']['block_key'] = $block['Block']['key']; + $this->RegistrationSetting->saveRegistrationSetting($blockSetting); + return $data; + } +/** + * geRegistrationsList + * get registrations by specified block id and specified user id limited number + * + * @param array $conditions find condition + * @param array $options 検索オプション + * @return array + */ + public function getRegistrationsList($conditions, $options = array()) { + //$limit = RegistrationsComponent::REGISTRATION_DEFAULT_DISPLAY_NUM_PER_PAGE}, $offset = 0, $sort = 'modified DESC') { + // 絞込条件 + $baseConditions = $this->getBaseCondition(); + $conditions = Hash::merge($baseConditions, $conditions); + + // 取得オプション + $this->RegistrationFrameSetting = ClassRegistry::init('Registrations.RegistrationFrameSetting', true); + $defaultOptions = $this->RegistrationFrameSetting->getRegistrationFrameSettingConditions(Current::read('Frame.key')); + $options = Hash::merge($defaultOptions, $options); + $list = $this->find('all', array( + 'recursive' => 0, + 'conditions' => $conditions, + $options + )); + return $list; + } + +/** + * get index sql condition method + * + * @param array $addConditions 追加条件 + * @return array + */ + public function getCondition($addConditions = array()) { + // ベースとなる権限のほかに現在フレームに表示設定されている登録フォームか見ている + $conditions = $this->getBaseCondition($addConditions); + + $frameDisplay = ClassRegistry::init('Registrations.RegistrationFrameDisplayRegistrations'); + $keys = $frameDisplay->find( + 'list', + array( + 'conditions' => array('RegistrationFrameDisplayRegistrations.frame_key' => Current::read('Frame.key')), + 'fields' => array('RegistrationFrameDisplayRegistrations.registration_key'), + 'recursive' => -1 + ) + ); + $conditions['Registration.key'] = $keys; + + if ($addConditions) { + $conditions = array_merge($conditions, $addConditions); + } + return $conditions; + } + +/** + * get index sql condition method + * + * @param array $addConditions 追加条件 + * @return array + */ + public function getBaseCondition($addConditions = array()) { + $conditions = $this->getWorkflowConditions(array( + 'block_id' => Current::read('Block.id'), + )); + + if (! Current::read('User.id')) { + $conditions['is_no_member_allow'] = RegistrationsComponent::PERMISSION_PERMIT; + } + + if ($addConditions) { + $conditions = array_merge($conditions, $addConditions); + } + return $conditions; + } + +/** + * saveRegistration + * save Registration data + * + * @param array &$registration registration + * @throws InternalErrorException + * @return bool + */ + public function saveRegistration(&$registration) { + $this->loadModels([ + 'RegistrationPage' => 'Registrations.RegistrationPage', + 'RegistrationFrameDisplayRegistration' => 'Registrations.RegistrationFrameDisplayRegistration', + 'RegistrationAnswerSummary' => 'Registrations.RegistrationAnswerSummary', + ]); + + //トランザクションBegin + $this->begin(); + + try { + $status = $registration['Registration']['status']; + $this->create(); + // 登録フォームは履歴を取っていくタイプのコンテンツデータなのでSave前にはID項目はカット + // (そうしないと既存レコードのUPDATEになってしまうから) + // (ちなみにこのカット処理をbeforeSaveで共通でやってしまおうとしたが、 + // beforeSaveでIDをカットしてもUPDATE動作になってしまっていたのでここに置くことにした) + $registration = Hash::remove($registration, 'Registration.id'); + + $this->set($registration); + + $saveRegistration = $this->save($registration); + if (! $saveRegistration) { + $this->rollback(); + return false; + } + $registrationId = $this->id; + + // ページ以降のデータを登録 + $registration = Hash::insert($registration, 'RegistrationPage.{n}.registration_id', $registrationId); + if (! $this->RegistrationPage->saveRegistrationPage($registration['RegistrationPage'])) { + $this->rollback(); + return false; + } + // フレーム内表示対象登録フォームに登録する + if (! $this->RegistrationFrameDisplayRegistration->saveDisplayRegistration(array( + 'registration_key' => $saveRegistration['Registration']['key'], + 'frame_key' => Current::read('Frame.key') + ))) { + $this->rollback(); + return false; + } + // これまでのテスト回答データを消す + $this->RegistrationAnswerSummary->deleteTestAnswerSummary($saveRegistration['Registration']['key'], $status); + + $this->commit(); + } catch (Exception $ex) { + $this->rollback(); + CakeLog::error($ex); + throw $ex; + } + return $registration; + } + +/** + * deleteRegistration + * Delete the registration data set of specified ID + * + * @param array $data post data + * @throws InternalErrorException + * @return bool + */ + public function deleteRegistration($data) { + $this->loadModels([ + 'RegistrationFrameDisplayRegistration' => 'Registrations.RegistrationFrameDisplayRegistration', + 'RegistrationAnswerSummary' => 'Registrations.RegistrationAnswerSummary', + ]); + $this->begin(); + try { + // 登録フォーム質問データ削除 + if (! $this->deleteAll(array( + 'Registration.key' => $data['Registration']['key']), true, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + //コメントの削除 + $this->deleteCommentsByContentKey($this->data['Registration']['key']); + + // 登録フォーム表示設定削除 + if (! $this->RegistrationFrameDisplayRegistration->deleteAll(array( + 'registration_key' => $data['Registration']['key']), true, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + // 登録フォーム回答削除 + if (! $this->RegistrationAnswerSummary->deleteAll(array( + 'registration_key' => $data['Registration']['key']), true, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + $this->commit(); + } catch (Exception $ex) { + //トランザクションRollback + $this->rollback(); + //エラー出力 + CakeLog::error($ex); + throw $ex; + } + + return true; + } +/** + * saveExportKey + * update export key + * + * @param int $registrationId id of registration + * @param string $exportKey exported key ( finger print) + * @throws InternalErrorException + * @return bool + */ + public function saveExportKey($registrationId, $exportKey) { + $this->begin(); + try { + $this->id = $registrationId; + $this->saveField('export_key', $exportKey); + } catch (Exception $ex) { + //トランザクションRollback + $this->rollback(); + //エラー出力 + CakeLog::error($ex); + throw $ex; + } + return true; + } +/** + * hasPublished method + * + * @param array $registration registration data + * @return int + */ + public function hasPublished($registration) { + if (isset($registration['Registration']['key'])) { + $isPublished = $this->find('count', array( + 'recursive' => -1, + 'conditions' => array( + 'is_active' => true, + 'key' => $registration['Registration']['key'] + ) + )); + } else { + $isPublished = 0; + } + return $isPublished; + } + +/** + * clearRegistrationId 登録フォームデータからIDのみをクリアする + * + * @param array &$registration 登録フォームデータ + * @return void + */ + public function clearRegistrationId(&$registration) { + foreach ($registration as $qKey => $q) { + if (is_array($q)) { + $this->clearRegistrationId($registration[$qKey]); + } elseif (preg_match('/^id$/', $qKey) || + preg_match('/^key$/', $qKey) || + preg_match('/^created(.*?)/', $qKey) || + preg_match('/^modified(.*?)/', $qKey)) { + unset($registration[$qKey]); + } + } + } +} diff --git a/Model/RegistrationAnswer.php b/Model/RegistrationAnswer.php new file mode 100644 index 0000000..90d311f --- /dev/null +++ b/Model/RegistrationAnswer.php @@ -0,0 +1,218 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationAnswer Model + */ +class RegistrationAnswer extends RegistrationsAppModel { + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'Registrations.RegistrationAnswerSingleChoice', + 'Registrations.RegistrationAnswerMultipleChoice', + 'Registrations.RegistrationAnswerSingleList', + 'Registrations.RegistrationAnswerTextArea', + 'Registrations.RegistrationAnswerText', + 'Registrations.RegistrationAnswerMatrixSingleChoice', + 'Registrations.RegistrationAnswerMatrixMultipleChoice', + 'Registrations.RegistrationAnswerDatetime', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'RegistrationChoice' => array( + 'className' => 'Registrations.RegistrationChoice', + 'foreignKey' => false, + 'conditions' => 'RegistrationAnswer.matrix_choice_key=RegistrationChoice.key', + 'fields' => '', + 'order' => '' + ), + 'RegistrationAnswerSummary' => array( + 'className' => 'Registrations.RegistrationAnswerSummary', + 'foreignKey' => 'registration_answer_summary_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'RegistrationQuestion' => array( + 'className' => 'Registrations.RegistrationQuestion', + 'foreignKey' => false, + 'conditions' => 'RegistrationAnswer.registration_question_key=RegistrationQuestion.key', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + // option情報取り出し + $summaryId = $options['registration_answer_summary_id']; + $this->data['RegistrationAnswer']['registration_answer_summary_id'] = $summaryId; + $question = $options['question']; + $allAnswers = $options['allAnswers']; + + // Answerモデルは繰り返し判定が行われる可能性高いのでvalidateルールは最初に初期化 + // mergeはしません + $this->validate = array( + 'registration_answer_summary_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + 'allowEmpty' => true, + //'required' => false, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + 'registration_question_key' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + //'message' => 'Your custom message here', + 'allowEmpty' => false, + 'required' => true, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + 'answer_value' => array( + 'answerRequire' => array( + 'rule' => array('answerRequire', $question), + 'message' => __d('registrations', 'Input required'), + ), + 'answerMaxLength' => array( + 'rule' => array('answerMaxLength', $question, RegistrationsComponent::REGISTRATION_MAX_ANSWER_LENGTH), + 'message' => sprintf(__d('registrations', 'the answer is too long. Please enter under %d letters.', RegistrationsComponent::REGISTRATION_MAX_ANSWER_LENGTH)), + ), + 'answerValidation' => array( + 'rule' => array('answerValidation', $question, $allAnswers), + 'last' => true, + 'message' => '' + ), + ), + ); + parent::beforeValidate($options); + + return true; + } + +/** + * getProgressiveAnswerOfThisSummary + * + * @param array $summary registration summary ( one record ) + * @return array + */ + public function getProgressiveAnswerOfThisSummary($summary) { + $answers = array(); + if (empty($summary)) { + return $answers; + } + $answer = $this->find('all', array( + 'conditions' => array( + 'registration_answer_summary_id' => $summary['RegistrationAnswerSummary']['id'] + ), + 'recursive' => -1 + )); + if (!empty($answer)) { + foreach ($answer as $ans) { + $answers[$ans['RegistrationAnswer']['registration_question_key']][] = $ans['RegistrationAnswer']; + } + } + return $answers; + } +/** + * getAnswerCount + * It returns the number of responses in accordance with the conditions + * + * @param array $conditions conditions + * @return int + */ + public function getAnswerCount($conditions) { + $cnt = $this->find('count', array( + 'conditions' => $conditions, + )); + return $cnt; + } + +/** + * saveAnswer + * save the answer data + * + * @param array $data Postされた回答データ + * @param array $registration registration data + * @param array $summary answer summary data + * @throws $ex + * @return bool + */ + public function saveAnswer($data, $registration, $summary) { + //トランザクションBegin + $this->begin(); + try { + $summaryId = $summary['RegistrationAnswerSummary']['id']; + // 繰り返しValidationを行うときは、こうやってエラーメッセージを蓄積するところ作らねばならない + // 仕方ないCakeでModelObjectを使う限りは + $validationErrors = array(); + foreach ($data['RegistrationAnswer'] as $answer) { + $targetQuestionKey = $answer[0]['registration_question_key']; + $targetQuestion = Hash::extract($registration['RegistrationPage'], '{n}.RegistrationQuestion.{n}[key=' . $targetQuestionKey . ']'); + // データ保存 + // Matrixタイプの場合はanswerが配列になっているがsaveでかまわない + $this->oneTimeValidateFlag = false; // saveMany中で1回しかValidateしなくてよい関数のためのフラグ + if (!$this->saveMany($answer, array( + 'registration_answer_summary_id' => $summaryId, + 'question' => $targetQuestion[0], + 'allAnswers' => $data['RegistrationAnswer']))) { + $validationErrors[$targetQuestionKey] = Hash::filter($this->validationErrors); + } + } + if (! empty($validationErrors)) { + $this->validationErrors = Hash::filter($validationErrors); + $this->rollback(); + return false; + } + $this->commit(); + } catch (Exception $ex) { + $this->rollback(); + CakeLog::error($ex); + throw $ex; + } + return true; + } +} \ No newline at end of file diff --git a/Model/RegistrationAnswerSummary.php b/Model/RegistrationAnswerSummary.php new file mode 100644 index 0000000..62a063a --- /dev/null +++ b/Model/RegistrationAnswerSummary.php @@ -0,0 +1,275 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationAnswerSummary Model + */ +class RegistrationAnswerSummary extends RegistrationsAppModel { + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + 'registration_key' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + //'message' => 'Your custom message here', + 'allowEmpty' => false, + 'required' => true, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'Registration' => array( + 'className' => 'Registrations.Registration', + 'foreignKey' => 'registration_key', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'User' => array( + 'className' => 'Users.User', + 'foreignKey' => 'user_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'RegistrationAnswer' => array( + 'className' => 'Registrations.RegistrationAnswer', + 'foreignKey' => 'registration_answer_summary_id', + 'dependent' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +/** + * getNowSummaryOfThisUser 指定された登録フォームIDと指定ユーザーに合致する登録フォーム回答を取得する + * + * @param int $registrationKey 登録フォームKey + * @param int $userId ユーザID (指定しない場合は null) + * @param string $sessionId セッションID + * @return array + */ + public function getNowSummaryOfThisUser($registrationKey, $userId, $sessionId) { + if ($userId) { + $conditions = array( + 'answer_status' => RegistrationsComponent::ACTION_ACT, + 'registration_key' => $registrationKey, + 'user_id' => $userId + ); + } else { + $conditions = array( + 'answer_status' => RegistrationsComponent::ACTION_ACT, + 'registration_key' => $registrationKey, + 'session_value' => $sessionId + ); + } + + $summary = $this->find('all', array( + 'conditions' => $conditions + )); + + return $summary; + } + +/** + * forceGetProgressiveAnswerSummary + * get answer summary record if there is no summary , then create + * + * @param array $registration registration + * @param int $userId user id + * @param string $sessionId session id + * @throws $ex + * @return array summary + */ + public function forceGetProgressiveAnswerSummary($registration, $userId, $sessionId) { + $this->begin(); + try { + $this->create(); + if (! $this->save(array( + 'answer_status' => RegistrationsComponent::ACTION_NOT_ACT, + 'test_status' => ($registration['Registration']['status'] != WorkflowComponent::STATUS_PUBLISHED) ? RegistrationsComponent::TEST_ANSWER_STATUS_TEST : RegistrationsComponent::TEST_ANSWER_STATUS_PEFORM, + 'answer_number' => 1, + 'registration_key' => $registration['Registration']['key'], + 'session_value' => $sessionId, + 'user_id' => $userId, + ))) { + $this->rollback(); + return false; + } + //$summary = array(); + //$summary['RegistrationAnswerSummary']['id'] = $this->id; + //return $summary; + $this->commit(); + } catch (Exception $ex) { + $this->rollback(); + CakeLog::error($ex); + throw $ex; + } + $summary = $this->findById($this->id); + return $summary; + } + +/** + * getResultCondition + * + * @param int $registration Registration + * @return array + */ + public function getResultCondition($registration) { + // 指定された登録フォームを集計するときのサマリ側の条件を返す + $baseConditions = array( + 'RegistrationAnswerSummary.answer_status' => RegistrationsComponent::ACTION_ACT, + 'RegistrationAnswerSummary.registration_key' => $registration['Registration']['key'] + ); + //公開時は本番時回答のみ、テスト時(=非公開時)は本番回答+テスト回答を対象とする。 + if ($registration['Registration']['status'] == WorkflowComponent::STATUS_PUBLISHED) { + $baseConditions['RegistrationAnswerSummary.test_status'] = RegistrationsComponent::TEST_ANSWER_STATUS_PEFORM; + } + return $baseConditions; + } + +/** + * getAggrigates + * 集計処理の実施 + * + * @param array $registration 登録フォーム情報 + * @return void + */ + public function getAggregate($registration) { + $this->RegistrationAnswer = ClassRegistry::init('Registrations.RegistrationAnswer', true); + // 質問データのとりまとめ + //$questionsは、registration_question_keyをキーとし、registration_question配下が代入されている。 + $questions = Hash::combine($registration, + 'RegistrationPage.{n}.RegistrationQuestion.{n}.key', + 'RegistrationPage.{n}.RegistrationQuestion.{n}'); + + // 集計データを集める際の基本条件 + $baseConditions = $this->getResultCondition($registration); + + //質問毎に集計 + foreach ($questions as &$question) { + if ($question['is_result_display'] != RegistrationsComponent::EXPRESSION_SHOW) { + //集計表示をしない、なので飛ばす + continue; + } + // 戻り値の、この質問の合計回答数を記録しておく。 + // skip ロジックがあるため、単純にsummaryのcountじゃない.. + $questionConditions = $baseConditions + array( + 'RegistrationAnswer.registration_question_key' => $question['key'], + ); + $question['answer_total_cnt'] = $this->RegistrationAnswer->getAnswerCount($questionConditions); + + if (RegistrationsComponent::isMatrixInputType($question['question_type'])) { + $this->__aggregateAnswerForMatrix($question, $questionConditions); + } else { + $this->__aggregateAnswerForNotMatrix($question, $questionConditions); + } + } + return $questions; + } + +/** + * __aggregateAnswerForMatrix + * matrix aggregate + * + * @param array &$question 登録フォーム質問(集計結果を配列追加して返します) + * @param array $questionConditions get aggregate base condition + * @return void + */ + private function __aggregateAnswerForMatrix(&$question, $questionConditions) { + $rowCnt = 0; + $cols = Hash::extract($question['RegistrationChoice'], '{n}[matrix_type=' . RegistrationsComponent::MATRIX_TYPE_COLUMN . ']'); + foreach ($question['RegistrationChoice'] as &$c) { + if ($c['matrix_type'] == RegistrationsComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX) { + foreach ($cols as $col) { + $conditions = $questionConditions + array( + 'RegistrationAnswer.matrix_choice_key' => $c['key'], + 'RegistrationAnswer.answer_value LIKE ' => '%' . RegistrationsComponent::ANSWER_DELIMITER . $col['key'] . RegistrationsComponent::ANSWER_VALUE_DELIMITER . '%', + ); + $cnt = $this->RegistrationAnswer->getAnswerCount($conditions); + $c['aggregate_total'][$col['key']] = $cnt; + } + $rowCnt++; + } + } + $question['answer_total_cnt'] /= $rowCnt; + } + +/** + * __aggregateAnswerForNotMatrix + * not matrix aggregate + * + * @param array &$question 登録フォーム質問(集計結果を配列追加して返します) + * @param array $questionConditions get aggregate base condition + * @return void + */ + private function __aggregateAnswerForNotMatrix(&$question, $questionConditions) { + foreach ($question['RegistrationChoice'] as &$c) { + $conditions = $questionConditions + array( + 'RegistrationAnswer.answer_value LIKE ' => '%' . RegistrationsComponent::ANSWER_DELIMITER . $c['key'] . RegistrationsComponent::ANSWER_VALUE_DELIMITER . '%', + ); + $cnt = $this->RegistrationAnswer->getAnswerCount($conditions); + $c['aggregate_total']['aggregate_not_matrix'] = $cnt; + } + } + +/** + * deleteTestAnswerSummary + * when registration is published, delete test answer summary + * + * @param int $key registration key + * @param int $status publish status + * @return bool + */ + public function deleteTestAnswerSummary($key, $status) { + if ($status != WorkflowComponent::STATUS_PUBLISHED) { + return true; + } + $this->deleteAll(array( + 'registration_key' => $key, + 'test_status' => RegistrationsComponent::TEST_ANSWER_STATUS_TEST), true); + return true; + } + +} diff --git a/Model/RegistrationAnswerSummaryCsv.php b/Model/RegistrationAnswerSummaryCsv.php new file mode 100644 index 0000000..bc0c371 --- /dev/null +++ b/Model/RegistrationAnswerSummaryCsv.php @@ -0,0 +1,278 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationAnswerSummary Model + */ +class RegistrationAnswerSummaryCsv extends RegistrationsAppModel { + +/** + * use table + * + * @var array + */ + public $useTable = 'registration_answer_summaries'; + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.Trackable', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + ); + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + ); + +/** + * getRegistrationForAnswerCsv + * + * @param int $registrationKey registration key + * @return array registration data + */ + public function getRegistrationForAnswerCsv($registrationKey) { + $this->Registration = ClassRegistry::init('Registrations.Registration', true); + // 指定の登録フォームデータを取得 + $registration = $this->Registration->find('first', array( + 'conditions' => array( + 'Registration.key' => $registrationKey, + 'Registration.is_active' => true, + ), + 'recursive' => -1 + )); + return $registration; + } + +/** + * getAnswerSummaryCsv + * + * @param array $registration registration data + * @param int $limit record limit + * @param int $offset offset + * @return array + */ + public function getAnswerSummaryCsv($registration, $limit, $offset) { + $this->RegistrationAnswer = ClassRegistry::init('Registrations.RegistrationAnswer', true); + + // 指定された登録フォームの回答データをCsvに出力しやすい行形式で返す + $retArray = array(); + + // $offset == 0 のときのみヘッダ行を出す + if ($offset == 0) { + $retArray[] = $this->_putHeader($registration); + } + + // $registrationにはページデータ、質問データが入っていることを前提とする + + // 登録フォームのkeyを取得 + $key = $registration['Registration']['key']; + + // keyに一致するsummaryを取得(テストじゃない、完了している) + $summaries = $this->find('all', array( + 'conditions' => array( + 'answer_status' => RegistrationsComponent::ACTION_ACT, + 'test_status' => RegistrationsComponent::TEST_ANSWER_STATUS_PEFORM, + 'registration_key' => $key, + ), + 'limit' => $limit, + 'offset' => $offset, + 'order' => 'RegistrationAnswerSummaryCsv.created', + )); + if (empty($summaries)) { + return $retArray; + } + + // summary loop + foreach ($summaries as $summary) { + //$answers = $summary['RegistrationAnswer']; + // 何回もSQLを発行するのは無駄かなと思いつつも + // RegistrationAnswerに回答データの取り扱いしやすい形への整備機能を組み込んであるので、それを利用したかった + // このクラスからでも利用できないかと試みたが + // AnswerとQuestionがJOINされた形でFindしないと整備機能が発動しない + // そうするためにはrecursive=2でないといけないわけだが、recursive=2にするとRoleのFindでSQLエラーになる + // 仕方ないのでこの形式で処理を行う + $answers = $this->RegistrationAnswer->find('all', array( + 'conditions' => array( + 'registration_answer_summary_id' => $summary[$this->alias]['id'] + ), + )); + $retArray[] = $this->_getRows($registration, $summary, $answers); + } + + return $retArray; + } + +/** + * _putHeader + * + * @param array $registration registration data + * @return array + */ + protected function _putHeader($registration) { + $cols = array(); + + // "回答者","回答日","回数" + $cols[] = __d('registrations', 'Respondent'); + $cols[] = __d('registrations', 'Answer Date'); + $cols[] = __d('registrations', 'Number'); + + foreach ($registration['RegistrationPage'] as $page) { + foreach ($page['RegistrationQuestion'] as $question) { + if (RegistrationsComponent::isMatrixInputType($question['question_type'])) { + $choiceSeq = 1; + foreach ($question['RegistrationChoice'] as $choice) { + if ($choice['matrix_type'] == RegistrationsComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX) { + $cols[] = $page['page_sequence'] . '-' . $question['question_sequence'] . '-' . $choiceSeq++ . '. ' . $choice['choice_label']; + } + } + } else { + $cols[] = $page['page_sequence'] . '-' . $question['question_sequence'] . '. ' . $question['question_value']; + } + } + } + return $cols; + } + +/** + * _getRow + * + * @param array $registration registration data + * @param array $summary answer summary + * @param array $answers answer data + * @return array + */ + protected function _getRows($registration, $summary, $answers) { + // ページ、質問のループから、取り出すべき質問のIDを順番に取り出す + // question loop + // 返却用配列にquestionのIDにマッチするAnswerを配列要素として追加、Answerがないときは空文字 + // なお選択肢系のものはchoice_idが回答にくっついているのでそれを削除する + // MatrixのものはMatrixの行数分返却行の列を加える + // その他の選択肢の場合は、入力されたその他のテキストを入れる + + $cols = array(); + + $cols[] = ($registration['Registration']['is_anonymity']) ? __d('registrations', 'Anonymity') : $summary['TrackableCreator']['username']; + $cols[] = $summary['RegistrationAnswerSummaryCsv']['modified']; + $cols[] = $summary['RegistrationAnswerSummaryCsv']['answer_number']; + + foreach ($registration['RegistrationPage'] as $page) { + foreach ($page['RegistrationQuestion'] as $question) { + if (RegistrationsComponent::isMatrixInputType($question['question_type'])) { + foreach ($question['RegistrationChoice'] as $choice) { + if ($choice['matrix_type'] == RegistrationsComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX) { + $cols[] = $this->_getMatrixAns($question, $choice, $answers); + } + } + } else { + $cols[] = $this->_getAns($question, $answers); + } + } + } + return $cols; + } + +/** + * _getAns + * + * @param array $question question data + * @param array $answers answer data + * @return string + */ + protected function _getAns($question, $answers) { + $retAns = ''; + // 回答配列データの中から、現在指定された質問に該当するものを取り出す + $ans = Hash::extract($answers, '{n}.RegistrationAnswer[registration_question_key=' . $question['key'] . ']'); + // 回答が存在するとき処理 + if ($ans) { + $ans = $ans[0]; + // 単純入力タイプのときは回答の値をそのまま返す + if (RegistrationsComponent::isOnlyInputType($question['question_type'])) { + $retAns = $ans['answer_value']; + } elseif (RegistrationsComponent::isSelectionInputType($question['question_type'])) { + // choice_id と choice_valueに分けられた回答選択肢配列を得る + // 選択されていた数分処理 + foreach ($ans['answer_values'] as $choiceKey => $dividedAns) { + // idから判断して、その他が選ばれていた場合、other_answer_valueを入れる + $choice = Hash::extract($question['RegistrationChoice'], '{n}[key=' . $choiceKey . ']'); + if ($choice) { + if ($choice[0]['other_choice_type'] != RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED) { + $retAns .= $ans['other_answer_value']; + } else { + $retAns .= $dividedAns; + } + $retAns .= RegistrationsComponent::ANSWER_DELIMITER; + } + } + $retAns = trim($retAns, RegistrationsComponent::ANSWER_DELIMITER); + } + } + return $retAns; + } + +/** + * _getMatrixAns + * + * @param array $question question data + * @param array $choice question choice data + * @param array $answers answer data + * @return string + */ + protected function _getMatrixAns($question, $choice, $answers) { + $retAns = ''; + // 回答配列データの中から、現在指定された質問に該当するものを取り出す + // マトリクスタイプのときは複数存在する(行数分) + $anss = Hash::extract($answers, '{n}.RegistrationAnswer[registration_question_key=' . $question['key'] . ']'); + if (empty($anss)) { + return $retAns; + } + // その中かから現在指定された選択肢行に該当するものを取り出す + $ans = Hash::extract($anss, '{n}[matrix_choice_key=' . $choice['key'] . ']'); + // 回答が存在するとき処理 + if ($ans) { + $ans = $ans[0]; + // idから判断して、その他が選ばれていた場合、other_answer_valueを入れる + if ($choice['other_choice_type'] != RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED) { + $retAns = $ans['other_answer_value'] . RegistrationsComponent::ANSWER_VALUE_DELIMITER; + } + $retAns = implode(RegistrationsComponent::ANSWER_DELIMITER, $ans['answer_values']); + } + return $retAns; + } +} diff --git a/Model/RegistrationChoice.php b/Model/RegistrationChoice.php new file mode 100644 index 0000000..1a72b4e --- /dev/null +++ b/Model/RegistrationChoice.php @@ -0,0 +1,199 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationChoice Model + */ +class RegistrationChoice extends RegistrationsAppModel { + +/** + * default graph colors + * 基本的にはJSで新しい選択肢を作成するので、これと同じ色配列がJSファイルにも書いてあります + * + * @var string + */ + static public $defaultGraphColors = array('#f38631', '#e0e4cd', '#69d2e7', '#68e2a7', '#f64649', + '#4d5361', '#47bfbd', '#7c4f6c', '#23313c', '#9c9b7f', '#be5945', '#cccccc'); + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.OriginalKey', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'RegistrationQuestion' => array( + 'className' => 'Registrations.RegistrationQuestion', + 'foreignKey' => 'registration_question_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + */ + public function beforeValidate($options = array()) { + $choiceIndex = $options['choiceIndex']; + // Choiceモデルは繰り返し判定が行われる可能性高いのでvalidateルールは最初に初期化 + // mergeはしません + $this->validate = array( + 'choice_label' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + 'message' => __d('registrations', 'Please input choice text.'), + ), + 'choiceLabel' => array( + 'rule' => array('custom', '/^(?!.*[\|\:]).*$/'), + 'message' => __d('registrations', 'You can not use the character of |, : for choice text '), + ), + ), + 'other_choice_type' => array( + 'numeric' => array( + 'rule' => array('numeric'), + 'message' => __d('net_commons', 'Invalid request.'), + //'allowEmpty' => false, + //'required' => false, + ), + ), + 'choice_sequence' => array( + 'numeric' => array( + 'rule' => array('numeric'), + ), + 'comparison' => array( + 'rule' => array('comparison', '==', $choiceIndex), + 'message' => __d('registrations', 'choice sequence is illegal.') + ), + ), + 'graph_color' => array( + 'rule' => '/^#[a-f0-9]{6}$/i', + 'message' => __d('registrations', 'First character is "#". And input the hexadecimal numbers by six digits.'), + //'allowEmpty' => false, + //'required' => false, + ), + ); + // ウィザード画面でのセットアップ中の場合はまだ親ページIDの正当性についてのチェックは行わない + if (! (isset($options['validate']) && $options['validate'] == RegistrationsComponent::REGISTRATION_VALIDATE_TYPE)) { + $this->validate = Hash::merge($this->validate, array( + 'registration_question_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + )); + } + $this->_checkSkip($options['isSkip'], $options['pageIndex'], $options['maxPageIndex']); + + return parent::beforeValidate($options); + } +/** + * getDefaultChoice + * get default data of registration choice + * + * @return array + */ + public function getDefaultChoice() { + return array( + 'choice_sequence' => 0, + 'matrix_type' => RegistrationsComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX, + 'choice_label' => __d('registrations', 'new choice') . '1', + 'other_choice_type' => RegistrationsComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED, + 'graph_color' => self::$defaultGraphColors[0], + 'skip_page_sequence' => RegistrationsComponent::SKIP_GO_TO_END + ); + } + +/** + * saveRegistrationChoice + * save RegistrationChoice data + * + * @param array &$choices registration choices + * @throws InternalErrorException + * @return bool + */ + public function saveRegistrationChoice(&$choices) { + // RegistrationChoiceが単独でSaveされることはない + // 必ず上位のRegistrationのSaveの折に呼び出される + // なので、$this->setDataSource('master');といった + // 決まり処理は上位で行われる + // ここでは行わない + foreach ($choices as &$choice) { + // 登録フォームは履歴を取っていくタイプのコンテンツデータなのでSave前にはID項目はカット + // (そうしないと既存レコードのUPDATEになってしまうから) + $choice = Hash::remove($choice, 'RegistrationChoice.id'); + $this->create(); + if (!$this->save($choice, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + } + return true; + } + +/** + * _checkSkip + * + * @param bool $isSkip スキップ有無 + * @param int $pageIndex ページ番号 + * @param int $maxPageIndex この登録フォームでの最後のページ番号 + * @return void + */ + protected function _checkSkip($isSkip, $pageIndex, $maxPageIndex) { + if ($isSkip != RegistrationsComponent::SKIP_FLAGS_SKIP) { + return; + } + // 質問がスキップ質問である場合 + // 未設定時はデフォルトの次ページ移動となります + if (! isset($this->data['RegistrationChoice']['skip_page_sequence'])) { + $this->data['RegistrationChoice']['skip_page_sequence'] = $pageIndex + 1; + } + // 最後ページへの指定ではない場合 + if ($this->data['RegistrationChoice']['skip_page_sequence'] != RegistrationsComponent::SKIP_GO_TO_END) { + // そのジャンプ先は現在ページから戻っていないか + if ($this->data['RegistrationChoice']['skip_page_sequence'] <= $pageIndex) { + $this->validationErrors['skip_page_sequence'][] = __d('registrations', 'Invalid skip page. Please set forward page.'); + } + // そのジャンプ先は存在するページシーケンスか + if ($this->data['RegistrationChoice']['skip_page_sequence'] > $maxPageIndex) { + $this->validationErrors['skip_page_sequence'][] = __d('registrations', 'Invalid skip page. page does not exist.'); + } + } + } + +} \ No newline at end of file diff --git a/Model/RegistrationExport.php b/Model/RegistrationExport.php new file mode 100644 index 0000000..605223a --- /dev/null +++ b/Model/RegistrationExport.php @@ -0,0 +1,132 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); +App::uses('WysIsWygDownloader', 'Registrations.Utility'); + +/** + * Summary for Registration Model + */ +class RegistrationExport extends RegistrationsAppModel { + +/** + * Use table config + * + * @var bool + */ + public $useTable = 'registrations'; + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'AuthorizationKeys.AuthorizationKey', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array(); + +/** + * getExportData + * + * @param string $registrationKey 登録フォームキー + * @return array RegistrationData for Export + */ + public function getExportData($registrationKey) { + // 登録フォームデータをjsonにして記述した内容を含むZIPファイルを作成する + $zipData = array(); + + // バージョン情報を取得するためComposer情報を得る + $Plugin = ClassRegistry::init('Plugins.Plugin'); + $composer = $Plugin->getComposer('netcommons/registrations'); + // 最初のデータは登録フォームプラグインのバージョン + $zipData['version'] = $composer['version']; + + // 言語数分 + $Language = ClassRegistry::init('Languages.Language'); + $languages = $Language->find('all', array( + 'recursive' => -1 + )); + $Registration = ClassRegistry::init('Registrations.Registration'); + $registrations = array(); + foreach ($languages as $lang) { + // 指定の登録フォームデータを取得 + $registration = $Registration->find('first', array( + 'conditions' => array( + 'Registration.key' => $registrationKey, + 'Registration.is_active' => true, + 'Registration.is_latest' => true, + 'Registration.language_id' => $lang['Language']['id'] + ), + 'recursive' => 0 + )); + // 指定の言語データがない場合もあることを想定 + if (empty($registration)) { + continue; + } + $registration = Hash::remove($registration, 'Block'); + $registration = Hash::remove($registration, 'TrackableCreator'); + $registration = Hash::remove($registration, 'TrackableUpdater'); + $Registration->clearRegistrationId($registration); + $registrations[] = $registration; + } + $zipData['Registrations'] = $registrations; + return $zipData; + } +/** + * putToZip + * + * @param ZipDownloader $zipFile ZIPファイルオブジェクト + * @param array $zipData zip data + * @return void + */ + public function putToZip($zipFile, $zipData) { + $this->Registration = ClassRegistry::init('Registrations.Registration'); + $this->RegistrationPage = ClassRegistry::init('Registrations.RegistrationPage'); + $this->RegistrationQuestion = ClassRegistry::init('Registrations.RegistrationQuestion'); + + $wysiswyg = new WysIsWygDownloader(); + + // 登録フォームデータの中でもWYSISWYGデータのものについては + // フォルダ別に確保(フォルダの中にZIPがある) + $flatRegistration = Hash::flatten($zipData); + foreach ($flatRegistration as $key => &$value) { + $model = null; + if (strpos($key, 'RegistrationQuestion.') !== false) { + $model = $this->RegistrationQuestion; + } elseif (strpos($key, 'RegistrationPage.') !== false) { + $model = $this->RegistrationPage; + } elseif (strpos($key, 'Registration.') !== false) { + $model = $this->Registration; + } + if (!$model) { + continue; + } + $columnName = substr($key, strrpos($key, '.') + 1); + if ($model->hasField($columnName)) { + if ($model->getColumnType($columnName) == 'text') { + $wysiswygZipFile = $wysiswyg->createWysIsWygZIP($model->alias . '.' . $columnName, $value); + $wysiswygFileName = $key . '.zip'; + $zipFile->addFile($wysiswygZipFile, $wysiswygFileName); + $value = $wysiswygFileName; + } + } + } + $registration = Hash::expand($flatRegistration); + // jsonデータにして書き込み + $zipFile->addFromString(RegistrationsComponent::REGISTRATION_JSON_FILENAME, json_encode($registration)); + } +} diff --git a/Model/RegistrationFrameDisplayRegistration.php b/Model/RegistrationFrameDisplayRegistration.php new file mode 100644 index 0000000..b40590d --- /dev/null +++ b/Model/RegistrationFrameDisplayRegistration.php @@ -0,0 +1,220 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationFrameDisplayRegistration Model + */ +class RegistrationFrameDisplayRegistration extends RegistrationsAppModel { + +/** + * Validation rules + * + * @var array + */ + public $validate = array(); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'Frame' => array( + 'className' => 'Frames.Frame', + 'foreignKey' => 'frame_key', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'Registration' => array( + 'className' => 'Registrations.Registration', + 'foreignKey' => 'registration_key', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + $this->validate = Hash::merge($this->validate, array( + 'registration_key' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + 'message' => __d('net_commons', 'Invalid request.'), + 'allowEmpty' => false, + 'required' => true, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + )); + parent::beforeValidate($options); + + return true; + } + +/** + * validateFrameDisplayRegistration + * + * @param mix $data PostData + * @return bool + */ + public function validateFrameDisplayRegistration($data) { + if ($data['RegistrationFrameSetting']['display_type'] == RegistrationsComponent::DISPLAY_TYPE_SINGLE) { + $saveData = Hash::extract($data, 'Single.RegistrationFrameDisplayRegistrations'); + $this->set($saveData); + $ret = $this->validates(); + } else { + $saveData = $data['RegistrationFrameDisplayRegistrations']; + $ret = $this->saveAll($saveData, array('validate' => 'only')); + } + return $ret; + } +/** + * saveFrameDisplayRegistration + * this function is called when save registration + * + * @param mix $data PostData + * @return bool + */ + public function saveFrameDisplayRegistration($data) { + //トランザクションは親元のRegistrationFrameSettingでやっているので不要 + if ($data['RegistrationFrameSetting']['display_type'] == RegistrationsComponent::DISPLAY_TYPE_SINGLE) { + // このフレームに設定されている全てのレコードを消す + // POSTされた登録フォームのレコードのみ作成する + $ret = $this->saveDisplayRegistrationForSingle($data); + } else { + // hiddenでPOSTされたレコードについて全て処理する + // POSTのis_displayが0,1によってdeleteかinsertで処理する + $ret = $this->saveDisplayRegistrationForList($data); + } + return $ret; + } + +/** + * saveDisplayRegistrationForList + * + * @param mix $data PostData + * @return bool + */ + public function saveDisplayRegistrationForList($data) { + $frameKey = Current::read('Frame.key'); + + foreach ($data['RegistrationFrameDisplayRegistrations'] as $index => $value) { + $registrationKey = $value['registration_key']; + $isDisplay = $data['List']['RegistrationFrameDisplayRegistrations'][$index]['is_display']; + $saveQs = array( + 'frame_key' => $frameKey, + 'registration_key' => $registrationKey + ); + if ($isDisplay != 0) { + if (!$this->saveDisplayRegistration($saveQs)) { + return false; + } + } else { + if (!$this->deleteAll($saveQs, false)) { + return false; + } + } + } + if (!$this->updateFrameDefaultAction("''")) { + return false; + } + return true; + } + +/** + * saveDisplayRegistrationForSingle + * + * @param mix $data PostData + * @return bool + */ + public function saveDisplayRegistrationForSingle($data) { + $frameKey = Current::read('Frame.key'); + $deleteQs = array( + 'frame_key' => $frameKey, + ); + $this->deleteAll($deleteQs, false); + + $saveData = Hash::extract($data, 'Single.RegistrationFrameDisplayRegistrations'); + $saveData['frame_key'] = $frameKey; + if (!$this->saveDisplayRegistration($saveData)) { + return false; + } + $action = "'" . 'registration_answers/view/' . Current::read('Block.id') . '/' . $saveData['registration_key'] . "'"; + if (!$this->updateFrameDefaultAction($action)) { + return false; + } + return true; + } + +/** + * saveDisplayRegistration + * saveRegistrationFrameDisplayRegistration + * + * @param array $data save data + * @return bool + */ + public function saveDisplayRegistration($data) { + // 該当データを検索して + $displayRegistration = $this->find('first', array( + 'conditions' => $data + )); + if (! empty($displayRegistration)) { + // あるならもう作らない + return true; + } + $this->create(); + if (!$this->save($data)) { + return false; + } + return true; + } +/** + * updateFrameDefaultAction + * update Frame default_action + * + * @param string $action default_action + * @return bool + */ + public function updateFrameDefaultAction($action) { + // frameのdefault_actionを変更しておく + $this->loadModels([ + 'Frame' => 'Frames.Frame', + ]); + $conditions = array( + 'Frame.key' => Current::read('Frame.key') + ); + $frameData = array( + 'default_action' => $action + ); + if (! $this->Frame->updateAll($frameData, $conditions)) { + return false; + } + return true; + } +} diff --git a/Model/RegistrationFrameSetting.php b/Model/RegistrationFrameSetting.php new file mode 100644 index 0000000..3ad6abc --- /dev/null +++ b/Model/RegistrationFrameSetting.php @@ -0,0 +1,218 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationFrameSetting Model + */ +class RegistrationFrameSetting extends RegistrationsAppModel { + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'Frame' => array( + 'className' => 'Frames.Frame', + 'foreignKey' => 'frame_key', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + $this->validate = Hash::merge($this->validate, array( + 'frame_key' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + //'message' => 'Your custom message here', + 'allowEmpty' => false, + //'required' => false, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + 'display_type' => array( + 'inList' => array( + 'rule' => array('inList', array(RegistrationsComponent::DISPLAY_TYPE_SINGLE, RegistrationsComponent::DISPLAY_TYPE_LIST)), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'display_num_per_page' => array( + 'inList' => array( + 'rule' => array('inList', array_keys(RegistrationsComponent::getDisplayNumberOptions())), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'sort_type' => array( + 'inList' => array( + 'rule' => array('inList', array_keys(RegistrationsComponent::getSortOrders())), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + )); + + parent::beforeValidate($options); + + return true; + } + +/** + * getRegistrationFrameSettingConditions 指定されたframe_keyの設定要件をSQL検索用の配列で取り出す + * + * @param string $frameKey frame key + * @return array ... displayNum sortField sortDirection + */ + public function getRegistrationFrameSettingConditions($frameKey) { + list(, $limit, $sort, $dir) = $this->getRegistrationFrameSetting($frameKey); + return array( + 'offset' => 0, + 'limit' => $limit, + 'order' => 'Registration.' . $sort . ' ' . $dir); + } +/** + * getFrameSetting 指定されたframe_keyの設定要件を取り出す + * + * @param string $frameKey frame key + * @return array ... displayNum sortField sortDirection + */ + public function getRegistrationFrameSetting($frameKey) { + $frameSetting = $this->find('first', array( + 'conditions' => array( + 'frame_key' => $frameKey + ), + 'recursive' => -1 + )); + // 指定されたフレーム設定が存在しない場合 + if (! $frameSetting) { + // とりあえずデフォルトの表示設定を返す + // しかし、表示対象登録フォームが設定されていないわけなので、空っぽの一覧表示となる + $frameSetting = $this->getDefaultFrameSetting(); + } + + $setting = $frameSetting['RegistrationFrameSetting']; + $displayType = $setting['display_type']; + $displayNum = $setting['display_num_per_page']; + if ($setting['sort_type'] == RegistrationsComponent::REGISTRATION_SORT_MODIFIED) { + $sort = 'modified'; + $dir = 'DESC'; + } elseif ($setting['sort_type'] == RegistrationsComponent::REGISTRATION_SORT_CREATED) { + $sort = 'created'; + $dir = 'ASC'; + } elseif ($setting['sort_type'] == RegistrationsComponent::REGISTRATION_SORT_TITLE) { + $sort = 'title'; + $dir = 'ASC'; + } elseif ($setting['sort_type'] == RegistrationsComponent::REGISTRATION_SORT_END) { + $sort = 'publish_end'; + $dir = 'ASC'; + } + return array($displayType, $displayNum, $sort, $dir); + } + +/** + * getDefaultFrameSetting + * return default frame setting + * + * @return array + */ + public function getDefaultFrameSetting() { + $frame = array( + 'RegistrationFrameSetting' => array( + //'id' => '', + 'display_type' => RegistrationsComponent::DISPLAY_TYPE_LIST, + 'display_num_per_page' => RegistrationsComponent::REGISTRATION_DEFAULT_DISPLAY_NUM_PER_PAGE, + 'sort_type' => RegistrationsComponent::DISPLAY_SORT_TYPE_NEW_ARRIVALS, + ) + ); + return $frame; + } + +/** + * saveFrameSettings + * + * @param array $data save data + * @return bool + * @throws InternalErrorException + */ + public function saveFrameSettings($data) { + $this->loadModels([ + 'RegistrationFrameDisplayRegistration' => 'Registrations.RegistrationFrameDisplayRegistration', + ]); + + //トランザクションBegin + $this->begin(); + try { + // フレーム設定のバリデート + $this->create(); + $this->set($data); + if (! $this->validates()) { + return false; + } + + // フレームに表示する登録フォーム一覧設定のバリデート + // 一覧表示タイプと単独表示タイプ + if (isset($data['RegistrationFrameDisplayRegistrations'])) { + $ret = $this->RegistrationFrameDisplayRegistration->validateFrameDisplayRegistration($data); + if ($ret === false) { + return false; + } + } + // フレーム設定の登録 + if (! $this->save($data, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + // フレームに表示する登録フォーム一覧設定の登録 + // 一覧表示タイプと単独表示タイプ + if (isset($data['RegistrationFrameDisplayRegistrations'])) { + $ret = $this->RegistrationFrameDisplayRegistration->saveFrameDisplayRegistration($data); + if ($ret === false) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + } + //トランザクションCommit + $this->commit(); + } catch (Exception $ex) { + //トランザクションRollback + $this->rollback(); + CakeLog::error($ex); + throw $ex; + } + + return true; + } +} diff --git a/Model/RegistrationPage.php b/Model/RegistrationPage.php new file mode 100644 index 0000000..4099342 --- /dev/null +++ b/Model/RegistrationPage.php @@ -0,0 +1,282 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationPage Model + */ +class RegistrationPage extends RegistrationsAppModel { + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.OriginalKey', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array(); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'Registration' => array( + 'className' => 'Registrations.Registration', + 'foreignKey' => 'registration_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'RegistrationQuestion' => array( + 'className' => 'Registrations.RegistrationQuestion', + 'foreignKey' => 'registration_page_id', + 'dependent' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +/** + * getDefaultPage + * get default data of registration page + * + * @return array + */ + public function getDefaultPage() { + $this->RegistrationQuestion = ClassRegistry::init('Registrations.RegistrationQuestion', true); + + $page = array( + 'page_title' => __d('registrations', 'First Page'), + 'page_sequence' => 0, + 'key' => '', + 'route_number' => 0, + ); + $page['RegistrationQuestion'][0] = $this->RegistrationQuestion->getDefaultQuestion(); + + return $page; + } + +/** + * getNextPage + * get next answer page number + * + * @param array $registration registration + * @param int $nowPageSeq current page sequence number + * @param array $nowAnswers now answer + * + * @return array + */ + public function getNextPage($registration, $nowPageSeq, $nowAnswers) { + // 次ページはデフォルトならば+1です + $nextPageSeq = $nowPageSeq + 1; + // 回答にスキップロジックで指定されたものがないかチェックし、行き先があるならそのページ番号を返す + foreach ($nowAnswers as $answer) { + $targetQuestion = Hash::extract($registration['RegistrationPage'], '{n}.RegistrationQuestion.{n}[key=' . $answer[0]['registration_question_key'] . ']'); + if ($targetQuestion) { + $q = $targetQuestion[0]; + // skipロジック対象の質問ならば次ページのチェックを行う + if ($q['is_skip'] == RegistrationsComponent::SKIP_FLAGS_SKIP) { + $choiceIds = explode(RegistrationsComponent::ANSWER_VALUE_DELIMITER, + trim($answer[0]['answer_value'], RegistrationsComponent::ANSWER_DELIMITER)); + // スキップロジックの選択肢みつけた + $choice = Hash::extract($q['RegistrationChoice'], '{n}[key=' . $choiceIds[0] . ']'); + if ($choice) { + $c = $choice[0]; + if (!empty($c['skip_page_sequence'])) { + // スキップ先ページ + $nextPageSeq = $c['skip_page_sequence']; + break; + } + } + } + } + } + // 次ページがもしかして存在しない(つまりエンドかも) + if ($nextPageSeq == RegistrationsComponent::SKIP_GO_TO_END) { + return false; + } + // ページ情報がない?終わりにする + if (!isset($registration['RegistrationPage'])) { + return false; + } + // ページ配列はページのシーケンス番号順に取り出されているので + $pages = $registration['RegistrationPage']; + $endPage = end($pages); + if ($endPage['page_sequence'] < $nextPageSeq) { + return false; + } + return $nextPageSeq; + } +/** + * setPageToRegistration + * setup page data to registration array + * + * @param array &$registration registration data + * @return void + */ + public function setPageToRegistration(&$registration) { + $this->RegistrationQuestion = ClassRegistry::init('Registrations.RegistrationQuestion', true); + // ページデータが登録フォームデータの中にない状態でここが呼ばれている場合、 + if (!isset($registration['RegistrationPage'])) { + $pages = $this->find('all', array( + 'conditions' => array( + 'registration_id' => $registration['Registration']['id'], + ), + 'order' => array('page_sequence ASC'), + 'recursive' => -1)); + + $registration['RegistrationPage'] = Hash::combine($pages, '{n}.RegistrationPage.page_sequence', '{n}.RegistrationPage'); + } + $registration['Registration']['page_count'] = 0; + if (isset($registration['RegistrationPage'])) { + foreach ($registration['RegistrationPage'] as &$page) { + $this->RegistrationQuestion->setQuestionToPage($registration, $page); + $registration['Registration']['page_count']++; + } + } + } +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function beforeValidate($options = array()) { + $pageIndex = $options['pageIndex']; + // Pageモデルは繰り返し判定が行われる可能性高いのでvalidateルールは最初に初期化 + // mergeはしません + $this->validate = array( + 'page_sequence' => array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + //'allowEmpty' => false, + //'required' => false, + ), + 'comparison' => array( + 'rule' => array('comparison', '==', $pageIndex), + 'message' => __d('registrations', 'page sequence is illegal.') + ), + ), + 'route_number' => array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + //'allowEmpty' => false, + //'required' => false, + ), + ), + ); + // ウィザード画面でのセットアップ中の場合はまだ親登録フォームIDの正当性についてのチェックは行わない + if (! (isset($options['validate']) && $options['validate'] == RegistrationsComponent::REGISTRATION_VALIDATE_TYPE)) { + $this->validate = Hash::merge($this->validate, array( + 'registration_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + 'allowEmpty' => false, + 'required' => true, + ), + ), + )); + } + + parent::beforeValidate($options); + + // 付属の質問以下のvalidate + if (! isset($this->data['RegistrationQuestion'][0])) { + $this->validationErrors['page_sequence'][] = __d('registrations', 'please set at least one question.'); + } else { + $validationErrors = array(); + $this->RegistrationQuestion = ClassRegistry::init('Registrations.RegistrationQuestion', true); + foreach ($this->data['RegistrationQuestion'] as $qIndex => $question) { + // 質問データバリデータ + $this->RegistrationQuestion->create(); + $this->RegistrationQuestion->set($question); + $options['questionIndex'] = $qIndex; + if (! $this->RegistrationQuestion->validates($options)) { + $validationErrors['RegistrationQuestion'][$qIndex] = $this->RegistrationQuestion->validationErrors; + } + } + $this->validationErrors += $validationErrors; + } + return true; + } +/** + * saveRegistrationPage + * save RegistrationPage data + * + * @param array &$registrationPages registration pages + * @throws InternalErrorException + * @return bool + */ + public function saveRegistrationPage(&$registrationPages) { + $this->loadModels([ + 'RegistrationQuestion' => 'Registrations.RegistrationQuestion', + ]); + + // RegistrationPageが単独でSaveされることはない + // 必ず上位のRegistrationのSaveの折に呼び出される + // なので、$this->setDataSource('master');といった + // 決まり処理は上位で行われる + // ここでは行わない + + foreach ($registrationPages as &$page) { + // 登録フォームは履歴を取っていくタイプのコンテンツデータなのでSave前にはID項目はカット + // (そうしないと既存レコードのUPDATEになってしまうから) + $page = Hash::remove($page, 'RegistrationPage.id'); + $this->create(); + if (! $this->save($page, false)) { // validateは上位のregistrationで済んでいるはず + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + $pageId = $this->id; + + $page = Hash::insert($page, 'RegistrationQuestion.{n}.registration_page_id', $pageId); + // もしもQuestionやChoiceのsaveがエラーになった場合は、 + // QuestionやChoiceのほうでInternalExceptionErrorが発行されるのでここでは何も行わない + $this->RegistrationQuestion->saveRegistrationQuestion($page['RegistrationQuestion']); + } + return true; + } +} diff --git a/Model/RegistrationQuestion.php b/Model/RegistrationQuestion.php new file mode 100644 index 0000000..cdf3640 --- /dev/null +++ b/Model/RegistrationQuestion.php @@ -0,0 +1,350 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationQuestion Model + */ +class RegistrationQuestion extends RegistrationsAppModel { + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.OriginalKey', + ); + +/** + * Validation rules + * + * @var array + */ + public $validate = array(); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * belongsTo associations + * + * @var array + */ + public $belongsTo = array( + 'RegistrationPage' => array( + 'className' => 'Registrations.RegistrationPage', + 'foreignKey' => 'registration_page_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'RegistrationChoice' => array( + 'className' => 'Registrations.RegistrationChoice', + 'foreignKey' => 'registration_question_id', + 'dependent' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @see Model::save() + */ + public function beforeValidate($options = array()) { + $qIndex = $options['questionIndex']; + // Questionモデルは繰り返し判定が行われる可能性高いのでvalidateルールは最初に初期化 + // mergeはしません + $this->validate = array( + 'question_sequence' => array( + 'numeric' => array( + 'rule' => array('numeric'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + 'comparison' => array( + 'rule' => array('comparison', '==', $qIndex), + 'message' => __d('registrations', 'question sequence is illegal.') + ), + ), + 'question_type' => array( + 'inList' => array( + 'rule' => array('inList', RegistrationsComponent::$typesList), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'question_value' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + 'message' => __d('registrations', 'Please input question text.'), + ), + ), + 'is_require' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_choice_random' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_skip' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_result_display' => array( + 'inList' => array( + 'rule' => array('inList', $this->_getResultDisplayList($this->data['RegistrationQuestion']['question_type'])), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'result_display_type' => array( + 'inList' => array( + 'rule' => array('inList', RegistrationsComponent::$resultDispTypesList), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + 'is_range' => array( + 'boolean' => array( + 'rule' => array('boolean'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + ); + // 範囲制限設定された質問の場合 + if ($this->data['RegistrationQuestion']['is_range'] == true) { + $this->validate = Hash::merge($this->validate, array( + 'min' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + 'message' => __d('registrations', 'Please enter both the maximum and minimum values.'), + ), + 'comparison' => array( + 'rule' => array('comparison', '<', $this->data['RegistrationQuestion']['max']), + 'message' => __d('registrations', 'Please enter smaller value than max.') + ), + ), + 'max' => array( + 'notBlank' => array( + 'rule' => array('notBlank'), + 'message' => __d('registrations', 'Please enter both the maximum and minimum values.'), + ), + 'comparison' => array( + 'rule' => array('comparison', '>', $this->data['RegistrationQuestion']['min']), + 'message' => __d('registrations', 'Please enter bigger value than min.') + ), + ), + )); + + } + // ウィザード画面でのセットアップ中の場合はまだ親ページIDの正当性についてのチェックは行わない + if (!(isset($options['validate']) && $options['validate'] == RegistrationsComponent::REGISTRATION_VALIDATE_TYPE)) { + $this->validate = Hash::merge($this->validate, array( + 'registration_page_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + 'message' => __d('net_commons', 'Invalid request.'), + ), + ), + )); + } + + parent::beforeValidate($options); + + $isSkip = $this->data['RegistrationQuestion']['is_skip']; + // 付属の選択肢以下のvalidate + if ($this->_checkChoiceExists() && isset($this->data['RegistrationChoice'])) { + // この質問種別に必要な選択肢データがちゃんとあるなら選択肢をバリデート + $validationErrors = array(); + $this->RegistrationChoice = ClassRegistry::init('Registrations.RegistrationChoice', true); + foreach ($this->data['RegistrationChoice'] as $cIndex => $choice) { + // 質問データバリデータ + $this->RegistrationChoice->create(); + $this->RegistrationChoice->set($choice); + $options['choiceIndex'] = $cIndex; + $options['isSkip'] = $isSkip; + if (!$this->RegistrationChoice->validates($options)) { + $validationErrors['RegistrationChoice'][$cIndex] = $this->RegistrationChoice->validationErrors; + } + } + $this->validationErrors += $validationErrors; + } + + return true; + } + +/** + * getDefaultQuestion + * get default data of registration question + * + * @return array + */ + public function getDefaultQuestion() { + $this->RegistrationChoice = ClassRegistry::init('Registrations.RegistrationChoice', true); + $question = array( + 'question_sequence' => 0, + 'question_value' => __d('registrations', 'New Question') . '1', + 'question_type' => RegistrationsComponent::TYPE_SELECTION, + 'is_require' => RegistrationsComponent::USES_NOT_USE, + 'is_skip' => RegistrationsComponent::SKIP_FLAGS_NO_SKIP, + 'is_choice_random' => RegistrationsComponent::USES_NOT_USE, + 'is_range' => RegistrationsComponent::USES_NOT_USE, + 'is_result_display' => RegistrationsComponent::EXPRESSION_SHOW, + 'result_display_type' => RegistrationsComponent::RESULT_DISPLAY_TYPE_BAR_CHART + ); + $question['RegistrationChoice'][0] = $this->RegistrationChoice->getDefaultChoice(); + return $question; + } + +/** + * setQuestionToPage + * setup page data to registration array + * + * @param array &$registration registration data + * @param array &$page registration page data + * @return void + */ + public function setQuestionToPage(&$registration, &$page) { + $questions = $this->find('all', array( + 'conditions' => array( + 'registration_page_id' => $page['id'], + ), + 'order' => array( + 'question_sequence' => 'asc', + ) + )); + + if (!empty($questions)) { + foreach ($questions as $question) { + if (isset($question['RegistrationChoice'])) { + $choices = $question['RegistrationChoice']; + $question['RegistrationQuestion']['RegistrationChoice'] = $choices; + $page['RegistrationQuestion'][] = $question['RegistrationQuestion']; + } + $registration['Registration']['question_count']++; + } + } + } + +/** + * saveRegistrationQuestion + * save RegistrationQuestion data + * + * @param array &$questions registration questions + * @throws InternalErrorException + * @return bool + */ + public function saveRegistrationQuestion(&$questions) { + $this->loadModels([ + 'RegistrationChoice' => 'Registrations.RegistrationChoice', + ]); + // RegistrationQuestionが単独でSaveされることはない + // 必ず上位のRegistrationのSaveの折に呼び出される + // なので、$this->setDataSource('master');といった + // 決まり処理は上位で行われる + // ここでは行わない + + foreach ($questions as &$question) { + // 登録フォームは履歴を取っていくタイプのコンテンツデータなのでSave前にはID項目はカット + // (そうしないと既存レコードのUPDATEになってしまうから) + $question = Hash::remove($question, 'RegistrationQuestion.id'); + + $this->create(); + if (! $this->save($question, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + $questionId = $this->id; + + if (isset($question['RegistrationChoice'])) { + $question = Hash::insert($question, 'RegistrationChoice.{n}.registration_question_id', $questionId); + // もしもChoiceのsaveがエラーになった場合は、 + // ChoiceのほうでInternalExceptionErrorが発行されるのでここでは何も行わない + $this->RegistrationChoice->saveRegistrationChoice($question['RegistrationChoice']); + } + } + return true; + } + +/** + * _checkChoiceExists + * + * 適正な選択肢を持っているか + * + * @return bool + */ + protected function _checkChoiceExists() { + // テキストタイプ、テキストエリアタイプの時は選択肢不要 + if (RegistrationsComponent::isOnlyInputType($this->data['RegistrationQuestion']['question_type'])) { + return true; + } + + // 上記以外の場合は最低1つは必要 + if (! Hash::check($this->data, 'RegistrationChoice.{n}')) { + $this->validationErrors['question_type'][] = __d('registrations', 'please set at least one choice.'); + return false; + } + + // マトリクスタイプの時は行に1つ列に一つ必要 + // マトリクスタイプのときは、行、カラムの両方ともに最低一つは必要 + if (RegistrationsComponent::isMatrixInputType($this->data['RegistrationQuestion']['question_type'])) { + $rows = Hash::extract($this->data['RegistrationChoice'], '{n}[matrix_type=' . RegistrationsComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX . ']'); + $cols = Hash::extract($this->data['RegistrationChoice'], '{n}[matrix_type=' . RegistrationsComponent::MATRIX_TYPE_COLUMN . ']'); + + if (empty($rows) || empty($cols)) { + $this->validationErrors['question_type'][] = __d('registrations', 'please set at least one choice at row and column.'); + return false; + } + } + return true; + } + +/** + * _getResultDisplayList + * 質問種別に応じて許されるisResultDisplayの設定値 + * + * @param int $questionType 質問種別 + * @return array + */ + protected function _getResultDisplayList($questionType) { + if (RegistrationsComponent::isOnlyInputType($questionType)) { + return array(RegistrationsComponent::USES_NOT_USE); + } + return array(RegistrationsComponent::USES_USE, RegistrationsComponent::USES_NOT_USE); + } +} \ No newline at end of file diff --git a/Model/RegistrationSetting.php b/Model/RegistrationSetting.php new file mode 100644 index 0000000..14e6c1a --- /dev/null +++ b/Model/RegistrationSetting.php @@ -0,0 +1,112 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +App::uses('RegistrationsAppModel', 'Registrations.Model'); + +/** + * Summary for RegistrationBlocksSetting Model + */ +class RegistrationSetting extends RegistrationsAppModel { + +/** + * Validation rules + * + * @var array + */ + public $validate = array( + 'block_id' => array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + //'allowEmpty' => false, + //'required' => false, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + ); + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + 'Blocks.BlockRolePermission', + ); + +/** + * getSetting + * + * @return mix RegistrationBlockSetting data + */ + public function getSetting() { + $this->Block = ClassRegistry::init('Blocks.Block', true); + $blockSetting = $this->Block->find('all', array( + 'recursive' => -1, + 'fields' => array( + $this->Block->alias . '.*', + $this->alias . '.*', + ), + 'joins' => array( + array( + 'table' => $this->table, + 'alias' => $this->alias, + 'type' => 'LEFT', + 'conditions' => array( + $this->Block->alias . '.key' . ' = ' . $this->alias . ' .block_key', + ), + ), + ), + 'conditions' => array( + 'Block.id' => Current::read('Block.id') + ), + )); + if (! $blockSetting) { + return $blockSetting; + } + return $blockSetting[0]; + } +/** + * Save registration settings + * + * @param array $data received post data + * @return bool True on success, false on failure + * @throws InternalErrorException + */ + public function saveRegistrationSetting($data) { + //トランザクションBegin + $this->begin(); + + //バリデーション + $this->set($data); + if (! $this->validates()) { + $this->rollback(); + return false; + } + + try { + if (! $this->save(null, false)) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + //トランザクションCommit + $this->commit(); + + } catch (Exception $ex) { + //トランザクションRollback + $this->rollback($ex); + } + return true; + } + +} diff --git a/Model/RegistrationsAppModel.php b/Model/RegistrationsAppModel.php new file mode 100644 index 0000000..63a86a2 --- /dev/null +++ b/Model/RegistrationsAppModel.php @@ -0,0 +1,44 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppModel', 'Model'); + +/** + * Summary for RegistrationQuestion Model + */ +class RegistrationsAppModel extends AppModel { + +/** + * use behaviors + * + * @var array + */ + public $actsAs = array( + ); + +/** + * Called during validation operations, before validation. Please note that custom + * validation rules can be defined in $validate. + * + * @param array $options Options passed from Model::save(). + * @return bool True if validate operation should continue, false to abort + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate + * @see Model::save() + */ + public function beforeValidate($options = array()) { + // この継承クラスたちがValidateロジックを走らせる前に必ずDBを切り替える + $this->setDataSource('master'); + return parent::beforeValidate($options); + } + +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..49de79b --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +Registrations +============== + +Registrations for NetComomns3 + +[![Build Status](https://api.travis-ci.org/NetCommons3/Registrations.png?branch=master)](https://travis-ci.org/NetCommons3/Registrations) +[![Coverage Status](https://coveralls.io/repos/NetCommons3/Registrations/badge.png?branch=master)](https://coveralls.io/r/NetCommons3/Registrations?branch=master) + +| dependencies | status | +| ------------- | ------ | +| composer.json | [![Dependency Status](https://www.versioneye.com/user/projects/(versioneye_project_ID)/badge.png)](https://www.versioneye.com/user/projects/(versioneye_project_ID)) | diff --git a/Test/Case/AllRegistrationsTest.php b/Test/Case/AllRegistrationsTest.php new file mode 100644 index 0000000..19dc284 --- /dev/null +++ b/Test/Case/AllRegistrationsTest.php @@ -0,0 +1,31 @@ + + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +/** + * Registrations All Test Suite + * + * @author AllCreator + * @package NetCommons\Announcements\Test\Case + * @codeCoverageIgnore + */ +class AllRegistrationsTest extends CakeTestSuite { + +/** + * All test suite + * + * @return CakeTestSuite + */ + public static function suite() { + $plugin = preg_replace('/^All([\w]+)Test$/', '$1', __CLASS__); + $suite = new CakeTestSuite(sprintf('All %s Plugin tests', $plugin)); + $suite->addTestDirectoryRecursive(CakePlugin::path($plugin) . 'Test' . DS . 'Case'); + return $suite; + } +} diff --git a/Test/Case/Controller/Component/empty b/Test/Case/Controller/Component/empty new file mode 100644 index 0000000..e69de29 diff --git a/Test/Case/Controller/QuesetionnaireAddController/AddTest.php b/Test/Case/Controller/QuesetionnaireAddController/AddTest.php new file mode 100644 index 0000000..2e44201 --- /dev/null +++ b/Test/Case/Controller/QuesetionnaireAddController/AddTest.php @@ -0,0 +1,248 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('RegistrationAddController', 'Registrations.Controller'); +App::uses('WorkflowControllerAddTest', 'Workflow.TestSuite'); + +/** + * FaqQuestionsController Test Case + * + * @author Shohei Nakajima + * @package NetCommons\Faqs\Test\Case\Controller\FaqQuestionsController + */ +class RegistrationAddControllerAddTest extends WorkflowControllerAddTest { + +/** + * Fixtures + * + * @var array + */ + public $fixtures = array( + 'plugin.registrations.registration', + 'plugin.registrations.registration_setting', + 'plugin.registrations.registration_frame_setting', + 'plugin.registrations.registration_frame_display_registration', + 'plugin.registrations.registration_page', + 'plugin.registrations.registration_question', + 'plugin.registrations.registration_choice', + 'plugin.registrations.registration_answer_summary', + 'plugin.workflow.workflow_comment', + ); + +/** + * Plugin name + * + * @var array + */ + public $plugin = 'registrations'; + +/** + * Controller name + * + * @var string + */ + protected $_controller = 'registration_add'; + +/** + * setUp method + * + * @return void + */ + public function setUp() { + parent::setUp(); + $this->Registration = ClassRegistry::init('Registrations.Registration'); + $this->Registration->Behaviors->unload('AuthorizationKey'); + $this->ActionRegistrationAdd = ClassRegistry::init('Registrations.ActionRegistrationAdd'); + } + +/** + * テストDataの取得 + * + * @return array + */ + private function __getData() { + $frameId = '6'; + $blockId = '2'; + $blockKey = 'block_1'; + + $data = array( + //'save_' . WorkflowComponent::STATUS_IN_DRAFT => null, + 'Frame' => array( + 'id' => $frameId + ), + 'Block' => array( + 'id' => $blockId, + 'key' => $blockKey, + 'language_id' => '2', + 'room_id' => '1', + 'plugin_key' => $this->plugin, + ), + 'ActionRegistrationAdd' => array( + 'create_option' => 'create', + 'title' => 'New Registration Title', + ), + ); + + return $data; + } + +/** + * addアクションのGETテスト(ログインなし)用DataProvider + * + * ### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderAddGet() { + $data = $this->__getData(); + $results = array(); + + //ログインなし + $results[0] = array( + 'urlOptions' => array('frame_id' => $data['Frame']['id'], 'block_id' => $data['Block']['id']), + 'assert' => null, 'exception' => 'ForbiddenException' + ); + return $results; + } + +/** + * addアクションのGETテスト(作成権限あり)用DataProvider + * + * ### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderAddGetByCreatable() { + $data = $this->__getData(); + $results = array(); + + //作成権限あり + $base = 0; + $results[0] = array( + 'urlOptions' => array('frame_id' => $data['Frame']['id'], 'block_id' => $data['Block']['id']), + 'assert' => array('method' => 'assertNotEmpty'), + ); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'input', 'name' => 'data[Frame][id]', 'value' => $data['Frame']['id']), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'input', 'name' => 'data[Block][id]', 'value' => $data['Block']['id']), + ))); + /*array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'button', 'name' => 'save_' . WorkflowComponent::STATUS_IN_DRAFT, 'value' => null), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'button', 'name' => 'save_' . WorkflowComponent::STATUS_APPROVED, 'value' => null), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'input', 'name' => 'data[FaqQuestion][id]', 'value' => $data['FaqQuestion']['id']), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'input', 'name' => 'data[FaqQuestion][key]', 'value' => $data['FaqQuestion']['key']), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'textarea', 'name' => 'data[FaqQuestion][question]', 'value' => null), + ))); + array_push($results, Hash::merge($results[$base], array( + 'assert' => array('method' => 'assertInput', 'type' => 'textarea', 'name' => 'data[FaqQuestion][answer]', 'value' => null), + )));*/ + + //フレームID指定なしテスト + array_push($results, Hash::merge($results[$base], array( + 'urlOptions' => array('frame_id' => null, 'block_id' => $data['Block']['id']), + 'assert' => array('method' => 'assertNotEmpty'), + ))); + array_push($results, Hash::merge($results[$base], array( + 'urlOptions' => array('frame_id' => null, 'block_id' => $data['Block']['id']), + 'assert' => array('method' => 'assertInput', 'type' => 'input', 'name' => 'data[Frame][id]', 'value' => null), + ))); + + return $results; + } + +/** + * addアクションのPOSTテスト用DataProvider + * + * ### 戻り値 + * - data: 登録データ + * - role: ロール + * - urlOptions: URLオプション + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderAddPost() { + $data = $this->__getData(); + + return array( + //ログインなし + array( + 'data' => $data, 'role' => null, + 'urlOptions' => array('frame_id' => $data['Frame']['id'], 'block_id' => $data['Block']['id']), + 'exception' => 'ForbiddenException' + ), + //作成権限あり + array( + 'data' => $data, 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER, + 'urlOptions' => array('frame_id' => $data['Frame']['id'], 'block_id' => $data['Block']['id']), + ), + //フレームID指定なしテスト + array( + 'data' => $data, 'role' => Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR, + 'urlOptions' => array('frame_id' => null, 'block_id' => $data['Block']['id']), + ), + ); + } + +/** + * addアクションのValidationErrorテスト用DataProvider + * + * ### 戻り値 + * - data: 登録データ + * - urlOptions: URLオプション + * - validationError: バリデーションエラー + * + * @return array + */ + public function dataProviderAddValidationError() { + $data = $this->__getData(); + $result = array( + 'data' => $data, + 'urlOptions' => array('frame_id' => $data['Frame']['id'], 'block_id' => $data['Block']['id']), + ); + + return array( + Hash::merge($result, array( + 'validationError' => array( + 'field' => 'ActionRegistrationAdd.create_option', + 'value' => null, + 'message' => sprintf(__d('registrations', 'Please choose create option.')) + ) + )), + Hash::merge($result, array( + 'validationError' => array( + 'field' => 'ActionRegistrationAdd.title', + 'value' => '', + 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('registrations', 'Title')) + ) + )), + ); + } +} diff --git a/Test/Case/Controller/RegistrationAnswersController/ViewTest.php b/Test/Case/Controller/RegistrationAnswersController/ViewTest.php new file mode 100644 index 0000000..cb2ac7d --- /dev/null +++ b/Test/Case/Controller/RegistrationAnswersController/ViewTest.php @@ -0,0 +1,420 @@ + + * @author Allcreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('WorkflowControllerViewTest', 'Workflow.TestSuite'); + +/** + * RegistrationAnswerController Test Case + * + * @author Allcreator + * @package NetCommons\Bbses\Test\Case\Controller\BbsArticlesController + */ +class RegistrationAnswerControllerViewTest extends WorkflowControllerViewTest { + +/** + * Fixtures + * + * @var array + */ + public $fixtures = array( + 'plugin.registrations.registration', + 'plugin.registrations.registration_setting', + 'plugin.registrations.registration_frame_setting', + 'plugin.registrations.registration_frame_display_registration', + 'plugin.registrations.registration_page', + 'plugin.registrations.registration_question', + 'plugin.registrations.registration_choice', + 'plugin.registrations.registration_answer_summary', + 'plugin.registrations.registration_answer', + 'plugin.authorization_keys.authorization_keys', + ); + +/** + * Plugin name + * + * @var array + */ + public $plugin = 'registrations'; + +/** + * Controller name + * + * @var string + */ + protected $_controller = 'registration_answers'; + +/** + * setUp method + * + * @return void + */ + public function setUp() { + parent::setUp(); + $this->Registration = ClassRegistry::init('Registrations.Registration'); + $this->Registration->Behaviors->unload('AuthorizationKey'); + } + +/** + * viewアクションのテスト用DataProvider + * + * ### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderView() { + $results = array(); + + //ログインなし + //--コンテンツあり + $results[0] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'registration_2'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + /* + $results[1] = Hash::merge($results[0], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + $results[2] = Hash::merge($results[0], array( //コメント(なし) + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => false, 'url' => array()), + )); + //--コンテンツなし + $results[3] = array( + 'urlOptions' => array('frame_id' => '14', 'block_id' => null, 'key' => null), + 'assert' => array('method' => 'assertEquals', 'expected' => 'emptyRender'), + 'exception' => null, 'return' => 'viewFile' + ); + */ + + return $results; + } + +/** + * viewアクションのテスト(作成権限のみ)用DataProvider + * + * ### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderViewByCreatable() { + $results = array(); + //作成権限のみ(一般が書いた記事&一度公開している) + $results[0] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'registration_10'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + /* + $results[1] = Hash::merge($results[0], array( //(承認済み記事は編集不可) + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + //作成権限のみ(一般が書いた質問&公開前) + $results[2] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_4'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + $results[3] = Hash::merge($results[2], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => true, 'url' => array()), + )); + //作成権限のみ(他人が書いた質問&公開中)(root_idとparent_idが異なる) + $results[4] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_9'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + $results[5] = Hash::merge($results[4], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + $results[6] = Hash::merge($results[4], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => false, 'url' => array()), + )); + + //作成権限のみ(他人が書いた質問&公開中)(root_idとparent_idが同一) + $results[7] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_8'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + $results[8] = Hash::merge($results[7], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + //--(子記事に'parent_id'あり) + $results[9] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_7'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + $results[10] = Hash::merge($results[9], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + //作成権限のみ(他人が書いた質問&公開前) + $results[11] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_5'), + 'assert' => null, + 'exception' => 'BadRequestException', + ); + //--コンテンツなし + $results[12] = array( + 'urlOptions' => array('frame_id' => '14', 'block_id' => null, 'key' => null), + 'assert' => array('method' => 'assertEquals', 'expected' => 'emptyRender'), + 'exception' => null, 'return' => 'viewFile' + ); + //--パラメータ不正(keyに該当する質問が存在しない) + $results[13] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_99'), + 'assert' => null, + 'exception' => 'BadRequestException', + ); + //--BBSなし + $results[14] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_xx'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + ); + $results[15] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_xx'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + 'return' => 'json' + ); + */ + return $results; + } + +/** + * viewアクションのテスト(編集権限、公開権限なし)用DataProvider + * + * ### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderViewByEditable() { + $results = array(); + + //編集権限あり(chef_userが書いた記事一度も公開していない) + //--コンテンツあり + $results[0] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'registration_48'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + /* + //チェック + //--編集ボタン + $results[1] = Hash::merge($results[0], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => true, 'url' => array()), + )); + //--コメントボタン + $results[2] = Hash::merge($results[0], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => false, 'url' => array()), + )); + //編集権限あり(chef_userが書いた記事公開) + //--コンテンツあり + $results[3] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_6'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + //チェック + //--編集ボタン + $results[4] = Hash::merge($results[3], array( //なし(公開すると編集不可) + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + //--コメントボタン + $results[5] = Hash::merge($results[3], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => true, 'url' => array()), + )); + //--コンテンツなし + $results[6] = array( + 'urlOptions' => array('frame_id' => '14', 'block_id' => null, 'key' => null), + 'assert' => array('method' => 'assertEquals', 'expected' => 'emptyRender'), + 'exception' => null, 'return' => 'viewFile' + ); + //フレームID指定なしテスト + $results[7] = array( + 'urlOptions' => array('frame_id' => null, 'block_id' => '2', 'key' => 'bbs_article_3'), + 'assert' => array('method' => 'assertNotEmpty'), + ); + $results[8] = Hash::merge($results[3], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => false, 'url' => array()), + )); + //根記事が取得できない + $results[9] = array( + 'urlOptions' => array('frame_id' => null, 'block_id' => '2', 'key' => 'bbs_article_10'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + ); + $results[10] = array( + 'urlOptions' => array('frame_id' => null, 'block_id' => '2', 'key' => 'bbs_article_10'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + 'return' => 'json' + ); + //親記事が取得できない + $results[11] = array( + 'urlOptions' => array('frame_id' => null, 'block_id' => '2', 'key' => 'bbs_article_11'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + ); + $results[12] = array( + 'urlOptions' => array('frame_id' => null, 'block_id' => '2', 'key' => 'bbs_article_11'), + 'assert' => 'null', + 'exception' => 'BadRequestException', + 'return' => 'json' + ); + */ + + return $results; + } + +/** + * viewアクションのテスト + * + * @param array $urlOptions URLオプション + * @param array $assert テストの期待値 + * @param string|null $exception Exception + * @param string $return testActionの実行後の結果 + * @dataProvider dataProviderViewError + * @return void + */ + /* + public function testViewError($urlOptions, $assert, $exception = null, $return = 'view') { + //Exception + ClassRegistry::removeObject('WorkflowBehavior'); + $workflowBehaviorMock = $this->getMock('WorkflowBehavior', ['canReadWorkflowContent']); + ClassRegistry::addObject('WorkflowBehavior', $workflowBehaviorMock); + $this->Registration->Behaviors->unload('Workflow'); + $this->Registration->Behaviors->load('Workflow', $this->Registration->actsAs['Workflow.Workflow']); + + $workflowBehaviorMock + ->expects($this->once()) + ->method('canReadWorkflowContent') + ->will($this->returnValue(false)); + + //テスト実施 + $url = Hash::merge(array( + 'plugin' => $this->plugin, + 'controller' => $this->_controller, + 'action' => 'view', + ), $urlOptions); + + $this->_testGetAction($url, $assert, $exception, $return); + } + */ +/** + * viewアクション用DataProvider + * + * #### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + /* + public function dataProviderViewError() { + $results = array(); + + // 参照不可のテスト + $results[0] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'registration_40'), + 'assert' => null, + 'exception' => 'BadRequestException', + ); + $results[1] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_10'), + 'assert' => null, + 'exception' => 'BadRequestException', + 'return' => 'json' + ); + return $results; + } + */ + +/** + * viewアクション(編集ボタンの確認) + * + * @param array $urlOptions URLオプション + * @param array $assert テストの期待値 + * @param string|null $exception Exception + * @param string $return testActionの実行後の結果 + * @dataProvider dataProviderViewGetByPublishable + * @return void + */ + public function testEditGetByPublishable($urlOptions, $assert, $exception = null, $return = 'view') { + //ログイン + TestAuthGeneral::login($this, Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR); + + $this->testView($urlOptions, $assert, $exception, $return); + + //ログアウト + TestAuthGeneral::logout($this); + } + +/** + * viewアクション(コメントボタンの確認)用DataProvider + * + * #### 戻り値 + * - urlOptions: URLオプション + * - assert: テストの期待値 + * - exception: Exception + * - return: testActionの実行後の結果 + * + * @return array + */ + public function dataProviderViewGetByPublishable() { + //公開中の記事 + $results[0] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'registration_2'), + 'assert' => null + ); + /* + //チェック + //--編集ボタン + $results[1] = Hash::merge($results[0], array( //あり + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => true, 'url' => array()), + )); + //--コメントボタン + $results[2] = Hash::merge($results[0], array( //あり + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => true, 'url' => array()), + )); + + //公開前の記事 + $results[3] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_4'), + 'assert' => null + ); + //チェック + //--編集ボタン + $results[4] = Hash::merge($results[3], array( + 'assert' => array('method' => 'assertActionLink', 'action' => 'edit', 'linkExist' => true, 'url' => array()), + )); + //--コメントボタン + $results[5] = Hash::merge($results[3], array( //なし + 'assert' => array('method' => 'assertActionLink', 'action' => 'reply', 'linkExist' => false, 'url' => array()), + )); + //--未承認のコメント(承認ボタン) + $results[6] = array( + 'urlOptions' => array('frame_id' => '6', 'block_id' => '2', 'key' => 'bbs_article_13'), + 'assert' => array('method' => 'assertInput', 'type' => 'button', 'name' => 'save_' . WorkflowComponent::STATUS_PUBLISHED, 'value' => null), + ); + */ + + return $results; + } + +} diff --git a/Test/Case/Controller/RegistrationBlocksController/IndexTest.php b/Test/Case/Controller/RegistrationBlocksController/IndexTest.php new file mode 100644 index 0000000..457e7be --- /dev/null +++ b/Test/Case/Controller/RegistrationBlocksController/IndexTest.php @@ -0,0 +1,210 @@ + + * @author AllCreator + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('BlocksControllerTest', 'Blocks.TestSuite'); + +/** + * RegistrationBlocksController Test Case + * + * @author AllCreator + * @package NetCommons\Qustionnaires\Test\Case\Controller\RegistrationBlocksController + */ +class RegistrationBlocksControllerIndexTest extends BlocksControllerTest { + +/** + * Plugin name + * + * @var array + */ + public $plugin = 'registrations'; + +/** + * Controller name + * + * @var string + */ + protected $_controller = 'registration_blocks'; + +/** + * Fixtures + * + * @var array + */ + public $fixtures = array( + 'plugin.registrations.registration', + 'plugin.registrations.registration_setting', + 'plugin.registrations.registration_frame_setting', + 'plugin.registrations.registration_frame_display_registration', + 'plugin.registrations.registration_page', + 'plugin.registrations.registration_question', + 'plugin.registrations.registration_choice', + 'plugin.registrations.registration_answer_summary', + ); + +/** + * Edit controller name + * + * @var string + */ + protected $_editController = 'registration_blocks'; + +/** + * setUp method + * + * @return void + */ + public function setUp() { + parent::setUp(); + $this->Registration = ClassRegistry::init('Registrations.Registration'); + $this->Registration->Behaviors->unload('AuthorizationKey'); + } + +/** + * index()のテスト + * + * 登録フォームは追加、編集用のコントローラを独自に持っているためここにオーバーライド + * @return void + */ + public function testIndex() { + //ログイン + TestAuthGeneral::login($this); + + //テスト実施 + $frameId = '6'; + $blockId = '2'; + $url = array( + 'plugin' => $this->plugin, + 'controller' => $this->_controller, + 'action' => 'index', + 'frame_id' => $frameId + ); + $result = $this->_testNcAction($url, array('method' => 'get')); + + //チェック + //--追加ボタンチェック + $addLink = $url; + $addLink['controller'] = 'registration_add'; + $addLink['action'] = 'add'; + $addLink['block_id'] = $blockId; + $this->assertRegExp( + '//', $result + ); + + //--編集ボタンチェック + $blockId = '2'; + $editLink = $url; + $editLink['controller'] = 'registration_edit'; + $editLink['action'] = 'edit_question'; + $editLink['block_id'] = $blockId; + $editLink['key'] = 'registration_4'; + $this->assertRegExp( + '//', $result + ); + + //--カレントブロックラジオボタン + //$this->assertInput('input', 'data[Frame][block_id]', null, $result); + + //ログアウト + TestAuthGeneral::logout($this); + } + +/** + * index()のブロックなしテスト + * + * 登録フォームはブロック一覧ではなく、コンテンツ一覧を出しているため独自実装が必要となる + * @return void + */ + public function testIndexNoneBlock() { + //ログイン + TestAuthGeneral::login($this); + + //テスト実施 + $frameId = '18'; + $url = array( + 'plugin' => $this->plugin, + 'controller' => $this->_controller, + 'action' => 'index', + 'frame_id' => $frameId, + ); + $result = $this->_testNcAction($url, array('method' => 'get'), null, 'viewFile'); + + //チェック + $this->assertTextEquals($result, 'not_found'); + + //ログアウト + TestAuthGeneral::logout($this); + } + +/** + * index()のページネーションテスト + * + * @param int $page ページ番号 + * @param bool $isFirst 最初のページかどうか + * @param bool $isLast 最後のページかどうか + * @dataProvider dataProviderPaginator + * @return void + */ + public function testIndexPaginator($page, $isFirst, $isLast) { + TestAuthGeneral::login($this); + + //テスト実施 + $frameId = '6'; + $url = array( + 'plugin' => $this->plugin, + 'controller' => $this->_controller, + 'action' => 'index', + 'frame_id' => $frameId, + ); + if (! $isFirst) { + $url[] = 'page:' . $page; + } + $result = $this->_testNcAction($url, array('method' => 'get')); + + //チェック + $this->assertRegExp( + '/' . preg_quote('