-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCalendarSearchPlanBehavior.php
More file actions
291 lines (270 loc) · 10.3 KB
/
CalendarSearchPlanBehavior.php
File metadata and controls
291 lines (270 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<?php
/**
* CalendarSearchPlan Behavior
*
* @author Noriko Arai <arai@nii.ac.jp>
* @author Allcreator <info@allcreator.net>
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
*/
//プラグインセパレータ(.)とパスセバレータ(/)混在に注意
App::uses('CalendarAppBehavior', 'Calendars.Model/Behavior');
App::uses('Space', 'Rooms.Model');
App::uses('WorkflowComponent', 'Workflow.Controller/Component');
App::uses('CalendarPermissiveRooms', 'Calendars.Utility');
/**
* CalendarSearchPlanBehavior
*
* @property array $calendarWdayArray calendar weekday array カレンダー曜日配列
* @property array $editRrules editRules 編集ルール配列
* @author Allcreator <info@allcreator.net>
* @package NetCommons\Calendars\Model\Behavior
*/
class CalendarSearchPlanBehavior extends CalendarAppBehavior {
/**
* getPlans
*
* 予定一覧の取得
* (共有予定とのマージ処理を簡易化するため$order は key => valの1要素のみ、ASC, DESC指定はないものとする)
*
* @param Model $model 実際のモデル名
* @param array $vars カレンダー設定情報
* @param array $planParams 予定パラメータ
* @param array $order ソートパラメータ
* @return array 検索成功時 予定配列を返す。検索結果が0件の時は、空配列を返す。検索失敗した時はInternalError例外をthrowする。
* @throws InternalErrorException
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function getPlans(Model $model, $vars, $planParams, $order = array()) {
// 探すのはis_activeかis_latestのものだけでよい
$baseOptions = array(
'conditions' => array(
array(
'OR' => array(
'CalendarEvent.is_active' => true,
'CalendarEvent.is_latest' => true,
)
)
),
'recursive' => 1, //belongTo, hasOne, hasMany関係をもつ1階層上下を対象にする。
//'order' => array($model->alias . '.start_date'),
'order' => $order,
);
foreach ($planParams as $field => $val) {
$key = $model->alias . '.' . $field;
$field = trim($field);
switch ($field) {
case 'dtstart':
$key = $key . ' >=';
break;
case 'dtend':
$key = $key . ' <';
break;
case 'language_id':
$key = 1;
$vals = array(
'OR' => array(
$model->alias . '.' . $field => $val,
$model->alias . '.is_translation' => false
)
);
$val = $vals;
break;
default:
}
$baseOptions['conditions'][$key] = $val;
}
/////////////////////////////////////////
// 時間以外の絞り込み条件をここに書く。
//表示対象となるルームIDの一覧を取得し、IN条件を追加する.
//
$eventDotRoomId = $model->alias . '.room_id';
//カレンダー用の役割・権限情報一式取得
if (!$model->Behaviors->hasMethod('prepareCalRoleAndPerm')) {
$model->Behaviors->load('Calendars.CalendarRoleAndPerm');
}
$calRoleAndPerm = $model->prepareCalRoleAndPerm();
//専用の各参照配列に代入
$readableRoomIds = &$calRoleAndPerm['readableRoomIds'];
//$rooms = &$calRoleAndPerm['rooms'];
//$roleOfRooms = &$calRoleAndPerm['roleOfRooms'];
//$roomInfos = &$calRoleAndPerm['roomInfos'];
$options = $baseOptions;
$options['conditions'][$eventDotRoomId] = $readableRoomIds;
////$plans = $model->getWorkflowContents('all', $options);
$plans = $model->find('all', $options);
/*
CakeLog::debug("DBG: options[" . print_r($options, true) . "]\n");
foreach ($plans as $plan) {
CakeLog::debug("DBG: event id[" . $plan['CalendarEvent']['id'] .
"] key[" . $plan['CalendarEvent']['key'] .
"] dtstart[" . $plan['CalendarEvent']['dtstart'] .
"] room_id[" . $plan['CalendarEvent']['room_id'] .
"] title[" . $plan['CalendarEvent']['title'] .
"] status[" . $plan['CalendarEvent']['status'] .
"] is_active[" . $plan['CalendarEvent']['is_active'] .
"] is_latest[" . $plan['CalendarEvent']['is_latest'] .
"] created_user[" . $plan['CalendarEvent']['created_user'] .
"] modified_user[" . $plan['CalendarEvent']['modified_user'] .
"]\n\n");
}
*/
////plansを$calRoleAndPerm中の各配列を使いスクリーニングする
////=>screenPlansUsingGetable方式に変えたので以下はやめた HASHI
////$plans = $this->__screenPlans($model, $plans, $calRoleAndPerm);
//スクリーニング方法をCalendarEventのGetableEvnet()を使う方法に変えた HASHI
//FUJI$roomPermRoles = $model->prepareCalRoleAndPerm();
//FUJICalendarPermissiveRooms::$roomPermRoles = $roomPermRoles;
$plans = $model->screenPlansUsingGetable($plans);
$sharePlans = $this->_getSharePlans($model, $vars, $baseOptions);
/////////////////////////////////////////
//通常予定と仲間の予定をマージする。
$mergedPlans = $this->__mergePlans($plans, $sharePlans, $order);
return $mergedPlans;
}
/**
* _getSharePlans
*
* 共有予定を取得する
*
* @param Model $model モデル
* @param array $vars カレンダー情報
* @param array $baseOptions 基本検索条件
* @return array
*/
protected function _getSharePlans($model, $vars, $baseOptions) {
if ($vars['CalendarFrameSetting']['is_myroom'] == false) {
return array();
}
///////////////////////////////////////////////////////////////////////
//自ユーザーを共有指定している他人のプライベート予定をとってくる。
//ここは、上記のルームIDの範疇外になるので、別にfindして、plansに
//マージすることとする。自分のルームID以外で、かつ、ShareUserが自分である
//情報を取得する。
if (empty($vars['myself'])) {
return array();
}
$myself = $vars['myself'];
//optionsの再設定
$options = Hash::merge(array(
//'recursive' => 1, //baseOptionsで指定済
'fields' => array(
$model->alias . '.*',
$model->CalendarEventShareUser->alias . '.*',
////'count(' . $model->CalendarEventShareUser->alias . '.id) AS friend_share_plan',
$model->CalendarRrule->alias . '.*',
$model->Language->alias . '.*',
$model->TrackableCreator->alias . '.id',
$model->TrackableCreator->alias . '.handlename',
$model->TrackableUpdater->alias . '.id',
$model->TrackableUpdater->alias . '.handlename',
//$model->CalendarEventContent->alias . '.*',
),
'conditions' => array(
$model->CalendarEventShareUser->alias . '.id NOT' => null,
//$model->alias . '.room_id' => $privateRoomIds,
'NOT' => array(
$model->alias . '.room_id' => $myself
), // 自分以外のルーム
$model->CalendarEventShareUser->alias . '.share_user' => Current::read('User.id'),
),
'joins' => array(
array(
'table' => $model->CalendarEventShareUser->table,
'alias' => $model->CalendarEventShareUser->alias,
'type' => 'LEFT',
'conditions' => array(
$model->CalendarEventShareUser->alias . '.calendar_event_id' . ' = ' . $model->alias . '.id',
),
),
),
//'order' => $order, //baseOptionsで指定済
), $baseOptions);
//Workflow条件について)
//仲間の予定は、他人のプライベート予定なので、
//getWorkflowContents()を使うと、一時保存中の他人のプライベート予定もとってきてしまう。
//他人のプライベート予定の場合、
//status=発行済かつis_active=trueのものだけが表示可能としてよい。
//よって、conditionsにその条件を明示追加する。
//
$options['conditions'][$model->alias . '.status'] = WorkflowComponent::STATUS_PUBLISHED;
$options['conditions'][$model->alias . '.is_active'] = true;
$options['conditions'][$model->alias . '.exception_event_id'] = 0; //除外でないもの
$sharePlans = $model->getWorkflowContents('all', $options);
foreach ($sharePlans as &$sharePlan) {
//「仲間の予定」であることを擬似項目をつかって、マーキングしておく。
$sharePlan['CalendarEvent']['pseudo_friend_share_plan'] = 1;
}
return $sharePlans;
}
/**
* __mergePlans
*
* 通常の表示予定と共有された他人のプライベート予定のマージ関数
* (共有予定とのマージ処理を簡易化するため$order は key => valの1要素のみ、ASC, DESC指定はないものとする)
*
* @param array $plansA plansA
* @param array $plansB plansB
* @param array $order ソートパラメータ
* @return array マージした配列を返す。
* @SuppressWarnings(PHPMD)
*/
private function __mergePlans($plansA, $plansB, $order) {
list($orderModel, $orderField) = explode('.', array_shift($order));
$planA = array_shift($plansA);
$planB = array_shift($plansB);
$mergedPlans = array();
while ($planA !== null || $planB !== null) {
if ($planA === null) {
//plansAは終わった
if (! $this->__overwriteSameKeyEvent($mergedPlans, $planB)) {
$mergedPlans[] = $planB;
}
$planB = array_shift($plansB);
continue;
}
if ($planB === null) {
//plansBは終わった
if (! $this->__overwriteSameKeyEvent($mergedPlans, $planA)) {
$mergedPlans[] = $planA;
}
$planA = array_shift($plansA);
continue;
}
if ($planA[$orderModel][$orderField] < $planB[$orderModel][$orderField]) {
if (! $this->__overwriteSameKeyEvent($mergedPlans, $planA)) {
$mergedPlans[] = $planA;
}
$planA = array_shift($plansA);
} else {
if (! $this->__overwriteSameKeyEvent($mergedPlans, $planB)) {
$mergedPlans[] = $planB;
}
$planB = array_shift($plansB);
}
}
return $mergedPlans;
}
/**
* __overwriteSameKeyEvent
*
* $mergedPlansの中に、$planと同一キーでid値がより大きいeventがあればplanを上書きする
*
* @param array &$mergedPlans mergedPlans
* @param array $plan plan
* @return bool 上書き実行されればtrue。上書き実行されなければfalse。
*/
private function __overwriteSameKeyEvent(&$mergedPlans, $plan) {
foreach ($mergedPlans as &$mergedPlan) {
if ($mergedPlan['CalendarEvent']['key'] == $plan['CalendarEvent']['key']) {
if ($mergedPlan['CalendarEvent']['id'] < $plan['CalendarEvent']['id']) {
//key一致で後出のeventのidの方が大きければ上書きして抜ける。
$mergedPlan = $plan;
return true;
}
}
}
return false;
}
}