diff --git a/Locale/jpn/LC_MESSAGES/reservations.po b/Locale/jpn/LC_MESSAGES/reservations.po index 7d15f0c..5110895 100644 --- a/Locale/jpn/LC_MESSAGES/reservations.po +++ b/Locale/jpn/LC_MESSAGES/reservations.po @@ -1413,9 +1413,12 @@ msgid "To see details of import file item settings, please see below.
" msgstr "インポートファイルへの設定項目の詳細は、下記を参照ください。
" "なお、各項目を無指定とする場合、空白の代わりに文字列「null」を設定してください。
" "また、無指定(「null」指定)または指定外の設定をした場合、未設定 とします。" + +msgid "Register to Calendar?" +msgstr "カレンダーに記入" msgid "-- not specified --" msgstr "-- 指定しない --" msgid "Location not found in select category." -msgstr "選択したカテゴリに登録されている施設はありません。" \ No newline at end of file +msgstr "選択したカテゴリに登録されている施設はありません。" diff --git a/Model/Behavior/RegistCalendarBehavior.php b/Model/Behavior/RegistCalendarBehavior.php new file mode 100644 index 0000000..e87427d --- /dev/null +++ b/Model/Behavior/RegistCalendarBehavior.php @@ -0,0 +1,161 @@ + + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + */ + +/** + * Class RegistCalendarBehavior + */ +class RegistCalendarBehavior extends ReservationAppBehavior { + +/** + * カレンダ更新 + * + * @param Model $model ReservationEvent + * @param array $data ReservationEvent data + * @param array $rruleData ReservationRrule data + * @return void + */ + public function updateCalendar(Model $model, $data, $rruleData) { + $data = Hash::merge($data, $rruleData); + + $cmd = ($data[$model->alias]['use_calendar']) ? 'save' : 'del'; + + $data[$model->alias]['start_datetime'] = + date('Y-m-d H:i:s', strtotime($data[$model->alias]['dtstart'])); + $data[$model->alias]['end_datetime'] = + date('Y-m-d H:i:s', strtotime($data[$model->alias]['dtend'])); + + // save_1がセットされてないとカレンダ登録されないので… + $data['save_1'] = true; + + if ($cmd === 'save') { + //実施期間設定あり&&カレンダー登録する + $this->_registCalendar($model, $data, $rruleData); + } else { + //cmd===del + if (!empty($data[$model->alias]['calendar_key'])) { + //calendar_keyが記録されているので、消しにいく。 + $this->_removeCalendar($model, $data, $rruleData); + } + } + } + +/** + * カレンダから登録削除 + * + * @param Model $model ReservationEvent + * @param array $data ReservationEvent data + * @param array $rruleData ReservationRrule data + * @return void + * + * @throws InternalErrorException + */ + protected function _removeCalendar(Model $model, $data, $rruleData) { + $model->loadModels( + [ + 'CalendarDeleteActionPlan' => 'Calendars.CalendarDeleteActionPlan', + ] + ); + //削除用settings指定 + $model->CalendarDeleteActionPlan->Behaviors->load( + 'Calendars.CalendarLink', + array( + 'linkPlugin' => Current::read('Plugin.key'), + 'table' => $model->alias, //fieldsの対象テーブル + 'sysFields' => array( + 'key' => 'key', //tasksの場合、task_contentsテーブルのkey + 'calendar_key' => 'calendar_key', //tasksの場合、task_contentsテーブルのcalendar_key + ), + 'isDelRepeat' => (Hash::get($rruleData, 'ReservationRrule.rrule', false)) ? + true : false, + ) + ); + $model->CalendarDeleteActionPlan->deletePlanForLink($data); + //削除が成功したので、calenar_keyをクリアし、use_calendarをOFFにして、 + //TaskContentにsave(update)しておく。 + $data[$model->alias]['calendar_key'] = ''; + $data[$model->alias]['use_calendar'] = 0; + $savedData = $model->save($data, false); + if ($savedData === false) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + $data[$model->alias] = $savedData[$model->alias]; + $model->CalendarDeleteActionPlan->Behaviors->unload('Calendars.CalendarLink'); + } + +/** + * カレンダ登録 + * + * @param Model $model ReservationEvent + * @param array $data ReservationEvent data + * @param array $rruleData ReservationRrule data + * @return void + * + * @throws InternalErrorException + */ + protected function _registCalendar(Model $model, $data, $rruleData) { + $model->loadModels( + [ + 'CalendarActionPlan' => 'Calendars.CalendarActionPlan', + ] + ); + //登録・変更用settings指定付きでbehaviorロード + $model->CalendarActionPlan->Behaviors->load( + 'Calendars.CalendarLink', + array( + 'linkPlugin' => Current::read('Plugin.key'), + 'table' => $model->alias, //fieldsの対象テーブル + //'table' => 'reservation_events', //fieldsの対象テーブル + 'inputFields' => array( + 'title' => 'title', + 'description' => 'description', + ), + 'sysFields' => array( + 'key' => 'key', //tasksの場合、task_contentsテーブルのkey + 'calendar_key' => 'calendar_key', //tasksの場合、task_contentsテーブルのcalendar_key + ), + 'startendFields' => array( + 'start_datetime' => 'start_datetime', + 'end_datetime' => 'end_datetime', + ), + 'isServerTime' => true, + 'useStartendComplete' => false, + 'isLessthanOfEnd' => false, + + 'isRepeat' => (Hash::get($rruleData, 'ReservationRrule.rrule', false)) ? + true : false, + 'rruleTable' => 'ReservationRrule', + 'rrule' => 'rrule', + 'isPlanRoomId' => true, + 'planRoomTable' => $model->alias, + 'plan_room_id' => 'room_id', + ) + ); + $calendarKey = $model->CalendarActionPlan->savePlanForLink($data); + if (is_string($calendarKey) && !empty($calendarKey)) { + //カレンダ登録成功 + //calenar_keyを TaskContentにsave(update)しておく。 + $data[$model->alias]['calendar_key'] = $calendarKey; + + $savedData = $model->save($data, false); + + if ($savedData === false) { + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + + $data[$model->alias] = $savedData[$model->alias]; + } elseif ($calendarKey === '') { + //未承認や一時保存はカレンダー登録条件を満たさないのでスルー(通常) + } else { //false + //カレンダー登録時にエラー発生(エラー) + //例外なげる + throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); + } + $model->CalendarActionPlan->Behaviors->unload('Calendars.CalendarLink'); + } +} \ No newline at end of file diff --git a/Model/Behavior/ReservationAppBehavior.php b/Model/Behavior/ReservationAppBehavior.php index 73a5a9d..5c42bf6 100644 --- a/Model/Behavior/ReservationAppBehavior.php +++ b/Model/Behavior/ReservationAppBehavior.php @@ -392,6 +392,7 @@ public function setPlanParams2Params(&$planParams, &$params) { 'linked_content_key', 'enable_email', 'email_send_timing', + 'use_calendar' ); foreach ($keys as $key) { if (isset($planParams[$key])) { @@ -434,7 +435,7 @@ public function setEventData($planParams, $rruleData, &$eventData) { 'end_time' => $planParams['end_time'], 'dtend' => $planParams['end_date'] . $planParams['end_time'], 'timezone' => $planParams['timezone'], - 'timezone' => Hash::get($planParams, 'timezone'), + //'timezone' => Hash::get($planParams, 'timezone'), 'status' => $planParams['status'], 'enable_email' => $planParams['enable_email'], 'email_send_timing' => $planParams['email_send_timing'], @@ -477,6 +478,8 @@ public function setEventData($planParams, $rruleData, &$eventData) { $eventData['ReservationEvent']['location_key'] = $params['location_key']; + $eventData['ReservationEvent']['use_calendar'] = $params['use_calendar']; + ////保存するモデルをここで替える //$eventData['ReservationEventContent']['linked_model'] = $params['linked_model']; //$eventData['ReservationEventContent']['linked_content_key'] = $params['linked_content_key']; diff --git a/Model/Behavior/ReservationInsertPlanBehavior.php b/Model/Behavior/ReservationInsertPlanBehavior.php index cf6affb..b870045 100644 --- a/Model/Behavior/ReservationInsertPlanBehavior.php +++ b/Model/Behavior/ReservationInsertPlanBehavior.php @@ -148,12 +148,15 @@ public function insertEventData(Model &$model, $planParams, $rruleData, throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } - if (!$model->ReservationEvent->save($eventData, false)) { //保存のみ + if (!$savedData = $model->ReservationEvent->save($eventData, false)) { //保存のみ $model->validationErrors = Hash::merge( $model->validationErrors, $model->ReservationEvent->validationErrors); throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } + // $planParams['rrule']か $rruleDataで繰り返し参照できる + $model->ReservationEvent->updateCalendar($savedData, $rruleData); + //施設予約独自の例外追加1) //変更後の公開ルームidが、「元予定生成者の*ルーム」から「編集者・承認者(=ログイン者)の //プライベート」に変化していた場合、created_userを、元予定生成者「から」編集者・承認者(=ログイン者) diff --git a/Model/Behavior/ReservationUpdatePlanBehavior.php b/Model/Behavior/ReservationUpdatePlanBehavior.php index 4eff7b4..19cff5a 100644 --- a/Model/Behavior/ReservationUpdatePlanBehavior.php +++ b/Model/Behavior/ReservationUpdatePlanBehavior.php @@ -412,6 +412,9 @@ public function updateDtstartData(Model &$model, $planParams, $rruleData, $event throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } + //$planParams['rrule']か $rruleData['ReservationRrule']で繰り返しわたせる。 + $model->ReservationEvent->updateCalendar($eventData, $rruleData); + //採番されたidをeventDataにセットしておく $eventData['ReservationEvent']['id'] = $model->ReservationEvent->id; diff --git a/Model/ReservationActionPlan.php b/Model/ReservationActionPlan.php index c5a096e..0a5e2a7 100644 --- a/Model/ReservationActionPlan.php +++ b/Model/ReservationActionPlan.php @@ -83,7 +83,7 @@ class ReservationActionPlan extends ReservationsAppModel { */ 'Reservations.ReservationMail', 'Reservations.ReservationTopics', - // 'Reservations.RegistCalendar', + ); // @codingStandardsIgnoreStart // $_schemaはcakePHP2の予約語だが、宣言するとphpcsが警告を出すので抑止する。 @@ -571,7 +571,7 @@ public function validteNotExistReservation($check) { // 全ての予約を更新 $ignoreConditions = [ 'NOT' => [ - 'ReservationEvent.rrule_id' => + 'ReservationEvent.reservation_rrule_id' => Hash::get($this->data, 'ReservationActionPlan.origin_rrule_id'), 'ReservationEvent.recurrence_event_id !=' => 0, 'ReservationEvent.exception_event_id !=' => 0, @@ -896,7 +896,7 @@ public function saveReservationPlan($data, $procMode, //$this->insertPlan($planParam); $eventId = $this->insertPlan($planParam, $isMyPrivateRoom); - //$this->updateCalendar($planParam); + } else { //PLAN_EDIT //変更処理 //CakeLog::debug("DBG: PLAN_MODIFY case."); @@ -1065,6 +1065,7 @@ public function convertToPlanParamFormat($data) { 'location', 'contact', 'description', 'enable_email', 'email_send_timing', 'status', 'location_key', + 'use_calendar', ); foreach ($fields as $field) { $planParam[$field] = $data[$this->alias][$field]; diff --git a/Model/ReservationEvent.php b/Model/ReservationEvent.php index 1e9d9a1..341d1de 100644 --- a/Model/ReservationEvent.php +++ b/Model/ReservationEvent.php @@ -71,6 +71,7 @@ class ReservationEvent extends ReservationsAppModel { 'M17n.M17n' => array( 'keyField' => false, ), + 'Reservations.RegistCalendar', ); /** diff --git a/Model/ReservationLocation.php b/Model/ReservationLocation.php index be89ac6..7a834db 100644 --- a/Model/ReservationLocation.php +++ b/Model/ReservationLocation.php @@ -452,7 +452,7 @@ public function getReservableLocations($categoryId = null, $userId = null) { 'ReservationLocationsRoom' => 'Reservations.ReservationLocationsRoom', 'ReservationLocationReservable' => 'Reservations.ReservationLocationReservable', 'ReservationLocationsApprovalUser' => 'Reservations.ReservationLocationsApprovalUser', - //'ReservationLocationRoom' => 'Reservations.ReservationLocationRoom' + 'Room' => 'Rooms.Room', ] ); $locations = $this->getLocations($categoryId); diff --git a/Model/ReservationLocationReservable.php b/Model/ReservationLocationReservable.php index 3a3210a..b38d61f 100644 --- a/Model/ReservationLocationReservable.php +++ b/Model/ReservationLocationReservable.php @@ -50,6 +50,17 @@ class ReservationLocationReservable extends ReservationsAppModel { ) ); +/** + * アクセスユーザがプライベートルームを使えるか + * + * @var null|bool + */ + protected $_usePrivateRoom = null; + + protected $_reservable = []; + + protected $_roleKeys = null; + /** * Called during validation operations, before validation. Please note that custom * validation rules can be defined in $validate. @@ -85,85 +96,103 @@ public function beforeValidate($options = array()) { * @return bool */ public function isReservableByLocation($location) { - $this->loadModels([ - 'RolesRoomsUser' => 'Rooms.RolesRoomsUser', - //'RolesRoom' => 'Rooms.RolesRoom', - //'Room' => 'Rooms.Room' - ]); + static $roleKeysByRoomId = []; + if (!isset($this->_reservable[$location['ReservationLocation']['key']])) { + $locationKey = $location['ReservationLocation']['key']; - $roomIds = $this->getReadableRoomIdsWithOutPrivate(); - $userId = Current::read('User.id'); - if (!$userId) { - return []; - } - // 個人的な予約OKな施設 - if ($location['ReservationLocation']['use_private']) { - // マイルームが使えるならOK - $this->loadModels(['UserRoleSetting' => 'UserRoles.UserRoleSetting']); - $userRole = Current::read('User.role_key'); - $userRoleSetting = $this->UserRoleSetting->find('first', [ - 'conditions' => [ - 'UserRoleSetting.role_key' => $userRole - ] + $this->loadModels([ + 'RolesRoomsUser' => 'Rooms.RolesRoomsUser', + //'RolesRoom' => 'Rooms.RolesRoom', + //'Room' => 'Rooms.Room' ]); - $usePrivateRoom = $userRoleSetting['UserRoleSetting']['use_private_room']; - return $usePrivateRoom; - } - - if ($location['ReservationLocation']['use_all_rooms']) { - // 全てのルームで予約Ok - // アクセスできる全ルーム(プライベートのぞく)でのロール取得 - $rolesRoomsUsers = $this->RolesRoomsUser->find('all', array( - 'recursive' => 0, - 'conditions' => array( - 'RolesRoomsUser.user_id' => $userId, - 'RolesRoomsUser.room_id' => $roomIds, - ), - )); - $roleKeys = Hash::combine($rolesRoomsUsers, '{n}.RolesRoom.role_key', '{n}.RolesRoom.role_key'); - $conditions = [ - 'ReservationLocationReservable.location_key' => $location['ReservationLocation']['key'], - 'ReservationLocationReservable.role_key' => $roleKeys, - 'room_id' => null, - ]; - $reservables = $this->find('all', ['conditions' => $conditions]); + $userId = Current::read('User.id'); + if (!$userId) { + $this->_reservable[$locationKey] = false; + return false; + } - foreach ($reservables as $reservable) { - if (Hash::get($reservable, 'ReservationLocationReservable.value')) { - // いずれかのロールで予約権限ついてれば予約OK - return true; + $roomIds = $this->getReadableRoomIdsWithOutPrivate(); + // 個人的な予約OKな施設 + if ($location['ReservationLocation']['use_private']) { + // マイルームが使えるならOK + if (is_null($this->_usePrivateRoom)) { + $this->loadModels(['UserRoleSetting' => 'UserRoles.UserRoleSetting']); + $userRole = Current::read('User.role_key'); + $userRoleSetting = $this->UserRoleSetting->find('first', [ + 'conditions' => [ + 'UserRoleSetting.role_key' => $userRole + ] + ]); + $this->_usePrivateRoom = $userRoleSetting['UserRoleSetting']['use_private_room']; } + $this->_reservable[$locationKey] = $this->_usePrivateRoom; + return $this->_reservable[$locationKey]; } - return false; - } else { - // 選択されたルームのみ予約OK - $reservable = false; - foreach ($roomIds as $roomId) { - // ルームでのロール取得 - $rolesRoomsUsers = $this->RolesRoomsUser->find('first', array( - 'recursive' => 0, - 'conditions' => array( - 'RolesRoomsUser.user_id' => $userId, - 'RolesRoomsUser.room_id' => $roomId, - ), - )); - $roleKeys = Hash::get($rolesRoomsUsers, 'RolesRoom.role_key'); - // ロールに対する予約権限取得 + if ($location['ReservationLocation']['use_all_rooms']) { + // 全てのルームで予約Ok + // アクセスできる全ルーム(プライベートのぞく)でのロール取得 + if (is_null($this->_roleKeys)) { + $rolesRoomsUsers = $this->RolesRoomsUser->find('all', array( + 'recursive' => 0, + 'conditions' => array( + 'RolesRoomsUser.user_id' => $userId, + 'RolesRoomsUser.room_id' => $roomIds, + ), + )); + $this->_roleKeys = Hash::combine($rolesRoomsUsers, + '{n}.RolesRoom.role_key', '{n}.RolesRoom.role_key'); + } + $conditions = [ 'ReservationLocationReservable.location_key' => $location['ReservationLocation']['key'], - 'ReservationLocationReservable.role_key' => $roleKeys, - 'room_id' => $roomId, + 'ReservationLocationReservable.role_key' => $this->_roleKeys, + 'room_id' => null, ]; - $reservable = $this->find('first', ['conditions' => $conditions]); - // ユーザがアクセス可能なルーム(プライベートのぞく)のいずれかで予約OKなら予約できる施設 - if (Hash::get($reservable, 'ReservationLocationReservable.value', false)) { - $reservable = true; + $reservables = $this->find('all', ['conditions' => $conditions]); + + foreach ($reservables as $reservable) { + if (Hash::get($reservable, 'ReservationLocationReservable.value')) { + // いずれかのロールで予約権限ついてれば予約OK + $this->_reservable[$locationKey] = true; + return true; + } + } + $this->_reservable[$locationKey] = false; + return false; + } else { + // 選択されたルームのみ予約OK + $reservable = false; + foreach ($roomIds as $roomId) { + // ルームでのロール取得 + if (!isset($roleKeysByRoomId[$roomId])) { + $rolesRoomsUsers = $this->RolesRoomsUser->find('first', array( + 'recursive' => 0, + 'conditions' => array( + 'RolesRoomsUser.user_id' => $userId, + 'RolesRoomsUser.room_id' => $roomId, + ), + )); + $roleKeysByRoomId[$roomId] = Hash::get($rolesRoomsUsers, 'RolesRoom.role_key'); + } + + // ロールに対する予約権限取得 + $conditions = [ + 'ReservationLocationReservable.location_key' => $location['ReservationLocation']['key'], + 'ReservationLocationReservable.role_key' => $roleKeysByRoomId[$roomId], + 'room_id' => $roomId, + ]; + $reservable = $this->find('first', ['conditions' => $conditions]); + // ユーザがアクセス可能なルーム(プライベートのぞく)のいずれかで予約OKなら予約できる施設 + if (Hash::get($reservable, 'ReservationLocationReservable.value', false)) { + $reservable = true; + } } + $this->_reservable[$locationKey] = $reservable; } - return $reservable; } + return $this->_reservable[$location['ReservationLocation']['key']]; } /** diff --git a/Utility/ReservationSupport.php b/Utility/ReservationSupport.php index 8e0858a..86d557d 100644 --- a/Utility/ReservationSupport.php +++ b/Utility/ReservationSupport.php @@ -433,7 +433,8 @@ private function __makeCapForViewSubset($event, $userStartDatetime, $userEndDate 'TERM' => $this->__getInitailTerm(substr($userStartDatetime, 0, 10)), 'enable_email' => intval($event['ReservationEvent']['is_enable_mail']), //名違いに注意 'email_send_timing' => intval($event['ReservationEvent']['email_send_timing']), - 'location_key' => $event['ReservationEvent']['location_key'] + 'location_key' => $event['ReservationEvent']['location_key'], + 'calendar_key' => $event['ReservationEvent']['calendar_key'] ), ); return $capForView; diff --git a/View/ReservationPlans/detail_edit.ctp b/View/ReservationPlans/detail_edit.ctp index 897476a..660cd69 100644 --- a/View/ReservationPlans/detail_edit.ctp +++ b/View/ReservationPlans/detail_edit.ctp @@ -311,6 +311,25 @@ echo $this->element('Reservations.scripts'); element('Reservations.ReservationPlans/detail_edit_mail'); ?> + +
+ request->data, 'ReservationActionPlan.calendar_key', + false)) { + $this->request->data['ReservationActionPlan']['use_calendar'] = true; + } else { + $this->request->data['ReservationActionPlan']['use_calendar'] = false; + } + echo $this->NetCommonsForm->inlineCheckbox('ReservationActionPlan.use_calendar', + ['label' => + __d( + 'reservations', + 'Register to Calendar?' + ) + ]); + ?> +
+
diff --git a/composer.json b/composer.json index 2801f68..b3d53f9 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,9 @@ { - "name": "netcommons/reservations", + "name": "netcommons/reservations", "description": "Reservations for NetCommons Plugin", - "homepage": "http://www.netcommons.org/", - "license": "NetCommons License", + "homepage": "http://www.netcommons.org/", + "license": "LicenseRef-NetCommons", + "license-ref-net-commons": "https://raw.githubusercontent.com/NetCommons3/NetCommons3/master/license.txt", "authors": [ { "name": "Toshihide Hashimoto(AllCreator Co., Ltd.)", @@ -29,29 +30,34 @@ ], "extra": { "installer-paths": { - "app/Plugin/{$name}": ["type:cakephp-plugin"] + "app/Plugin/{$name}": [ + "type:cakephp-plugin" + ] } }, "require": { - "cakedc/migrations": "~2.2", - "netcommons/blocks": "@dev", - "netcommons/categories": "@dev", - "netcommons/frames": "@dev", - "netcommons/groups": "@dev", - "netcommons/holidays": "@dev", - "netcommons/mails": "@dev", - "netcommons/net-commons": "@dev", - "netcommons/pages": "@dev", - "netcommons/plugin-manager": "@dev", - "netcommons/rooms": "@dev", - "netcommons/topics": "@dev", - "netcommons/users": "@dev", - "netcommons/workflow": "@dev", - "netcommons/wysiwyg": "@dev" + "cakedc/migrations": "~2.2", + "netcommons/blocks": "@dev", + "netcommons/categories": "@dev", + "netcommons/frames": "@dev", + "netcommons/groups": "@dev", + "netcommons/holidays": "@dev", + "netcommons/mails": "@dev", + "netcommons/net-commons": "@dev", + "netcommons/pages": "@dev", + "netcommons/plugin-manager": "@dev", + "netcommons/rooms": "@dev", + "netcommons/topics": "@dev", + "netcommons/users": "@dev", + "netcommons/workflow": "@dev", + "netcommons/wysiwyg": "@dev" }, - "type": "cakephp-plugin", - "keywords": ["cakephp", "reservations"], + "type": "cakephp-plugin", + "keywords": [ + "cakephp", + "reservations" + ], "config": { "vendor-dir": "vendors" } -} +} \ No newline at end of file