소스 파일명 : items_update.php
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
<?php // (2018.2.19, 차재복, Cha Jae Bok, cjbword@gmailcom) 

# item_update.php
	// 용어 분류(이동) 및 지정/변경 등

# 호출하는 상위 스크립트는 정해진 것 만 제한적 허용 (해킹 방어)
	$script_filename = basename($_SERVER['SCRIPT_FILENAME']);
	if ( $script_filename != 'items.php' ) exit ('.');

# 화면 출력 지연
	$delay_echo = '';

# 편집자 여부 체킹
	if ( empty($_SESSION['user_name']) ) {
		$delay_echo .= "<span style='color:red;'>편집 권한 없음 !!! => 상단 우측 `로그인`을 클릭하여, `테스트 편집자(testuser)`로써 로그인 하시기 바랍니다.</span>";
		return;
	}

# 전달 파라미터 정리 
	// (전달 파라미터 요약 정리)
	// $_POST[para][source_id], $_POST[para][source_no], $_POST[para][target_id]
	// $_POST[action] => no_designate, 

	// 전체 전달 파라미터 출력 지연
	$delay_echo .= "<pre>"; $delay_echo.=print_r($_POST,true); $delay_echo.="</pre>";

# 전달 파라미터 해킹 방지
	$action = $_POST[action];
		$action = substr($action,0,13);												// 해킹 방지 (스트링 길이 제한)

	$title = $_POST[para][title];
		$title = mb_substr($title,0,20,'utf-8');									// 해킹 방지 (스트링 길이 제한)
		$title = mysqli_real_escape_string($dbi,$title);							// 해킹 방지 (sql injection 방지)
	
	$source_no = $_POST[para][source_no];
		if ($source_no!=null and strpos($source_no,',')===false and (!is_numeric($source_no) or $source_no<=0)) {
			return;										// 해킹방지 (수치 아니거나, 0 보다 작으면)
		} else if ($source_no!=null) {
			$source_no_arr = explode(',',$source_no);
			foreach($source_no_arr as $key=>$value) {
				if( !is_numeric($value) or $value<=0 ) {
					$delay_echo .= '$source_no 비어있음 !!!';
					return; 
				}
			}
		}
/*
		if ($source_no!=null and strpos($source_no,',')===false and (!is_numeric($source_no) or $source_no<=0)) {
			return; 															// 해킹방지 (수치 아니거나, 0 보다 작으면)
		} else if ($source_no!=null and strpos($source_no,',')!==false) {
			$source_no_arr = explode(',',$source_no);
			foreach($source_no_arr as $key=>$value) 
				if( !is_numeric($value) or $value<=0 ) return; 
		} 
*/
	$source_id = $_POST[para][source_id];
		if ($source_id!=null and (!is_numeric($source_id) or $source_id<=0)) exit;	// 해킹방지 (수치 아니거나, 0 보다 작으면)
	
	$target_id = $_POST[para][target_id];
		if ($target_id!=null and (!is_numeric($target_id) or $target_id<=0)) exit;	// 해킹방지 (수치 아니거나, 0 보다 작으면)



# 분류항목 업데이트 수행 루틴들

	// 분류항목 삭제 (id_delete)
	if ($action == 'id_delete' and !empty($source_id) and empty($title) and empty($target_id) and empty($source_no)) { 

		$delay_echo .= '$action='.$action.', $source_id='.$source_id."<br>";

		// 혹시나, 소스 id 를 부모로 갖는 id 여부 확인
 		$query = "select * from gubun_tree_v2 where parent=$source_id";
		$result = mysqli_query($dbi,$query);
		if (mysqli_num_rows($result) ) {
			$delay_echo .= "소스 id를 부모로 갖는 id 가 있어서 삭제 불가"."<br>";
		} else {
			$delay_echo .= "소스 id를 부모로 갖는 id 가 없어서 삭제 가능"."<br>";

			// 소스 id가 마지막이 아닌 중간 sub_seq이면, 이후 id sub_seq 1씩 감소시켜야 함
 			$query = "select parent,sub_seq,linked_num from gubun_tree_v2 where id=$source_id";
			$result = mysqli_query($dbi,$query);
				if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
			$matched=mysqli_fetch_assoc($result);
			$cur_sub_seq=$matched[sub_seq];
			$cur_parent=$matched[parent];
			
			if ( $matched[linked_num] ) {
				$delay_echo .= "해당 id 하부에 no가 있어서 삭제 불가"."<br>";
				return;
			} else {
				$query = "update gubun_tree_v2 set sub_seq=(sub_seq-1) where parent=$cur_parent and sub_seq>$cur_sub_seq";
				$result = mysqli_query($dbi,$query);
					if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
				if (mysqli_affected_rows($dbi)>=1) {
					$delay_echo .= "소스 id sub_seq 이후 1 씩 감소"."<br>";
				} else {
					$delay_echo .= "소스 id sub_seq 이후 1 씩 감소 없음 => (마지막인듯)"."<br>";
				}

				// 해당 id 삭제
				$query = "delete from gubun_tree_v2 where id=$source_id limit 1";
				$result = mysqli_query($dbi,$query);
				if (mysqli_affected_rows($dbi)==1) {
					$delay_echo .= "해당 분류항목 1개 삭제"."<br>";
					// 해당 id 삭제 후 화면을 parent 기준으로 보여주기 위함
					$source_id = $cur_parent;
				} else {
					$delay_echo .= "해당 분류항목 1개 삭제 => 실패"."<br>";
					if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
				}
			}
		}
	} 


	// 분류항목 명칭 변경 (id_rename)
	if ($action == 'id_rename' and !empty($source_id) and !empty($title) and $source_no==null and $target_id==null ) { 
		$delay_echo .= '$action='.$action.', $title='.$title.', $source_no='.$source_no.', $source_id='.$source_id.', $target_id='.$target_id."<br>";

		$query = "update gubun_tree_v2 set name='".$title."' where id=$source_id limit 1";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "분류 명칭 변경 됨 ($title)"."<br>";
		} else {
			$delay_echo .= "분류 명칭 변경 안됨"."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
		$delay_echo .= "<hr>";
	}


	// 분류항목 직전 생성 (id_gen_before)
	if ($action == 'id_gen_before' and !empty($source_id) and !empty($title) and empty($target_id) and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $title='.$title.', $source_id='.$source_id."<br>";

		// 소스 id의 부모,부번호를 알아냄
 		$query = "select parent,sub_seq from gubun_tree_v2 where id=$source_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched=mysqli_fetch_assoc($result);
		$parent = $matched[parent];
		$sub_seq = $matched[sub_seq];

		$delay_echo .= "<br>parent=".$parent.", sub_seq=".$sub_seq;
		$delay_echo .= "<br>".$query."<br>";

		// 소스 id 부터 1씩 증가시킴
 		$query = "update gubun_tree_v2 set sub_seq=(sub_seq+1) where parent=$parent and sub_seq>=$sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "소스 id 부터 1씩 증가시킴"."<br>";
		} else {
			$delay_echo .= "소스 id 부터 1씩 증가시킴 => 실패 (마지막일 수도 있음)"."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// id 중 빈 번호 확인
		$query = "select a.id + 1 as available from gubun_tree_v2 a left join gubun_tree_v2 b on b.id = (a.id + 1) where b.id is null order by a.id limit 0,1";
		$result=mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$temp_id=mysqli_fetch_assoc($result);

		$delay_echo .= "<br>"."new id=".$temp_id[available]."<br>";

		// 분류항목 새로이 삽입
		$query = "insert into gubun_tree_v2 (id,parent,sub_seq,name,linked_num) values (".$temp_id[available].",$parent,$sub_seq,'".$title."',0)";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "분류항목 새로이 삽입시킴"."<br>";
		} else {
			$delay_echo .= "분류항목 새로이 삽입시킴 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 삽입된 항목에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($temp_id[available],$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id=".$temp_id[available];
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "삽입된 항목에 path2node,path 업데이트"."<br>";
		} else {
			$delay_echo .= "삽입된 항목에 path2node,path 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	} 


	// 분류항목 직후 생성 (id_gen_after)
	if ($action == 'id_gen_after' and !empty($source_id) and !empty($title) and empty($target_id) and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $title='.$title.', $source_id='.$source_id."<br>";

		// 소스 id의 부모,부번호를 알아냄
 		$query = "select parent,sub_seq from gubun_tree_v2 where id=$source_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched=mysqli_fetch_assoc($result);
		$parent = $matched[parent];
		$sub_seq = $matched[sub_seq];

		$delay_echo .= "<br>parent=".$parent.", sub_seq=".$sub_seq;
		$delay_echo .= "<br>".$query."<br>";

		// 소스 id 직후부터 1씩 증가시킴
 		$query = "update gubun_tree_v2 set sub_seq=(sub_seq+1) where parent=$parent and sub_seq>=($sub_seq+1)";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "소스 id 직후부터 1씩 증가시킴"."<br>";
		} else {
			$delay_echo .= "소스 id 직후부터 1씩 증가시킴 => 실패 (마지막일 수도 있음)"."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// id 중 빈 번호 확인
		$query = "select a.id + 1 as available from gubun_tree_v2 a left join gubun_tree_v2 b on b.id = (a.id + 1) where b.id is null order by a.id limit 0,1";
		$result=mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$temp_id=mysqli_fetch_assoc($result);

		$delay_echo .= "<br>"."new id=".$temp_id[available]."<br>";

		// 분류항목 새로이 삽입
		$query = "insert into gubun_tree_v2 (id,parent,sub_seq,name,linked_num) values (".$temp_id[available].",$parent,$sub_seq+1,'".$title."',0)";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "분류항목 새로이 삽입시킴"."<br>";
		} else {
			$delay_echo .= "분류항목 새로이 삽입시킴 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 삽입된 항목에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($temp_id[available],$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id=".$temp_id[available];
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "삽입된 항목에 path2node,path 업데이트"."<br>";
		} else {
			$delay_echo .= "삽입된 항목에 path2node,path 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	} 


	// 분류항목 자식 생성 (id_gen_after)
	if ($action == 'id_gen_child' and !empty($source_id) and !empty($title) and empty($target_id) and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $title='.$title.', $source_id='.$source_id."<br>";

		// 소스 id의 자식 존재 알아보기
 		$query = "select * from gubun_tree_v2 where parent=$source_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		if ( $max_sub_seq = mysqli_num_rows($result) ) {
			$delay_echo .= "자식 최대수=".$max_sub_seq."<br>";
		} else {
			$delay_echo .= "자식이 없으므로 max_sub_seq=1"."<br>";
			$max_sub_seq = 1;
		}

		// id 중 빈 번호 확인
		$query = "select a.id + 1 as available from gubun_tree_v2 a left join gubun_tree_v2 b on b.id = (a.id + 1) where b.id is null order by a.id limit 0,1";
		$result=mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$temp_id=mysqli_fetch_assoc($result);

		$delay_echo .= "new id=".$temp_id[available]."<br>";

		// 분류항목 새로이 삽입
		$query = "insert into gubun_tree_v2 (id,parent,sub_seq,name,linked_num) values (".$temp_id[available].",$source_id,$max_sub_seq,'".$title."',0)";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "분류항목 새로이 삽입시킴"."<br>";
		} else {
			$delay_echo .= "분류항목 새로이 삽입시킴 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 삽입된 항목에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($temp_id[available],$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id=".$temp_id[available];
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "삽입된 항목에 path2node,depth 업데이트"."<br>";
		} else {
			$delay_echo .= "삽입된 항목에 path2node,depth 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	}


	// 분류항목 직후 이동 (id_after)
	if ($action == 'id_after' and !empty($source_id) and !empty($target_id) and empty($title) and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $title='.$title.', $source_no='.$source_no.', $source_id='.$source_id.', $target_id='.$target_id."<br>";

		// 소스쪽 이동 항목을 발췌하면, 나머지 항목 부번호들은 1씩 감해짐
		$query = "update gubun_tree_v2 a left join (select parent,sub_seq from gubun_tree_v2 where id=$source_id) b on a.parent=b.parent set a.sub_seq=(a.sub_seq-1) where a.sub_seq>b.sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐"."<br>";
		} else {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 타깃 항목의 부모,부번호를 알아냄
 		$query = "select parent,sub_seq from gubun_tree_v2 where id=$target_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched=mysqli_fetch_assoc($result);
		$parent = $matched[parent];
		$sub_seq = $matched[sub_seq];

		$delay_echo .= "<br>parent=".$parent.", sub_seq=".$sub_seq;
		$delay_echo .= "<br>".$query."<br>";

		// 타킷쪽 목적 항목 이후 부번호들을 1씩 증가시킴
 		$query = "update gubun_tree_v2 set sub_seq=(sub_seq+1) where parent=$parent and sub_seq>$sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "타킷쪽 목적 항목 이후 부번호들이 1씩 증가됨"."<br>";
		} else {
			$delay_echo .= "타킷쪽 목적 항목 이후 부번호들이 1씩 증가됨 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 소스 항목을 타킷 항목에 맞춰 수정(이동)
		$query = "update gubun_tree_v2 set parent=$parent,sub_seq=($sub_seq+1) where id=$source_id";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "소스 항목을 타킷 항목에 맞춰 수정(이동)"."<br>";
		} else {
			$delay_echo .= "소스 항목을 타킷 항목에 맞춰 수정(이동) => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 직후이동한 분류항목(source_id)에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($source_id,$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id={$source_id}";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "직후이동한 분류항목에 path2node,depth 업데이트"."<br>";
		} else {
			$delay_echo .= "직후이동한 분류항목에 path2node,depth 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	}


	// 분류항목 직전 이동 (id_before)
	if ($action == 'id_before' and !empty($source_id) and !empty($target_id) and empty($title) and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $title='.$title.', $source_no='.$source_no.', $source_id='.$source_id.', $target_id='.$target_id."<br>";

		// 소스쪽 이동 항목을 발췌하면, 나머지 항목 부번호들은 1씩 감해짐
		$query = "update gubun_tree_v2 a left join (select parent,sub_seq from gubun_tree_v2 where id=$source_id) b on a.parent=b.parent set a.sub_seq=(a.sub_seq-1) where a.sub_seq>b.sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐"."<br>";
		} else {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 타깃 항목의 부모,부번호를 알아냄
 		$query = "select parent,sub_seq from gubun_tree_v2 where id=$target_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched=mysqli_fetch_assoc($result);
		$parent = $matched[parent];
		$sub_seq = $matched[sub_seq];

		$delay_echo .= "<br>parent=".$parent.", sub_seq=".$sub_seq;
		$delay_echo .= "<br>".$query."<br>";

		// 타킷쪽 목적 항목부터 부번호들을 1씩 증가시킴
 		$query = "update gubun_tree_v2 set sub_seq=(sub_seq+1) where parent=$parent and sub_seq>=$sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "타킷쪽 목적 항목부터 부번호들이 1씩 증가됨"."<br>";
		} else {
			$delay_echo .= "타킷쪽 목적 항목부터 부번호들이 1씩 증가됨 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 소스 항목을 타킷 항목에 맞춰 수정(이동)
		$query = "update gubun_tree_v2 set parent=$parent,sub_seq=($sub_seq) where id=$source_id";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "소스 항목을 타킷 항목에 맞춰 수정(이동)"."<br>";
		} else {
			$delay_echo .= "소스 항목을 타킷 항목에 맞춰 수정(이동) => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 직전이동한 분류항목(source_id)에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($source_id,$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id={$source_id}";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "직전이동한 분류항목에 path2node,depth 업데이트"."<br>";
		} else {
			$delay_echo .= "직전이동한 분류항목에 path2node,depth 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	}


	// 분류항목 자식 이동 (id_child)
	if ($action == 'id_child' and !empty($source_id) and !empty($target_id) and $title==null and $source_no==null) { 

		$delay_echo .= '$action='.$action.', $source_id='.$source_id.', $target_id='.$target_id."<br>";

		// 소스쪽 이동 항목을 발췌하면, 나머지 항목 부번호들은 1씩 감해짐
		$query = "update gubun_tree_v2 a left join (select parent,sub_seq from gubun_tree_v2 where id=$source_id) b on a.parent=b.parent set a.sub_seq=(a.sub_seq-1) where a.sub_seq>b.sub_seq";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐"."<br>";
		} else {
			$delay_echo .= "소스쪽 나머지 항목 부번호들이 1씩 감해짐 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 타킷 항목의 하부 자식번호 중 최대 알아내기
		$query = "select ifnull(max(sub_seq),0)+1 as max_num from gubun_tree_v2 where parent=$target_id";
		$result = mysqli_query($dbi,$query);
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched=mysqli_fetch_assoc($result);
		$max_num = $matched[max_num];

		// 소스 항목을 타킷 항목의 하부 자식으로 수정(이동)
		$query = "update gubun_tree_v2 set parent=$target_id,sub_seq=$max_num where id=$source_id";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "소스 항목을 타킷 항목의 하부 자식으로 수정(이동)"."<br>";
		} else {
			$delay_echo .= "소스 항목을 타킷 항목의 하부 자식으로 수정(이동) => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		$delay_echo .= "<br>".$query."<br>";

		// 자식이동한 분류항목(source_id)에 path2node, depth 업데이트
		$delay_echo .= path_depth_update ($source_id,$delay_echo,$dbi);
/*
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id={$source_id}";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "자식이동한 분류항목에 path2node,depth 업데이트"."<br>";
		} else {
			$delay_echo .= "자식이동한 분류항목에 path2node,depth 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
*/
	}


# 용어해설항목 업데이트 수행 루틴들 

	// 용어해설항목 순서번호 상향 또는 하향 조정 (no_up 또는 no_down)
	if ( ($action == 'no_up' or $action == 'no_down') and !empty($source_no) and !empty($source_id) and $title==null and $target_id == null) { 

		$delay_echo .= '$action='.$action.', $source_no='.$source_no.', $source_id='.$source_id."<br>";

		// 일단 소팅하고, 번호 새로 매기기
		mysqli_query($dbi,"set @rank:=0");
		mysqli_query($dbi,"update book_idx set list_ord = @rank := @rank+1 where tree_id=$source_id order by list_ord,titlename");
		if (mysqli_errno($dbi)) {
			$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";
		} else {
			$delay_echo .= "일단 소팅하고, 번호 새로 매기기"."<br>";
		}

		// 선택 항목의 순서번호 알아보기
		$result = mysqli_query($dbi,"select list_ord from book_idx where tree_id=$source_id and no=$source_no");
			if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		$matched = mysqli_fetch_assoc($result);
		$cur_list_ord = $matched[list_ord];

		$delay_echo .= "선택 항목의 순서번호 알아보기 cur_list_ord=$cur_list_ord"."<br>";

		// (no_up) 
		if ( $action == 'no_up' ) {
			// 직전 것을 하향 이동
			mysqli_query($dbi,"update book_idx set list_ord=(list_ord+1) where tree_id=$source_id and list_ord=($cur_list_ord-1)");
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}

			// (no_up) 자신을 상향 이동
			mysqli_query($dbi,"update book_idx set list_ord=($cur_list_ord-1) where tree_id=$source_id and no=$source_no and list_ord=($cur_list_ord)");
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		} else if ( $action == 'no_down' ) {
			// (no_down) 직후 것을 상향 이동
			mysqli_query($dbi,"update book_idx set list_ord=(list_ord-1) where tree_id=$source_id and list_ord=($cur_list_ord+1)");
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}

			// (no_up) 자신을 하향 이동
			mysqli_query($dbi,"update book_idx set list_ord=(list_ord+1) where tree_id=$source_id and no=$source_no and list_ord=($cur_list_ord)");
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 순서번호 검증 테스트
		$result = mysqli_query($dbi,"select no,list_ord from book_idx where tree_id=$source_id order by list_ord");
		$i=1;
		while ($matched=mysqli_fetch_assoc($result)) {
			// 변경 전후
			if ($matched[no] == $source_no) {
				$delay_echo .= '$source_no='.$source_no.', old_list_ord='.$cur_list_ord.', new_list_ord='.$matched[list_ord]."<br>";
			}
			// 연속성 검증
			if( $i == $matched[list_ord] ) {
				$i=$i+1;
			} else {
				$delay_echo .= "순서번호가 연속적이지 아님";
			}
		}

	}


	// 용어해설항목 분류 삭제 (no_delete)
	if ($action == 'no_delete' and !empty($source_no) and !empty($source_id) ) { 
//		echo "<pre>";print_r($_POST);echo "</pre>";

		// 해당 용어항목 순서를 알아냄
		$query = "select list_ord from book_idx where tree_id=$source_id and no=$source_no limit 1";
		$result = mysqli_query($dbi,$query);
		$row = mysqli_fetch_assoc($result);

		// 해당 용어항목 직후부터 순서번호 모두 1씩 감함
		$query = "update book_idx set list_ord=(list_ord-1) where tree_id=$source_id and list_ord>$row[list_ord]";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi) >= 1) {
			$delay_echo .= "해당 용어항목 직후부터 순서번호 모두 1씩 감함"."<br>";
		} else {
			$delay_echo .= "해당 용어항목 직후부터 순서번호 모두 1씩 감함 => 실패"."<br>";
			if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 해당 용어항목 순서번호 삭제
		$query = "delete from book_idx where tree_id=$source_id and no=$source_no limit 1"; 
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "해당 용어항목 순서번호 삭제"."<br>";
		} else {
			$delay_echo .= "해당 용어항목 순서번호 삭제 => 실패"."<br>";
			if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

		// 해당 분류에 속한 용어들 갯수 update
		$query = "update gubun_tree_v2 set linked_num=(select count(*) from book_idx where tree_id=$source_id) where id=$source_id";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "해당 분류에 속한 용어들 갯수 update 성공"."<br>";
		}

	}


	// 용어해설항목 명칭 변경 (no_rename)
	if ($action == 'no_rename' and !empty($source_no) and !empty($source_id) and !empty($title) and $target_id == null) { 

		$delay_echo .= '$action='.$action.', $source_no='.$source_no.', $source_id='.$source_id.', $title='.$title."<br>";

		$query = "update book_idx set titlename='".$title."' where tree_id=$source_id and no=$source_no limit 1";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)==1) {
			$delay_echo .= "용어 명칭 변경 됨 ($title)"."<br>";
		} else {
			$delay_echo .= "용어 명칭 변경 안됨"."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

	}

/*
	// 용어해설항목 분류 지정 (no_designate)
	if ( $action == 'no_designate' and !empty($source_no) and !empty($target_id) and $source_no_arr==null ) { 

		$delay_echo .= '$action='.$action.', $source_no='.$source_no.', $target_id='.$target_id."<br>";

		// 이미 분류되어진 것 있는가 여부를 체크($temp1 검색) 후 분류 작업 ";
		$result=mysqli_query($dbi,"select * from book_idx where no=$source_no and tree_id=$target_id");
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		if (mysqli_num_rows($result)) {
			$dealy .= "<br>이미 해당 id에 기 분류되어짐"."<br>";
		} else {
			// 전달된 no를 해당 분류 id에 지정
			$query = "insert into book_idx (no,list_ord,tree_id,titlename) select $source_no,max(list_ord)+1 as list_ord,$target_id,(select word from dict_word_list where no=$source_no and wordtype='k' limit 1) from book_idx where tree_id=$target_id limit 1";
			$result = mysqli_query($dbi,$query);
			if ($result or mysqli_affected_rows($dbi)==1) {
				$delay_echo .= "전달된 no를 해당 분류 id에 지정 삽입"."<br>";

				// 해당 분류에 속한 용어들 갯수 update
				$query = "update gubun_tree_v2 set linked_num=(select count(*) from book_idx where tree_id=$target_id) where id=$target_id";
				$result = mysqli_query($dbi,$query);
				if (mysqli_affected_rows($dbi)==1) {
					$delay_echo .= "해당 분류에 속한 용어들 갯수 update 성공"."<br>";
				}
			} else {
				$delay_echo .= "전달된 no를 해당 분류 id에 지정 삽입 => 실패"."<br>";
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
			}
		}

	}
*/

	// 다수의 용어해설항목을 한꺼번에 분류 지정 (no_designate)
	if ( $action == 'no_designate' and is_array($source_no_arr) and !empty($target_id)  ) { 
														// and strpos($source_no,',')!==false

		$delay_echo .= '$action='.$action.'(다수 no들 분류 지정), $target_id='.$target_id."<br>";

		$delay_echo.="<pre>"; $delay_echo.=print_r($source_no_arr,true); $delay_echo.="</pre>";

		// 여러 소스 no들을 ','로 구분
		$source_no_list = implode(',',$source_no_arr);

		// 이미 분류되어진 것 있는가 여부를 체크($temp1 검색) 후 분류 작업 ";
		$result=mysqli_query($dbi,"select * from book_idx where no in ($source_no_list) and tree_id=$target_id");
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		if ($nums = mysqli_num_rows($result)) {
			$delay_echo .= "이미 해당 id에 기 분류되어진 것들({$source_no_list})이 ($nums)개 있음"."<br>";
		} else {
			$delay_echo .= "해당 id에 기 분류되어진 것들({$source_no_list})이 없음"."<br>";

			// 현재 list_ord 중 최대값 구하기
			mysqli_query($dbi,"select @max:=max(list_ord) from book_idx where tree_id=$target_id");
				if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}

			// 전달된 다수 no들을 해당 분류 id에 지정
			$query = "insert into book_idx
						(no,tree_id,titlename,list_ord) 
						( select no,{$target_id} as tree_id,word,@max:=@max+1 as list_ord from dict_word_list where no in ({$source_no_list}) and wordtype='k' group by no )
					 ";
			$result = mysqli_query($dbi,$query);
			if ( mysqli_affected_rows($dbi)>=1) {
				$delay_echo .= "전달된 여러 no 들을 해당 분류 id에 지정 삽입"."<br>";

				// 해당 분류에 속한 용어들 갯수 update
				$query = "update gubun_tree_v2 set linked_num=(select count(*) from book_idx where tree_id=$target_id) where id=$target_id";
				$result = mysqli_query($dbi,$query);
				if (mysqli_affected_rows($dbi)==1) {
					$delay_echo .= "해당 분류에 속한 용어들 갯수 update 성공"."<br>";
				}
			} else {
				$delay_echo .= "전달된 여러 no 들을 해당 분류 id에 지정 삽입 => 실패"."<br>";
				if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
			}
		}

	}


	// 다수의 용어해설항목을 한꺼번에 분류 변경 (no_change)
	if ($action == 'no_change' and is_array($source_no_arr) and !empty($target_id) and !empty($source_id) ) { 
																	// and strpos($source_no,',')!==false

		$delay_echo .= 'action='.$action.'(다수 no들 분류 변경), target_id='.$target_id.', source_id='.$source_id."<br>";

		$delay_echo.="<pre>"; $delay_echo.=print_r($source_no_arr,true); $delay_echo.="</pre>";

		// 여러 소스 no들을 ','로 구분
		$source_no_list = implode(',',$source_no_arr);

		// 해당 소스들의 no,list_ord,titlename들을 알아냄
		$query = "select no,list_ord,titlename from book_idx where tree_id=$source_id and no in ($source_no_list)";
		$result = mysqli_query($dbi,$query);
		while ($matched = mysqli_fetch_assoc($result)) {
			$delay_echo .= 'no='.$matched[no].', list_osr='.$matched[list_ord].', titlename='.$matched[titlename].'<br>';
		}

		// 현재 target_id에서 list_ord 중 최대값 구하기
		mysqli_query($dbi,"select @max:=max(list_ord) from book_idx where tree_id=$target_id");
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}

		// 추출된 no들의 id를 target_id로 바꾸고, list_ord 업데이트
		$query = "update
					book_idx a
					inner join 
					(
						select no,tree_id,@max:=@max+1 as list_ord from book_idx where tree_id=$source_id and no in ($source_no_list)
					) b
					on (a.tree_id=b.tree_id and a.no=b.no)
					set a.tree_id=$target_id,a.list_ord=b.list_ord
				";
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "추출된 no들의 id를 tree_id로 바꾸고, list_ord 업데이트 <br>";

			// source 분류에 속한 용어들 갯수 update
			$query = "update gubun_tree_v2 set linked_num=(select count(*) from book_idx where tree_id=$source_id) where id=$source_id";
			$result = mysqli_query($dbi,$query);
			if (mysqli_affected_rows($dbi)==1) {
				$delay_echo .= "source 분류 $source_id에 속한 용어들 갯수 update 성공"."<br>";
			}

			// target 분류에 속한 용어들 갯수 update
			$query = "update gubun_tree_v2 set linked_num=(select count(*) from book_idx where tree_id=$target_id) where id=$target_id";
			$result = mysqli_query($dbi,$query);
			if (mysqli_affected_rows($dbi)==1) {
				$delay_echo .= "target 분류 $target_id에 속한 용어들 갯수 update 성공"."<br>";
			}

		} else {
			$delay_echo .= "추출된 no들의 id를 tree_id로 바꾸고, list_ord 업데이트 => 실패 <br>";
			if (mysqli_errno($dbi)) {$delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}

	}


?>

<?php

// path2node, depth 업데이트 함수
function path_depth_update ($temp_id,$delay_echo,$dbi) {
		$query = "update gubun_tree_v2 set 
					path2node=concat(';0;;',replace(substring_index(getpath_v2(id),'|',-1),'::',';;'),';'),
					path2node_v2=concat('0,',replace(substring_index(getpath_v2(id),'|',-1),'::',',')),
					depth=round( ( length(path2node) - length(replace(path2node,';;','')) )/length(';;') )
					where id=".$temp_id;
		$result = mysqli_query($dbi,$query);
		if (mysqli_affected_rows($dbi)>=1) {
			$delay_echo .= "path2node,path 업데이트"."<br>";
		} else {
			$delay_echo .= "path2node,path 업데이트 => 실패 "."<br>";
			if (mysqli_errno($dbi)) { $delay_echo .= mysqli_errno($dbi)." : ".mysqli_error($dbi)."\n";}
		}
		return $delay_echo;
}

?>