Changeset 25281 for trunk/include
- Timestamp:
- Nov 1, 2013, 12:03:10 PM (11 years ago)
- Location:
- trunk/include
- Files:
-
- 10 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/ws_functions.inc.php
r25276 r25281 22 22 // +-----------------------------------------------------------------------+ 23 23 24 /**** IMPLEMENTATION OF WEB SERVICE METHODS ***********************************/25 26 24 /** 27 25 * Event handler for method invocation security check. Should return a PwgError … … 207 205 } 208 206 209 function ws_getMissingDerivatives($params, $service) 210 { 211 if ( empty($params['types']) ) 212 { 213 $types = array_keys(ImageStdParams::get_defined_type_map()); 214 } 215 else 216 { 217 $types = array_intersect(array_keys(ImageStdParams::get_defined_type_map()), $params['types']); 218 if (count($types)==0) 219 { 220 return new PwgError(WS_ERR_INVALID_PARAM, "Invalid types"); 221 } 222 } 223 224 $max_urls = $params['max_urls']; 225 list($max_id, $image_count) = pwg_db_fetch_row( pwg_query('SELECT MAX(id)+1, COUNT(*) FROM '.IMAGES_TABLE) ); 226 227 if (0 == $image_count) 228 { 229 return array(); 230 } 231 232 $start_id = intval($params['prev_page']); 233 if ($start_id<=0) 234 { 235 $start_id = $max_id; 236 } 237 238 $uid = '&b='.time(); 207 /** 208 * Writes info to the log file 209 */ 210 function ws_logfile($string) 211 { 239 212 global $conf; 240 $conf['question_mark_in_urls'] = $conf['php_extension_in_urls'] = true; 241 $conf['derivative_url_style']=2; //script 242 243 $qlimit = min(5000, ceil(max($image_count/500, $max_urls/count($types)))); 244 $where_clauses = ws_std_image_sql_filter( $params, '' ); 245 $where_clauses[] = 'id<start_id'; 246 if ( !empty($params['ids']) ) 247 { 248 $where_clauses[] = 'id IN ('.implode(',',$params['ids']).')'; 249 } 250 251 $query_model = 'SELECT id, path, representative_ext, width,height,rotation 252 FROM '.IMAGES_TABLE.' 253 WHERE '.implode(' AND ', $where_clauses).' 254 ORDER BY id DESC 255 LIMIT '.$qlimit; 256 257 $urls=array(); 258 do 259 { 260 $result = pwg_query( str_replace('start_id', $start_id, $query_model)); 261 $is_last = pwg_db_num_rows($result) < $qlimit; 262 while ($row=pwg_db_fetch_assoc($result)) 263 { 264 $start_id = $row['id']; 265 $src_image = new SrcImage($row); 266 if ($src_image->is_mimetype()) 267 continue; 268 foreach($types as $type) 269 { 270 $derivative = new DerivativeImage($type, $src_image); 271 if ($type != $derivative->get_type()) 272 continue; 273 if (@filemtime($derivative->get_path())===false) 274 { 275 $urls[] = $derivative->get_url().$uid; 276 } 277 } 278 if (count($urls)>=$max_urls && !$is_last) 279 break; 280 } 281 if ($is_last) 282 { 283 $start_id = 0; 284 } 285 }while (count($urls)<$max_urls && $start_id); 286 287 $ret = array(); 288 if ($start_id) 289 { 290 $ret['next_page']=$start_id; 291 } 292 $ret['urls']=$urls; 293 return $ret; 294 } 295 296 /** 297 * returns PWG version (web service method) 298 */ 299 function ws_getVersion($params, $service) 300 { 301 global $conf; 302 if ( $conf['show_version'] or is_admin() ) 303 { 304 return PHPWG_VERSION; 305 } 306 else 307 { 308 return new PwgError(403, 'Forbidden'); 309 } 310 } 311 312 /** 313 * returns general informations (web service method) 314 */ 315 function ws_getInfos($params, $service) 316 { 317 $infos['version'] = PHPWG_VERSION; 318 319 $query = 'SELECT COUNT(*) FROM '.IMAGES_TABLE.';'; 320 list($infos['nb_elements']) = pwg_db_fetch_row(pwg_query($query)); 321 322 $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.';'; 323 list($infos['nb_categories']) = pwg_db_fetch_row(pwg_query($query)); 324 325 $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.' WHERE dir IS NULL;'; 326 list($infos['nb_virtual']) = pwg_db_fetch_row(pwg_query($query)); 327 328 $query = 'SELECT COUNT(*) FROM '.CATEGORIES_TABLE.' WHERE dir IS NOT NULL;'; 329 list($infos['nb_physical']) = pwg_db_fetch_row(pwg_query($query)); 330 331 $query = 'SELECT COUNT(*) FROM '.IMAGE_CATEGORY_TABLE.';'; 332 list($infos['nb_image_category']) = pwg_db_fetch_row(pwg_query($query)); 333 334 $query = 'SELECT COUNT(*) FROM '.TAGS_TABLE.';'; 335 list($infos['nb_tags']) = pwg_db_fetch_row(pwg_query($query)); 336 337 $query = 'SELECT COUNT(*) FROM '.IMAGE_TAG_TABLE.';'; 338 list($infos['nb_image_tag']) = pwg_db_fetch_row(pwg_query($query)); 339 340 $query = 'SELECT COUNT(*) FROM '.USERS_TABLE.';'; 341 list($infos['nb_users']) = pwg_db_fetch_row(pwg_query($query)); 342 343 $query = 'SELECT COUNT(*) FROM '.GROUPS_TABLE.';'; 344 list($infos['nb_groups']) = pwg_db_fetch_row(pwg_query($query)); 345 346 $query = 'SELECT COUNT(*) FROM '.COMMENTS_TABLE.';'; 347 list($infos['nb_comments']) = pwg_db_fetch_row(pwg_query($query)); 348 349 // first element 350 if ($infos['nb_elements'] > 0) 351 { 352 $query = 'SELECT MIN(date_available) FROM '.IMAGES_TABLE.';'; 353 list($infos['first_date']) = pwg_db_fetch_row(pwg_query($query)); 354 } 355 356 // unvalidated comments 357 if ($infos['nb_comments'] > 0) 358 { 359 $query = 'SELECT COUNT(*) FROM '.COMMENTS_TABLE.' WHERE validated=\'false\';'; 360 list($infos['nb_unvalidated_comments']) = pwg_db_fetch_row(pwg_query($query)); 361 } 362 363 foreach ($infos as $name => $value) 364 { 365 $output[] = array( 366 'name' => $name, 367 'value' => $value, 368 ); 369 } 370 371 return array('infos' => new PwgNamedArray($output, 'item')); 372 } 373 374 function ws_caddie_add($params, $service) 375 { 376 global $user; 377 $query = ' 378 SELECT id 379 FROM '.IMAGES_TABLE.' LEFT JOIN '.CADDIE_TABLE.' ON id=element_id AND user_id='.$user['id'].' 380 WHERE id IN ('.implode(',',$params['image_id']).') 381 AND element_id IS NULL'; 382 $datas = array(); 383 foreach ( array_from_query($query, 'id') as $id ) 384 { 385 $datas[] = array('element_id'=>$id, 'user_id'=>$user['id']); 386 } 387 if (count($datas)) 388 { 389 mass_inserts( 390 CADDIE_TABLE, 391 array('element_id','user_id'), 392 $datas 393 ); 394 } 395 return count($datas); 396 } 397 398 /** 399 * returns images per category (web service method) 400 */ 401 function ws_categories_getImages($params, $service) 402 { 403 global $user, $conf; 404 405 $images = array(); 406 407 //------------------------------------------------- get the related categories 408 $where_clauses = array(); 409 foreach($params['cat_id'] as $cat_id) 410 { 411 if ($params['recursive']) 412 { 413 $where_clauses[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.$cat_id.'(,|$)\''; 414 } 415 else 416 { 417 $where_clauses[] = 'id='.$cat_id; 418 } 419 } 420 if (!empty($where_clauses)) 421 { 422 $where_clauses = array( '('. 423 implode(' 424 OR ', $where_clauses) . ')' 425 ); 426 } 427 $where_clauses[] = get_sql_condition_FandF( 428 array('forbidden_categories' => 'id'), 429 NULL, true 430 ); 431 432 $query = ' 433 SELECT id, name, permalink, image_order 434 FROM '.CATEGORIES_TABLE.' 435 WHERE '. implode(' 436 AND ', $where_clauses); 437 $result = pwg_query($query); 438 $cats = array(); 439 while ($row = pwg_db_fetch_assoc($result)) 440 { 441 $row['id'] = (int)$row['id']; 442 $cats[ $row['id'] ] = $row; 443 } 444 445 //-------------------------------------------------------- get the images 446 if ( !empty($cats) ) 447 { 448 $where_clauses = ws_std_image_sql_filter( $params, 'i.' ); 449 $where_clauses[] = 'category_id IN (' 450 .implode(',', array_keys($cats) ) 451 .')'; 452 $where_clauses[] = get_sql_condition_FandF( array( 453 'visible_images' => 'i.id' 454 ), null, true 455 ); 456 457 $order_by = ws_std_image_sql_order($params, 'i.'); 458 if ( empty($order_by) 459 and count($params['cat_id'])==1 460 and isset($cats[ $params['cat_id'][0] ]['image_order']) 461 ) 462 { 463 $order_by = $cats[ $params['cat_id'][0] ]['image_order']; 464 } 465 $order_by = empty($order_by) ? $conf['order_by'] : 'ORDER BY '.$order_by; 466 467 $query = ' 468 SELECT i.*, GROUP_CONCAT(category_id) AS cat_ids 469 FROM '.IMAGES_TABLE.' i 470 INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id 471 WHERE '. implode(' 472 AND ', $where_clauses).' 473 GROUP BY i.id 474 '.$order_by.' 475 LIMIT '.$params['per_page'].' OFFSET '.($params['per_page']*$params['page']); 476 477 $result = pwg_query($query); 478 while ($row = pwg_db_fetch_assoc($result)) 479 { 480 $image = array(); 481 foreach ( array('id', 'width', 'height', 'hit') as $k ) 482 { 483 if (isset($row[$k])) 484 { 485 $image[$k] = (int)$row[$k]; 486 } 487 } 488 foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 489 { 490 $image[$k] = $row[$k]; 491 } 492 $image = array_merge( $image, ws_std_get_urls($row) ); 493 494 $image_cats = array(); 495 foreach ( explode(',', $row['cat_ids']) as $cat_id ) 496 { 497 $url = make_index_url( 498 array( 499 'category' => $cats[$cat_id], 500 ) 501 ); 502 $page_url = make_picture_url( 503 array( 504 'category' => $cats[$cat_id], 505 'image_id' => $row['id'], 506 'image_file' => $row['file'], 507 ) 508 ); 509 $image_cats[] = array ( 510 'id' => (int)$cat_id, 511 'url' => $url, 512 'page_url' => $page_url, 513 ); 514 } 515 516 $image['categories'] = new PwgNamedArray( 517 $image_cats,'category', array('id','url','page_url') 518 ); 519 $images[] = $image; 520 } 521 } 522 523 return array ( 524 'paging' => new PwgNamedStruct( 525 array( 526 'page' => $params['page'], 527 'per_page' => $params['per_page'], 528 'count' => count($images) 529 ) ), 530 'images' => new PwgNamedArray($images, 'image', ws_std_get_image_xml_attributes() ) 531 ); 532 } 533 534 535 /** 536 * create a tree from a flat list of categories, no recursivity for high speed 537 */ 538 function categories_flatlist_to_tree($categories) 539 { 540 $tree = array(); 541 $key_of_cat = array(); 542 543 foreach ($categories as $key => &$node) 544 { 545 $key_of_cat[$node['id']] = $key; 546 547 if (!isset($node['id_uppercat'])) 548 { 549 $tree[] = &$node; 550 } 551 else 552 { 553 if (!isset($categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'])) 554 { 555 $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'] = new PwgNamedArray(array(), 'category', ws_std_get_category_xml_attributes()); 556 } 557 558 $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories']->_content[] = &$node; 559 } 560 } 561 562 return $tree; 563 } 564 565 /** 566 * returns a list of categories (web service method) 567 */ 568 function ws_categories_getList($params, $service) 569 { 570 global $user,$conf; 571 572 $where = array('1=1'); 573 $join_type = 'INNER'; 574 $join_user = $user['id']; 575 576 if (!$params['recursive']) 577 { 578 if ($params['cat_id']>0) 579 $where[] = '(id_uppercat='.(int)($params['cat_id']).' 580 OR id='.(int)($params['cat_id']).')'; 581 else 582 $where[] = 'id_uppercat IS NULL'; 583 } 584 elseif ($params['cat_id']>0) 585 { 586 $where[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'. 587 (int)($params['cat_id']) 588 .'(,|$)\''; 589 } 590 591 if ($params['public']) 592 { 593 $where[] = 'status = "public"'; 594 $where[] = 'visible = "true"'; 595 596 $join_user = $conf['guest_id']; 597 } 598 elseif (is_admin()) 599 { 600 // in this very specific case, we don't want to hide empty 601 // categories. Function calculate_permissions will only return 602 // categories that are either locked or private and not permitted 603 // 604 // calculate_permissions does not consider empty categories as forbidden 605 $forbidden_categories = calculate_permissions($user['id'], $user['status']); 606 $where[]= 'id NOT IN ('.$forbidden_categories.')'; 607 $join_type = 'LEFT'; 608 } 609 610 $query = ' 611 SELECT id, name, permalink, uppercats, global_rank, id_uppercat, 612 comment, 613 nb_images, count_images AS total_nb_images, 614 representative_picture_id, user_representative_picture_id, count_images, count_categories, 615 date_last, max_date_last, count_categories AS nb_categories 616 FROM '.CATEGORIES_TABLE.' 617 '.$join_type.' JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id AND user_id='.$join_user.' 618 WHERE '. implode(' 619 AND ', $where); 620 621 $result = pwg_query($query); 622 623 // management of the album thumbnail -- starts here 624 $image_ids = array(); 625 $categories = array(); 626 $user_representative_updates_for = array(); 627 // management of the album thumbnail -- stops here 628 629 $cats = array(); 630 while ($row = pwg_db_fetch_assoc($result)) 631 { 632 $row['url'] = make_index_url( 633 array( 634 'category' => $row 635 ) 636 ); 637 foreach( array('id','nb_images','total_nb_images','nb_categories') as $key) 638 { 639 $row[$key] = (int)$row[$key]; 640 } 641 642 if ($params['fullname']) 643 { 644 $row['name'] = strip_tags(get_cat_display_name_cache($row['uppercats'], null, false)); 645 } 646 else 647 { 648 $row['name'] = strip_tags( 649 trigger_event( 650 'render_category_name', 651 $row['name'], 652 'ws_categories_getList' 653 ) 654 ); 655 } 656 657 $row['comment'] = strip_tags( 658 trigger_event( 659 'render_category_description', 660 $row['comment'], 661 'ws_categories_getList' 662 ) 663 ); 664 665 // management of the album thumbnail -- starts here 666 // 667 // on branch 2.3, the algorithm is duplicated from 668 // include/category_cats, but we should use a common code for Piwigo 2.4 669 // 670 // warning : if the API method is called with $params['public'], the 671 // album thumbnail may be not accurate. The thumbnail can be viewed by 672 // the connected user, but maybe not by the guest. Changing the 673 // filtering method would be too complicated for now. We will simply 674 // avoid to persist the user_representative_picture_id in the database 675 // if $params['public'] 676 if (!empty($row['user_representative_picture_id'])) 677 { 678 $image_id = $row['user_representative_picture_id']; 679 } 680 elseif (!empty($row['representative_picture_id'])) 681 { // if a representative picture is set, it has priority 682 $image_id = $row['representative_picture_id']; 683 } 684 elseif ($conf['allow_random_representative']) 685 { 686 // searching a random representant among elements in sub-categories 687 $image_id = get_random_image_in_category($row); 688 } 689 else 690 { // searching a random representant among representant of sub-categories 691 if ($row['count_categories']>0 and $row['count_images']>0) 692 { 693 $query = ' 694 SELECT representative_picture_id 695 FROM '.CATEGORIES_TABLE.' INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' 696 ON id = cat_id and user_id = '.$user['id'].' 697 WHERE uppercats LIKE \''.$row['uppercats'].',%\' 698 AND representative_picture_id IS NOT NULL' 699 .get_sql_condition_FandF 700 ( 701 array 702 ( 703 'visible_categories' => 'id', 704 ), 705 "\n AND" 706 ).' 707 ORDER BY '.DB_RANDOM_FUNCTION.'() 708 LIMIT 1 709 ;'; 710 $subresult = pwg_query($query); 711 if (pwg_db_num_rows($subresult) > 0) 712 { 713 list($image_id) = pwg_db_fetch_row($subresult); 714 } 715 } 716 } 717 718 if (isset($image_id)) 719 { 720 if ($conf['representative_cache_on_subcats'] and $row['user_representative_picture_id'] != $image_id) 721 { 722 $user_representative_updates_for[ $row['id'] ] = $image_id; 723 } 724 725 $row['representative_picture_id'] = $image_id; 726 $image_ids[] = $image_id; 727 $categories[] = $row; 728 } 729 unset($image_id); 730 // management of the album thumbnail -- stops here 731 732 733 $cats[] = $row; 734 } 735 usort($cats, 'global_rank_compare'); 736 737 // management of the album thumbnail -- starts here 738 if (count($categories) > 0) 739 { 740 $thumbnail_src_of = array(); 741 $new_image_ids = array(); 742 743 $query = ' 744 SELECT id, path, representative_ext, level 745 FROM '.IMAGES_TABLE.' 746 WHERE id IN ('.implode(',', $image_ids).') 747 ;'; 748 $result = pwg_query($query); 749 while ($row = pwg_db_fetch_assoc($result)) 750 { 751 if ($row['level'] <= $user['level']) 752 { 753 $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); 754 } 755 else 756 { 757 // problem: we must not display the thumbnail of a photo which has a 758 // higher privacy level than user privacy level 759 // 760 // * what is the represented category? 761 // * find a random photo matching user permissions 762 // * register it at user_representative_picture_id 763 // * set it as the representative_picture_id for the category 764 765 foreach ($categories as &$category) 766 { 767 if ($row['id'] == $category['representative_picture_id']) 768 { 769 // searching a random representant among elements in sub-categories 770 $image_id = get_random_image_in_category($category); 771 772 if (isset($image_id) and !in_array($image_id, $image_ids)) 773 { 774 $new_image_ids[] = $image_id; 775 } 776 777 if ($conf['representative_cache_on_level']) 778 { 779 $user_representative_updates_for[ $category['id'] ] = $image_id; 780 } 781 782 $category['representative_picture_id'] = $image_id; 783 } 784 } 785 unset($category); 786 } 787 } 788 789 if (count($new_image_ids) > 0) 790 { 791 $query = ' 792 SELECT id, path, representative_ext 793 FROM '.IMAGES_TABLE.' 794 WHERE id IN ('.implode(',', $new_image_ids).') 795 ;'; 796 $result = pwg_query($query); 797 while ($row = pwg_db_fetch_assoc($result)) 798 { 799 $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); 800 } 801 } 802 } 803 804 // compared to code in include/category_cats, we only persist the new 805 // user_representative if we have used $user['id'] and not the guest id, 806 // or else the real guest may see thumbnail that he should not 807 if (!$params['public'] and count($user_representative_updates_for)) 808 { 809 $updates = array(); 810 811 foreach ($user_representative_updates_for as $cat_id => $image_id) 812 { 813 $updates[] = array( 814 'user_id' => $user['id'], 815 'cat_id' => $cat_id, 816 'user_representative_picture_id' => $image_id, 817 ); 818 } 819 820 mass_updates( 821 USER_CACHE_CATEGORIES_TABLE, 822 array( 823 'primary' => array('user_id', 'cat_id'), 824 'update' => array('user_representative_picture_id') 825 ), 826 $updates 827 ); 828 } 829 830 foreach ($cats as &$cat) 831 { 832 foreach ($categories as $category) 833 { 834 if ($category['id'] == $cat['id'] and isset($category['representative_picture_id'])) 835 { 836 $cat['tn_url'] = $thumbnail_src_of[$category['representative_picture_id']]; 837 } 838 } 839 // we don't want them in the output 840 unset($cat['user_representative_picture_id']); 841 unset($cat['count_images']); 842 unset($cat['count_categories']); 843 } 844 unset($cat); 845 // management of the album thumbnail -- stops here 846 847 if ($params['tree_output']) 848 { 849 $cats = categories_flatlist_to_tree($cats); 850 } 851 852 return array( 853 'categories' => new PwgNamedArray($cats, 'category', ws_std_get_category_xml_attributes()) 854 ); 855 } 856 857 /** 858 * returns the list of categories as you can see them in administration (web 859 * service method). 860 * 861 * Only admin can run this method and permissions are not taken into 862 * account. 863 */ 864 function ws_categories_getAdminList($params, $service) 865 { 866 $query = ' 867 SELECT 868 category_id, 869 COUNT(*) AS counter 870 FROM '.IMAGE_CATEGORY_TABLE.' 871 GROUP BY category_id 872 ;'; 873 $nb_images_of = simple_hash_from_query($query, 'category_id', 'counter'); 874 875 $query = ' 876 SELECT 877 id, 878 name, 879 comment, 880 uppercats, 881 global_rank 882 FROM '.CATEGORIES_TABLE.' 883 ;'; 884 $result = pwg_query($query); 885 $cats = array(); 886 887 while ($row = pwg_db_fetch_assoc($result)) 888 { 889 $id = $row['id']; 890 $row['nb_images'] = isset($nb_images_of[$id]) ? $nb_images_of[$id] : 0; 891 $row['name'] = strip_tags( 892 trigger_event( 893 'render_category_name', 894 $row['name'], 895 'ws_categories_getAdminList' 896 ) 897 ); 898 $row['comment'] = strip_tags( 899 trigger_event( 900 'render_category_description', 901 $row['comment'], 902 'ws_categories_getAdminList' 903 ) 904 ); 905 $cats[] = $row; 906 } 907 908 usort($cats, 'global_rank_compare'); 909 return array( 910 'categories' => new PwgNamedArray( 911 $cats, 912 'category', 913 array( 914 'id', 915 'nb_images', 916 'name', 917 'uppercats', 918 'global_rank', 919 ) 920 ) 921 ); 922 } 923 924 /** 925 * returns detailed information for an element (web service method) 926 */ 927 function ws_images_addComment($params, $service) 928 { 929 $query = ' 930 SELECT DISTINCT image_id 931 FROM '.IMAGE_CATEGORY_TABLE.' INNER JOIN '.CATEGORIES_TABLE.' ON category_id=id 932 WHERE commentable="true" 933 AND image_id='.$params['image_id']. 934 get_sql_condition_FandF( 935 array( 936 'forbidden_categories' => 'id', 937 'visible_categories' => 'id', 938 'visible_images' => 'image_id' 939 ), 940 ' AND' 941 ); 942 if ( !pwg_db_num_rows( pwg_query( $query ) ) ) 943 { 944 return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id"); 945 } 946 947 $comm = array( 948 'author' => trim( $params['author'] ), 949 'content' => trim( $params['content'] ), 950 'image_id' => $params['image_id'], 951 ); 952 953 include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php'); 954 955 $comment_action = insert_user_comment( 956 $comm, $params['key'], $infos 957 ); 958 959 switch ($comment_action) 960 { 961 case 'reject': 962 $infos[] = l10n('Your comment has NOT been registered because it did not pass the validation rules'); 963 return new PwgError(403, implode("; ", $infos) ); 964 case 'validate': 965 case 'moderate': 966 $ret = array( 967 'id' => $comm['id'], 968 'validation' => $comment_action=='validate', 969 ); 970 return array( 'comment' => new PwgNamedStruct($ret) ); 971 default: 972 return new PwgError(500, "Unknown comment action ".$comment_action ); 973 } 974 } 975 976 /** 977 * returns detailed information for an element (web service method) 978 */ 979 function ws_images_getInfo($params, $service) 980 { 981 global $user, $conf; 982 983 $query=' 984 SELECT * FROM '.IMAGES_TABLE.' 985 WHERE id='.$params['image_id']. 986 get_sql_condition_FandF( 987 array('visible_images' => 'id'), 988 ' AND' 989 ).' 990 LIMIT 1'; 991 $result = pwg_query($query); 992 993 if (pwg_db_num_rows($result) == 0) 994 { 995 return new PwgError(404, "image_id not found"); 996 } 997 998 $image_row = pwg_db_fetch_assoc($result); 999 $image_row = array_merge( $image_row, ws_std_get_urls($image_row) ); 1000 1001 //-------------------------------------------------------- related categories 1002 $query = ' 1003 SELECT id, name, permalink, uppercats, global_rank, commentable 1004 FROM '.IMAGE_CATEGORY_TABLE.' 1005 INNER JOIN '.CATEGORIES_TABLE.' ON category_id = id 1006 WHERE image_id = '.$image_row['id']. 1007 get_sql_condition_FandF( 1008 array( 'forbidden_categories' => 'category_id' ), 1009 ' AND' 1010 ).' 1011 ;'; 1012 $result = pwg_query($query); 1013 $is_commentable = false; 1014 $related_categories = array(); 1015 while ($row = pwg_db_fetch_assoc($result)) 1016 { 1017 if ($row['commentable']=='true') 1018 { 1019 $is_commentable = true; 1020 } 1021 unset($row['commentable']); 1022 $row['url'] = make_index_url( 1023 array( 1024 'category' => $row 1025 ) 1026 ); 1027 1028 $row['page_url'] = make_picture_url( 1029 array( 1030 'image_id' => $image_row['id'], 1031 'image_file' => $image_row['file'], 1032 'category' => $row 1033 ) 1034 ); 1035 $row['id']=(int)$row['id']; 1036 $related_categories[] = $row; 1037 } 1038 usort($related_categories, 'global_rank_compare'); 1039 if ( empty($related_categories) ) 1040 { 1041 return new PwgError(401, 'Access denied'); 1042 } 1043 1044 //-------------------------------------------------------------- related tags 1045 $related_tags = get_common_tags( array($image_row['id']), -1 ); 1046 foreach( $related_tags as $i=>$tag) 1047 { 1048 $tag['url'] = make_index_url( 1049 array( 1050 'tags' => array($tag) 1051 ) 1052 ); 1053 $tag['page_url'] = make_picture_url( 1054 array( 1055 'image_id' => $image_row['id'], 1056 'image_file' => $image_row['file'], 1057 'tags' => array($tag), 1058 ) 1059 ); 1060 unset($tag['counter']); 1061 $tag['id']=(int)$tag['id']; 1062 $related_tags[$i]=$tag; 1063 } 1064 //------------------------------------------------------------- related rates 1065 $rating = array('score'=>$image_row['rating_score'], 'count'=>0, 'average'=>null); 1066 if (isset($rating['score'])) 1067 { 1068 $query = ' 1069 SELECT COUNT(rate) AS count 1070 , ROUND(AVG(rate),2) AS average 1071 FROM '.RATE_TABLE.' 1072 WHERE element_id = '.$image_row['id'].' 1073 ;'; 1074 $row = pwg_db_fetch_assoc(pwg_query($query)); 1075 $rating['score'] = (float)$rating['score']; 1076 $rating['average'] = (float)$row['average']; 1077 $rating['count'] = (int)$row['count']; 1078 } 1079 1080 //---------------------------------------------------------- related comments 1081 $related_comments = array(); 1082 1083 $where_comments = 'image_id = '.$image_row['id']; 1084 if ( !is_admin() ) 1085 { 1086 $where_comments .= ' 1087 AND validated="true"'; 1088 } 1089 1090 $query = ' 1091 SELECT COUNT(id) AS nb_comments 1092 FROM '.COMMENTS_TABLE.' 1093 WHERE '.$where_comments; 1094 list($nb_comments) = array_from_query($query, 'nb_comments'); 1095 $nb_comments = (int)$nb_comments; 1096 1097 if ( $nb_comments>0 and $params['comments_per_page']>0 ) 1098 { 1099 $query = ' 1100 SELECT id, date, author, content 1101 FROM '.COMMENTS_TABLE.' 1102 WHERE '.$where_comments.' 1103 ORDER BY date 1104 LIMIT '.(int)$params['comments_per_page']. 1105 ' OFFSET '.(int)($params['comments_per_page']*$params['comments_page']); 1106 1107 $result = pwg_query($query); 1108 while ($row = pwg_db_fetch_assoc($result)) 1109 { 1110 $row['id']=(int)$row['id']; 1111 $related_comments[] = $row; 1112 } 1113 } 1114 1115 $comment_post_data = null; 1116 if ($is_commentable and 1117 (!is_a_guest() 1118 or (is_a_guest() and $conf['comments_forall'] ) 1119 ) 1120 ) 1121 { 1122 $comment_post_data['author'] = stripslashes($user['username']); 1123 $comment_post_data['key'] = get_ephemeral_key(2, $params['image_id']); 1124 } 1125 1126 $ret = $image_row; 1127 foreach ( array('id','width','height','hit','filesize') as $k ) 1128 { 1129 if (isset($ret[$k])) 1130 { 1131 $ret[$k] = (int)$ret[$k]; 1132 } 1133 } 1134 foreach ( array('path', 'storage_category_id') as $k ) 1135 { 1136 unset($ret[$k]); 1137 } 1138 1139 $ret['rates'] = array( WS_XML_ATTRIBUTES => $rating ); 1140 $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') ); 1141 $ret['tags'] = new PwgNamedArray($related_tags, 'tag', ws_std_get_tag_xml_attributes() ); 1142 if ( isset($comment_post_data) ) 1143 { 1144 $ret['comment_post'] = array( WS_XML_ATTRIBUTES => $comment_post_data ); 1145 } 1146 $ret['comments_paging'] = new PwgNamedStruct( array( 1147 'page' => $params['comments_page'], 1148 'per_page' => $params['comments_per_page'], 1149 'count' => count($related_comments), 1150 'total_count' => $nb_comments, 1151 ) ); 1152 1153 $ret['comments'] = new PwgNamedArray($related_comments, 'comment', array('id','date') ); 1154 1155 if ($service->_responseFormat != 'rest') 1156 return $ret; // for backward compatibility only 1157 else 1158 return array( 'image' => new PwgNamedStruct($ret, null, array('name','comment') ) ); 1159 } 1160 1161 1162 /** 1163 * rates the image_id in the parameter 1164 */ 1165 function ws_images_Rate($params, $service) 1166 { 1167 $query = ' 1168 SELECT DISTINCT id FROM '.IMAGES_TABLE.' 1169 INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id 1170 WHERE id='.$params['image_id'] 1171 .get_sql_condition_FandF( 1172 array( 1173 'forbidden_categories' => 'category_id', 1174 'forbidden_images' => 'id', 1175 ), 1176 ' AND' 1177 ).' 1178 LIMIT 1'; 1179 if ( pwg_db_num_rows( pwg_query($query) )==0 ) 1180 { 1181 return new PwgError(404, "Invalid image_id or access denied" ); 1182 } 1183 $rate = (int)$params['rate']; 1184 include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php'); 1185 $res = rate_picture( $params['image_id'], $rate ); 1186 if ($res==false) 1187 { 1188 global $conf; 1189 return new PwgError( 403, "Forbidden or rate not in ". implode(',',$conf['rate_items'])); 1190 } 1191 return $res; 1192 } 1193 1194 1195 /** 1196 * returns a list of elements corresponding to a query search 1197 */ 1198 function ws_images_search($params, $service) 1199 { 1200 global $page; 1201 $images = array(); 1202 include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' ); 1203 1204 $where_clauses = ws_std_image_sql_filter( $params, 'i.' ); 1205 $order_by = ws_std_image_sql_order($params, 'i.'); 1206 1207 $super_order_by = false; 1208 if ( !empty($order_by) ) 1209 { 1210 global $conf; 1211 $conf['order_by'] = 'ORDER BY '.$order_by; 1212 $super_order_by=true; // quick_search_result might be faster 1213 } 1214 1215 $search_result = get_quick_search_results($params['query'], 1216 $super_order_by, 1217 implode(' AND ', $where_clauses) 1218 ); 1219 1220 $image_ids = array_slice( 1221 $search_result['items'], 1222 $params['page']*$params['per_page'], 1223 $params['per_page'] 1224 ); 1225 1226 if ( count($image_ids) ) 1227 { 1228 $query = ' 1229 SELECT * FROM '.IMAGES_TABLE.' 1230 WHERE id IN ('.implode(',', $image_ids).')'; 1231 1232 $image_ids = array_flip($image_ids); 1233 $result = pwg_query($query); 1234 while ($row = pwg_db_fetch_assoc($result)) 1235 { 1236 $image = array(); 1237 foreach ( array('id', 'width', 'height', 'hit') as $k ) 1238 { 1239 if (isset($row[$k])) 1240 { 1241 $image[$k] = (int)$row[$k]; 1242 } 1243 } 1244 foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 1245 { 1246 $image[$k] = $row[$k]; 1247 } 1248 $image = array_merge( $image, ws_std_get_urls($row) ); 1249 $images[$image_ids[$image['id']]] = $image; 1250 } 1251 ksort($images, SORT_NUMERIC); 1252 $images = array_values($images); 1253 } 1254 1255 return array ( 1256 'paging' => new PwgNamedStruct( 1257 array( 1258 'page' => $params['page'], 1259 'per_page' => $params['per_page'], 1260 'count' => count($images), 1261 'total_count' => count($search_result['items']), 1262 ) ), 1263 'images' => new PwgNamedArray($images, 'image', 1264 ws_std_get_image_xml_attributes() ) 1265 ); 1266 } 1267 1268 function ws_images_setPrivacyLevel($params, $service) 1269 { 1270 global $conf; 1271 if ( !in_array($params['level'], $conf['available_permission_levels']) ) 1272 { 1273 return new PwgError(WS_ERR_INVALID_PARAM, "Invalid level"); 1274 } 1275 1276 $query = ' 1277 UPDATE '.IMAGES_TABLE.' 1278 SET level='.(int)$params['level'].' 1279 WHERE id IN ('.implode(',',$params['image_id']).')'; 1280 $result = pwg_query($query); 1281 $affected_rows = pwg_db_changes($result); 1282 if ($affected_rows) 1283 { 1284 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 1285 invalidate_user_cache(); 1286 } 1287 return $affected_rows; 1288 } 1289 1290 function ws_images_setRank($params, $service) 1291 { 1292 // does the image really exist? 1293 $query=' 1294 SELECT COUNT(*) 1295 FROM '.IMAGES_TABLE.' 1296 WHERE id = '.$params['image_id'].' 1297 ;'; 1298 1299 list($count) = pwg_db_fetch_row(pwg_query($query)); 1300 if ($count == 0) 1301 { 1302 return new PwgError(404, "image_id not found"); 1303 } 1304 1305 // is the image associated to this category? 1306 $query = ' 1307 SELECT COUNT(*) 1308 FROM '.IMAGE_CATEGORY_TABLE.' 1309 WHERE image_id = '.$params['image_id'].' 1310 AND category_id = '.$params['category_id'].' 1311 ;'; 1312 list($count) = pwg_db_fetch_row(pwg_query($query)); 1313 if ($count == 0) 1314 { 1315 return new PwgError(404, "This image is not associated to this category"); 1316 } 1317 1318 // what is the current higher rank for this category? 1319 $query = ' 1320 SELECT 1321 MAX(rank) AS max_rank 1322 FROM '.IMAGE_CATEGORY_TABLE.' 1323 WHERE category_id = '.$params['category_id'].' 1324 ;'; 1325 $result = pwg_query($query); 1326 $row = pwg_db_fetch_assoc($result); 1327 1328 if (is_numeric($row['max_rank'])) 1329 { 1330 if ($params['rank'] > $row['max_rank']) 1331 { 1332 $params['rank'] = $row['max_rank'] + 1; 1333 } 1334 } 1335 else 1336 { 1337 $params['rank'] = 1; 1338 } 1339 1340 // update rank for all other photos in the same category 1341 $query = ' 1342 UPDATE '.IMAGE_CATEGORY_TABLE.' 1343 SET rank = rank + 1 1344 WHERE category_id = '.$params['category_id'].' 1345 AND rank IS NOT NULL 1346 AND rank >= '.$params['rank'].' 1347 ;'; 1348 pwg_query($query); 1349 1350 // set the new rank for the photo 1351 $query = ' 1352 UPDATE '.IMAGE_CATEGORY_TABLE.' 1353 SET rank = '.$params['rank'].' 1354 WHERE image_id = '.$params['image_id'].' 1355 AND category_id = '.$params['category_id'].' 1356 ;'; 1357 pwg_query($query); 1358 1359 // return data for client 1360 return array( 1361 'image_id' => $params['image_id'], 1362 'category_id' => $params['category_id'], 1363 'rank' => $params['rank'], 1364 ); 1365 } 1366 1367 function ws_images_add_chunk($params, $service) 1368 { 1369 global $conf; 1370 1371 // data 1372 // original_sum 1373 // type {thumb, file, high} 1374 // position 1375 1376 foreach ($params as $param_key => $param_value) { 1377 if ('data' == $param_key) { 1378 continue; 1379 } 1380 1381 ws_logfile( 1382 sprintf( 1383 '[ws_images_add_chunk] input param "%s" : "%s"', 1384 $param_key, 1385 is_null($param_value) ? 'NULL' : $param_value 1386 ) 1387 ); 1388 } 1389 1390 $upload_dir = $conf['upload_dir'].'/buffer'; 1391 1392 // create the upload directory tree if not exists 1393 if (!mkgetdir($upload_dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR)) 1394 { 1395 return new PwgError(500, 'error during buffer directory creation'); 1396 } 1397 1398 $filename = sprintf( 1399 '%s-%s-%05u.block', 1400 $params['original_sum'], 1401 $params['type'], 1402 $params['position'] 1403 ); 1404 1405 ws_logfile('[ws_images_add_chunk] data length : '.strlen($params['data'])); 1406 1407 $bytes_written = file_put_contents( 1408 $upload_dir.'/'.$filename, 1409 base64_decode($params['data']) 1410 ); 1411 1412 if (false === $bytes_written) { 1413 return new PwgError( 1414 500, 1415 'an error has occured while writting chunk '.$params['position'].' for '.$params['type'] 1416 ); 1417 } 1418 } 1419 1420 function merge_chunks($output_filepath, $original_sum, $type) 1421 { 1422 global $conf; 1423 1424 ws_logfile('[merge_chunks] input parameter $output_filepath : '.$output_filepath); 1425 1426 if (is_file($output_filepath)) 1427 { 1428 unlink($output_filepath); 1429 1430 if (is_file($output_filepath)) 1431 { 1432 return new PwgError(500, '[merge_chunks] error while trying to remove existing '.$output_filepath); 1433 } 1434 } 1435 1436 $upload_dir = $conf['upload_dir'].'/buffer'; 1437 $pattern = '/'.$original_sum.'-'.$type.'/'; 1438 $chunks = array(); 1439 1440 if ($handle = opendir($upload_dir)) 1441 { 1442 while (false !== ($file = readdir($handle))) 1443 { 1444 if (preg_match($pattern, $file)) 1445 { 1446 ws_logfile($file); 1447 $chunks[] = $upload_dir.'/'.$file; 1448 } 1449 } 1450 closedir($handle); 1451 } 1452 1453 sort($chunks); 1454 1455 if (function_exists('memory_get_usage')) { 1456 ws_logfile('[merge_chunks] memory_get_usage before loading chunks: '.memory_get_usage()); 1457 } 1458 1459 $i = 0; 1460 1461 foreach ($chunks as $chunk) 1462 { 1463 $string = file_get_contents($chunk); 1464 1465 if (function_exists('memory_get_usage')) { 1466 ws_logfile('[merge_chunks] memory_get_usage on chunk '.++$i.': '.memory_get_usage()); 1467 } 1468 1469 if (!file_put_contents($output_filepath, $string, FILE_APPEND)) 1470 { 1471 return new PwgError(500, '[merge_chunks] error while writting chunks for '.$output_filepath); 1472 } 1473 1474 unlink($chunk); 1475 } 1476 1477 if (function_exists('memory_get_usage')) { 1478 ws_logfile('[merge_chunks] memory_get_usage after loading chunks: '.memory_get_usage()); 1479 } 1480 } 1481 1482 /** 1483 * Function introduced for Piwigo 2.4 and the new "multiple size" 1484 * (derivatives) feature. As we only need the biggest sent photo as 1485 * "original", we remove chunks for smaller sizes. We can't make it earlier 1486 * in ws_images_add_chunk because at this moment we don't know which $type 1487 * will be the biggest (we could remove the thumb, but let's use the same 1488 * algorithm) 1489 */ 1490 function remove_chunks($original_sum, $type) 1491 { 1492 global $conf; 1493 1494 $upload_dir = $conf['upload_dir'].'/buffer'; 1495 $pattern = '/'.$original_sum.'-'.$type.'/'; 1496 $chunks = array(); 1497 1498 if ($handle = opendir($upload_dir)) 1499 { 1500 while (false !== ($file = readdir($handle))) 1501 { 1502 if (preg_match($pattern, $file)) 1503 { 1504 $chunks[] = $upload_dir.'/'.$file; 1505 } 1506 } 1507 closedir($handle); 1508 } 1509 1510 foreach ($chunks as $chunk) 1511 { 1512 unlink($chunk); 1513 } 1514 } 1515 1516 function ws_images_addFile($params, $service) 1517 { 1518 ws_logfile(__FUNCTION__.', input : '.var_export($params, true)); 1519 // image_id 1520 // type {thumb, file, high} 1521 // sum -> not used currently (Piwigo 2.4) 1522 1523 global $conf; 1524 1525 // 1526 // what is the path and other infos about the photo? 1527 // 1528 $query = ' 1529 SELECT 1530 path, 1531 file, 1532 md5sum, 1533 width, 1534 height, 1535 filesize 1536 FROM '.IMAGES_TABLE.' 1537 WHERE id = '.$params['image_id'].' 1538 ;'; 1539 $result = pwg_query($query); 1540 1541 if (pwg_db_num_rows($result) == 0) 1542 { 1543 return new PwgError(404, "image_id not found"); 1544 } 1545 1546 $image = pwg_db_fetch_assoc($result); 1547 1548 // since Piwigo 2.4 and derivatives, we do not take the imported "thumb" 1549 // into account 1550 if ('thumb' == $params['type']) 1551 { 1552 remove_chunks($image['md5sum'], $type); 1553 return true; 1554 } 1555 1556 // since Piwigo 2.4 and derivatives, we only care about the "original" 1557 $original_type = 'file'; 1558 if ('high' == $params['type']) 1559 { 1560 $original_type = 'high'; 1561 } 1562 1563 $file_path = $conf['upload_dir'].'/buffer/'.$image['md5sum'].'-original'; 1564 1565 merge_chunks($file_path, $image['md5sum'], $original_type); 1566 chmod($file_path, 0644); 1567 1568 include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 1569 1570 // if we receive the "file", we only update the original if the "file" is 1571 // bigger than current original 1572 if ('file' == $params['type']) 1573 { 1574 $do_update = false; 1575 1576 $infos = pwg_image_infos($file_path); 1577 1578 foreach (array('width', 'height', 'filesize') as $image_info) 1579 { 1580 if ($infos[$image_info] > $image[$image_info]) 1581 { 1582 $do_update = true; 1583 } 1584 } 1585 1586 if (!$do_update) 1587 { 1588 unlink($file_path); 1589 return true; 1590 } 1591 } 1592 1593 $image_id = add_uploaded_file( 1594 $file_path, 1595 $image['file'], 1596 null, 1597 null, 1598 $params['image_id'], 1599 $image['md5sum'] // we force the md5sum to remain the same 1600 ); 1601 } 1602 1603 function ws_images_add($params, $service) 1604 { 1605 global $conf, $user; 1606 1607 foreach ($params as $param_key => $param_value) { 1608 ws_logfile( 1609 sprintf( 1610 '[pwg.images.add] input param "%s" : "%s"', 1611 $param_key, 1612 is_null($param_value) ? 'NULL' : $param_value 1613 ) 1614 ); 1615 } 1616 1617 if ($params['image_id'] > 0) 1618 { 1619 $query=' 1620 SELECT COUNT(*) 1621 FROM '.IMAGES_TABLE.' 1622 WHERE id = '.$params['image_id'].' 1623 ;'; 1624 1625 list($count) = pwg_db_fetch_row(pwg_query($query)); 1626 if ($count == 0) 1627 { 1628 return new PwgError(404, "image_id not found"); 1629 } 1630 } 1631 1632 // does the image already exists ? 1633 if ($params['check_uniqueness']) 1634 { 1635 if ('md5sum' == $conf['uniqueness_mode']) 1636 { 1637 $where_clause = "md5sum = '".$params['original_sum']."'"; 1638 } 1639 if ('filename' == $conf['uniqueness_mode']) 1640 { 1641 $where_clause = "file = '".$params['original_filename']."'"; 1642 } 1643 1644 $query = ' 1645 SELECT COUNT(*) 1646 FROM '.IMAGES_TABLE.' 1647 WHERE '.$where_clause.' 1648 ;'; 1649 list($counter) = pwg_db_fetch_row(pwg_query($query)); 1650 if ($counter != 0) { 1651 return new PwgError(500, 'file already exists'); 1652 } 1653 } 1654 1655 // due to the new feature "derivatives" (multiple sizes) introduced for 1656 // Piwigo 2.4, we only take the biggest photos sent on 1657 // pwg.images.addChunk. If "high" is available we use it as "original" 1658 // else we use "file". 1659 remove_chunks($params['original_sum'], 'thumb'); 1660 1661 if (isset($params['high_sum'])) 1662 { 1663 $original_type = 'high'; 1664 remove_chunks($params['original_sum'], 'file'); 1665 } 1666 else 1667 { 1668 $original_type = 'file'; 1669 } 1670 1671 $file_path = $conf['upload_dir'].'/buffer/'.$params['original_sum'].'-original'; 1672 1673 merge_chunks($file_path, $params['original_sum'], $original_type); 1674 chmod($file_path, 0644); 1675 1676 include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 1677 1678 $image_id = add_uploaded_file( 1679 $file_path, 1680 $params['original_filename'], 1681 null, // categories 1682 isset($params['level']) ? $params['level'] : null, 1683 $params['image_id'] > 0 ? $params['image_id'] : null, 1684 $params['original_sum'] 1685 ); 1686 1687 $info_columns = array( 1688 'name', 1689 'author', 1690 'comment', 1691 'date_creation', 1692 ); 1693 1694 $update = array(); 1695 1696 foreach ($info_columns as $key) 1697 { 1698 if (isset($params[$key])) 1699 { 1700 $update[$key] = $params[$key]; 1701 } 1702 } 1703 1704 if (count(array_keys($update)) > 0) 1705 { 1706 single_update( 1707 IMAGES_TABLE, 1708 $update, 1709 array('id' => $image_id) 1710 ); 1711 } 1712 1713 $url_params = array('image_id' => $image_id); 1714 1715 // let's add links between the image and the categories 1716 if (isset($params['categories'])) 1717 { 1718 ws_add_image_category_relations($image_id, $params['categories']); 1719 1720 if (preg_match('/^\d+/', $params['categories'], $matches)) { 1721 $category_id = $matches[0]; 1722 1723 $query = ' 1724 SELECT id, name, permalink 1725 FROM '.CATEGORIES_TABLE.' 1726 WHERE id = '.$category_id.' 1727 ;'; 1728 $result = pwg_query($query); 1729 $category = pwg_db_fetch_assoc($result); 1730 1731 $url_params['section'] = 'categories'; 1732 $url_params['category'] = $category; 1733 } 1734 } 1735 1736 // and now, let's create tag associations 1737 if (isset($params['tag_ids']) and !empty($params['tag_ids'])) 1738 { 1739 set_tags( 1740 explode(',', $params['tag_ids']), 1741 $image_id 1742 ); 1743 } 1744 1745 invalidate_user_cache(); 1746 1747 return array( 1748 'image_id' => $image_id, 1749 'url' => make_picture_url($url_params), 1750 ); 1751 } 1752 1753 function ws_images_addSimple($params, $service) 1754 { 1755 global $conf; 1756 1757 if (!isset($_FILES['image'])) 1758 { 1759 return new PwgError(405, "The image (file) is missing"); 1760 } 1761 1762 if ($params['image_id'] > 0) 1763 { 1764 $query=' 1765 SELECT COUNT(*) 1766 FROM '.IMAGES_TABLE.' 1767 WHERE id = '.$params['image_id'].' 1768 ;'; 1769 1770 list($count) = pwg_db_fetch_row(pwg_query($query)); 1771 if ($count == 0) 1772 { 1773 return new PwgError(404, "image_id not found"); 1774 } 1775 } 1776 1777 include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 1778 1779 $image_id = add_uploaded_file( 1780 $_FILES['image']['tmp_name'], 1781 $_FILES['image']['name'], 1782 $params['category'], 1783 8, 1784 $params['image_id'] > 0 ? $params['image_id'] : null 1785 ); 1786 1787 $info_columns = array( 1788 'name', 1789 'author', 1790 'comment', 1791 'level', 1792 'date_creation', 1793 ); 1794 1795 foreach ($info_columns as $key) 1796 { 1797 if (isset($params[$key])) 1798 { 1799 $update[$key] = $params[$key]; 1800 } 1801 } 1802 1803 if (count($update) > 0) 1804 { 1805 $update['id'] = $image_id; 1806 1807 single_update( 1808 IMAGES_TABLE, 1809 $update, 1810 array('id' => $update['id']) 1811 ); 1812 } 1813 1814 1815 if (isset($params['tags']) and !empty($params['tags'])) 1816 { 1817 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 1818 1819 $tag_ids = array(); 1820 if (is_array($params['tags'])) 1821 { 1822 foreach ($params['tags'] as $tag_name) 1823 { 1824 $tag_ids[] = tag_id_from_tag_name($tag_name); 1825 } 1826 } 1827 else 1828 { 1829 $tag_names = preg_split('~(?<!\\\),~', $params['tags']); 1830 foreach ($tag_names as $tag_name) 1831 { 1832 $tag_ids[] = tag_id_from_tag_name(preg_replace('#\\\\*,#', ',', $tag_name)); 1833 } 1834 } 1835 1836 add_tags($tag_ids, array($image_id)); 1837 } 1838 1839 $url_params = array('image_id' => $image_id); 1840 1841 if (!empty($params['category'])) 1842 { 1843 $query = ' 1844 SELECT id, name, permalink 1845 FROM '.CATEGORIES_TABLE.' 1846 WHERE id = '.$params['category'][0].' 1847 ;'; 1848 $result = pwg_query($query); 1849 $category = pwg_db_fetch_assoc($result); 1850 1851 $url_params['section'] = 'categories'; 1852 $url_params['category'] = $category; 1853 } 1854 1855 // update metadata from the uploaded file (exif/iptc), even if the sync 1856 // was already performed by add_uploaded_file(). 1857 1858 require_once(PHPWG_ROOT_PATH.'admin/include/functions_metadata.php'); 1859 sync_metadata(array($image_id)); 1860 1861 return array( 1862 'image_id' => $image_id, 1863 'url' => make_picture_url($url_params), 1864 ); 1865 } 1866 1867 function ws_rates_delete($params, $service) 1868 { 1869 $query = ' 1870 DELETE FROM '.RATE_TABLE.' 1871 WHERE user_id='.$params['user_id']; 1872 1873 if (!empty($params['anonymous_id'])) 1874 { 1875 $query .= ' AND anonymous_id=\''.$params['anonymous_id'].'\''; 1876 } 1877 1878 $changes = pwg_db_changes(pwg_query($query)); 1879 if ($changes) 1880 { 1881 include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php'); 1882 update_rating_score(); 1883 } 1884 return $changes; 1885 } 1886 1887 1888 /** 1889 * perform a login (web service method) 1890 */ 1891 function ws_session_login($params, $service) 1892 { 1893 if (try_log_user($params['username'], $params['password'],false)) 1894 { 1895 return true; 1896 } 1897 return new PwgError(999, 'Invalid username/password'); 1898 } 1899 1900 1901 /** 1902 * performs a logout (web service method) 1903 */ 1904 function ws_session_logout($params, $service) 1905 { 1906 if (!is_a_guest()) 1907 { 1908 logout_user(); 1909 } 1910 return true; 1911 } 1912 1913 function ws_session_getStatus($params, $service) 1914 { 1915 global $user; 1916 $res = array(); 1917 $res['username'] = is_a_guest() ? 'guest' : stripslashes($user['username']); 1918 foreach ( array('status', 'theme', 'language') as $k ) 1919 { 1920 $res[$k] = $user[$k]; 1921 } 1922 $res['pwg_token'] = get_pwg_token(); 1923 $res['charset'] = get_pwg_charset(); 1924 1925 list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();')); 1926 $res['current_datetime'] = $dbnow; 1927 1928 return $res; 1929 } 1930 1931 1932 /** 1933 * returns a list of tags (web service method) 1934 */ 1935 function ws_tags_getList($params, $service) 1936 { 1937 $tags = get_available_tags(); 1938 if ($params['sort_by_counter']) 1939 { 1940 usort($tags, create_function('$a,$b', 'return -$a["counter"]+$b["counter"];') ); 1941 } 1942 else 1943 { 1944 usort($tags, 'tag_alpha_compare'); 1945 } 1946 for ($i=0; $i<count($tags); $i++) 1947 { 1948 $tags[$i]['id'] = (int)$tags[$i]['id']; 1949 $tags[$i]['counter'] = (int)$tags[$i]['counter']; 1950 $tags[$i]['url'] = make_index_url( 1951 array( 1952 'section'=>'tags', 1953 'tags'=>array($tags[$i]) 1954 ) 1955 ); 1956 } 1957 return array('tags' => new PwgNamedArray($tags, 'tag', ws_std_get_tag_xml_attributes()) ); 1958 } 1959 1960 /** 1961 * returns the list of tags as you can see them in administration (web 1962 * service method). 1963 * 1964 * Only admin can run this method and permissions are not taken into 1965 * account. 1966 */ 1967 function ws_tags_getAdminList($params, $service) 1968 { 1969 $tags = get_all_tags(); 1970 return array( 1971 'tags' => new PwgNamedArray( 1972 $tags, 1973 'tag', 1974 ws_std_get_tag_xml_attributes() 1975 ) 1976 ); 1977 } 1978 1979 /** 1980 * returns a list of images for tags (web service method) 1981 */ 1982 function ws_tags_getImages($params, $service) 1983 { 1984 global $conf; 1985 1986 // first build all the tag_ids we are interested in 1987 $tags = find_tags($params['tag_id'], $params['tag_url_name'], $params['tag_name']); 1988 $tags_by_id = array(); 1989 foreach( $tags as $tag ) 1990 { 1991 $tags['id'] = (int)$tag['id']; 1992 $tags_by_id[ $tag['id'] ] = $tag; 1993 } 1994 unset($tags); 1995 $tag_ids = array_keys($tags_by_id); 1996 1997 1998 $where_clauses = ws_std_image_sql_filter($params); 1999 if (!empty($where_clauses)) 2000 { 2001 $where_clauses = implode( ' AND ', $where_clauses); 2002 } 2003 $image_ids = get_image_ids_for_tags( 2004 $tag_ids, 2005 $params['tag_mode_and'] ? 'AND' : 'OR', 2006 $where_clauses, 2007 ws_std_image_sql_order($params) ); 2008 2009 $count_set = count($image_ids); 2010 $image_ids = array_slice($image_ids, $params['per_page']*$params['page'], $params['per_page'] ); 2011 2012 $image_tag_map = array(); 2013 if ( !empty($image_ids) and !$params['tag_mode_and'] ) 2014 { // build list of image ids with associated tags per image 2015 $query = ' 2016 SELECT image_id, GROUP_CONCAT(tag_id) AS tag_ids 2017 FROM '.IMAGE_TAG_TABLE.' 2018 WHERE tag_id IN ('.implode(',',$tag_ids).') AND image_id IN ('.implode(',',$image_ids).') 2019 GROUP BY image_id'; 2020 $result = pwg_query($query); 2021 while ( $row=pwg_db_fetch_assoc($result) ) 2022 { 2023 $row['image_id'] = (int)$row['image_id']; 2024 $image_ids[] = $row['image_id']; 2025 $image_tag_map[ $row['image_id'] ] = explode(',', $row['tag_ids']); 2026 } 2027 } 2028 2029 $images = array(); 2030 if (!empty($image_ids)) 2031 { 2032 $rank_of = array_flip($image_ids); 2033 $result = pwg_query(' 2034 SELECT * FROM '.IMAGES_TABLE.' 2035 WHERE id IN ('.implode(',',$image_ids).')'); 2036 while ($row = pwg_db_fetch_assoc($result)) 2037 { 2038 $image = array(); 2039 $image['rank'] = $rank_of[ $row['id'] ]; 2040 foreach ( array('id', 'width', 'height', 'hit') as $k ) 2041 { 2042 if (isset($row[$k])) 2043 { 2044 $image[$k] = (int)$row[$k]; 2045 } 2046 } 2047 foreach ( array('file', 'name', 'comment', 'date_creation', 'date_available') as $k ) 2048 { 2049 $image[$k] = $row[$k]; 2050 } 2051 $image = array_merge( $image, ws_std_get_urls($row) ); 2052 2053 $image_tag_ids = ($params['tag_mode_and']) ? $tag_ids : $image_tag_map[$image['id']]; 2054 $image_tags = array(); 2055 foreach ($image_tag_ids as $tag_id) 2056 { 2057 $url = make_index_url( 2058 array( 2059 'section'=>'tags', 2060 'tags'=> array($tags_by_id[$tag_id]) 2061 ) 2062 ); 2063 $page_url = make_picture_url( 2064 array( 2065 'section'=>'tags', 2066 'tags'=> array($tags_by_id[$tag_id]), 2067 'image_id' => $row['id'], 2068 'image_file' => $row['file'], 2069 ) 2070 ); 2071 $image_tags[] = array( 2072 'id' => (int)$tag_id, 2073 'url' => $url, 2074 'page_url' => $page_url, 2075 ); 2076 } 2077 $image['tags'] = new PwgNamedArray($image_tags, 'tag', ws_std_get_tag_xml_attributes() ); 2078 $images[] = $image; 2079 } 2080 usort($images, 'rank_compare'); 2081 unset($rank_of); 2082 } 2083 2084 return array( 2085 'paging' => new PwgNamedStruct( 2086 array( 2087 'page' => $params['page'], 2088 'per_page' => $params['per_page'], 2089 'count' => count($images), 2090 'total_count' => $count_set, 2091 ) ), 2092 'images' => new PwgNamedArray($images, 'image', 2093 ws_std_get_image_xml_attributes() ) 2094 ); 2095 } 2096 2097 function ws_categories_add($params, $service) 2098 { 2099 if (!is_admin()) 2100 { 2101 return new PwgError(401, 'Access denied'); 2102 } 2103 2104 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2105 2106 $options = array(); 2107 if (!empty($params['status']) and in_array($params['status'], array('private','public'))) 2108 { 2109 $options['status'] = $params['status']; 2110 } 2111 2112 if (!empty($params['comment'])) 2113 { 2114 $options['comment'] = $params['comment']; 2115 } 2116 2117 2118 $creation_output = create_virtual_category( 2119 $params['name'], 2120 $params['parent'], 2121 $options 2122 ); 2123 2124 if (isset($creation_output['error'])) 2125 { 2126 return new PwgError(500, $creation_output['error']); 2127 } 2128 2129 invalidate_user_cache(); 2130 2131 return $creation_output; 2132 } 2133 2134 function ws_tags_add($params, $service) 2135 { 2136 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2137 2138 $creation_output = create_tag($params['name']); 2139 2140 if (isset($creation_output['error'])) 2141 { 2142 return new PwgError(500, $creation_output['error']); 2143 } 2144 2145 return $creation_output; 2146 } 2147 2148 function ws_images_exist($params, $service) 2149 { 2150 ws_logfile(__FUNCTION__.' '.var_export($params, true)); 2151 2152 global $conf; 2153 2154 $split_pattern = '/[\s,;\|]/'; 2155 2156 if ('md5sum' == $conf['uniqueness_mode']) 2157 { 2158 // search among photos the list of photos already added, based on md5sum 2159 // list 2160 $md5sums = preg_split( 2161 $split_pattern, 2162 $params['md5sum_list'], 2163 -1, 2164 PREG_SPLIT_NO_EMPTY 2165 ); 2166 2167 $query = ' 2168 SELECT 2169 id, 2170 md5sum 2171 FROM '.IMAGES_TABLE.' 2172 WHERE md5sum IN (\''.implode("','", $md5sums).'\') 2173 ;'; 2174 $id_of_md5 = simple_hash_from_query($query, 'md5sum', 'id'); 2175 2176 $result = array(); 2177 2178 foreach ($md5sums as $md5sum) 2179 { 2180 $result[$md5sum] = null; 2181 if (isset($id_of_md5[$md5sum])) 2182 { 2183 $result[$md5sum] = $id_of_md5[$md5sum]; 2184 } 2185 } 2186 } 2187 else if ('filename' == $conf['uniqueness_mode']) 2188 { 2189 // search among photos the list of photos already added, based on 2190 // filename list 2191 $filenames = preg_split( 2192 $split_pattern, 2193 $params['filename_list'], 2194 -1, 2195 PREG_SPLIT_NO_EMPTY 2196 ); 2197 2198 $query = ' 2199 SELECT 2200 id, 2201 file 2202 FROM '.IMAGES_TABLE.' 2203 WHERE file IN (\''.implode("','", $filenames).'\') 2204 ;'; 2205 $id_of_filename = simple_hash_from_query($query, 'file', 'id'); 2206 2207 $result = array(); 2208 2209 foreach ($filenames as $filename) 2210 { 2211 $result[$filename] = null; 2212 if (isset($id_of_filename[$filename])) 2213 { 2214 $result[$filename] = $id_of_filename[$filename]; 2215 } 2216 } 2217 } 2218 2219 return $result; 2220 } 2221 2222 function ws_images_checkFiles($params, $service) 2223 { 2224 ws_logfile(__FUNCTION__.', input : '.var_export($params, true)); 2225 2226 // input parameters 2227 // 2228 // image_id 2229 // thumbnail_sum 2230 // file_sum 2231 // high_sum 2232 2233 $query = ' 2234 SELECT 2235 path 2236 FROM '.IMAGES_TABLE.' 2237 WHERE id = '.$params['image_id'].' 2238 ;'; 2239 $result = pwg_query($query); 2240 if (pwg_db_num_rows($result) == 0) 2241 { 2242 return new PwgError(404, "image_id not found"); 2243 } 2244 list($path) = pwg_db_fetch_row($result); 2245 2246 $ret = array(); 2247 2248 if (isset($params['thumbnail_sum'])) 2249 { 2250 // We always say the thumbnail is equal to create no reaction on the 2251 // other side. Since Piwigo 2.4 and derivatives, the thumbnails and web 2252 // sizes are always generated by Piwigo 2253 $ret['thumbnail'] = 'equals'; 2254 } 2255 2256 if (isset($params['high_sum'])) 2257 { 2258 $ret['file'] = 'equals'; 2259 $compare_type = 'high'; 2260 } 2261 elseif (isset($params['file_sum'])) 2262 { 2263 $compare_type = 'file'; 2264 } 2265 2266 if (isset($compare_type)) 2267 { 2268 ws_logfile(__FUNCTION__.', md5_file($path) = '.md5_file($path)); 2269 if (md5_file($path) != $params[$compare_type.'_sum']) 2270 { 2271 $ret[$compare_type] = 'differs'; 2272 } 2273 else 2274 { 2275 $ret[$compare_type] = 'equals'; 2276 } 2277 } 2278 2279 ws_logfile(__FUNCTION__.', output : '.var_export($ret, true)); 2280 2281 return $ret; 2282 } 2283 2284 function ws_images_setInfo($params, $service) 2285 { 2286 global $conf; 2287 2288 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2289 2290 $query=' 2291 SELECT * 2292 FROM '.IMAGES_TABLE.' 2293 WHERE id = '.$params['image_id'].' 2294 ;'; 2295 $result = pwg_query($query); 2296 2297 if (pwg_db_num_rows($result) == 0) 2298 { 2299 return new PwgError(404, "image_id not found"); 2300 } 2301 2302 $image_row = pwg_db_fetch_assoc($result); 2303 2304 // database registration 2305 $update = array(); 2306 2307 $info_columns = array( 2308 'name', 2309 'author', 2310 'comment', 2311 'level', 2312 'date_creation', 2313 ); 2314 2315 foreach ($info_columns as $key) 2316 { 2317 if (isset($params[$key])) 2318 { 2319 if ('fill_if_empty' == $params['single_value_mode']) 2320 { 2321 if (empty($image_row[$key])) 2322 { 2323 $update[$key] = $params[$key]; 2324 } 2325 } 2326 elseif ('replace' == $params['single_value_mode']) 2327 { 2328 $update[$key] = $params[$key]; 2329 } 2330 else 2331 { 2332 return new PwgError( 2333 500, 2334 '[ws_images_setInfo]' 2335 .' invalid parameter single_value_mode "'.$params['single_value_mode'].'"' 2336 .', possible values are {fill_if_empty, replace}.' 2337 ); 2338 } 2339 } 2340 } 2341 2342 if (isset($params['file'])) 2343 { 2344 if (!empty($image_row['storage_category_id'])) 2345 { 2346 return new PwgError(500, '[ws_images_setInfo] updating "file" is forbidden on photos added by synchronization'); 2347 } 2348 2349 $update['file'] = $params['file']; 2350 } 2351 2352 if (count(array_keys($update)) > 0) 2353 { 2354 $update['id'] = $params['image_id']; 2355 2356 single_update( 2357 IMAGES_TABLE, 2358 $update, 2359 array('id' => $update['id']) 2360 ); 2361 } 2362 2363 if (isset($params['categories'])) 2364 { 2365 ws_add_image_category_relations( 2366 $params['image_id'], 2367 $params['categories'], 2368 ('replace' == $params['multiple_value_mode'] ? true : false) 2369 ); 2370 } 2371 2372 // and now, let's create tag associations 2373 if (isset($params['tag_ids'])) 2374 { 2375 $tag_ids = array(); 2376 2377 foreach (explode(',', $params['tag_ids']) as $candidate) 2378 { 2379 $candidate = trim($candidate); 2380 2381 if (preg_match(PATTERN_ID, $candidate)) 2382 { 2383 $tag_ids[] = $candidate; 2384 } 2385 } 2386 2387 if ('replace' == $params['multiple_value_mode']) 2388 { 2389 set_tags( 2390 $tag_ids, 2391 $params['image_id'] 2392 ); 2393 } 2394 elseif ('append' == $params['multiple_value_mode']) 2395 { 2396 add_tags( 2397 $tag_ids, 2398 array($params['image_id']) 2399 ); 2400 } 2401 else 2402 { 2403 return new PwgError( 2404 500, 2405 '[ws_images_setInfo]' 2406 .' invalid parameter multiple_value_mode "'.$params['multiple_value_mode'].'"' 2407 .', possible values are {replace, append}.' 2408 ); 2409 } 2410 } 2411 2412 invalidate_user_cache(); 2413 } 2414 2415 function ws_images_delete($params, $service) 2416 { 2417 global $conf; 2418 2419 if (get_pwg_token() != $params['pwg_token']) 2420 { 2421 return new PwgError(403, 'Invalid security token'); 2422 } 2423 2424 if (!is_array($params['image_id'])) 2425 { 2426 $params['image_id'] = preg_split( 2427 '/[\s,;\|]/', 2428 $params['image_id'], 2429 -1, 2430 PREG_SPLIT_NO_EMPTY 2431 ); 2432 } 2433 $params['image_id'] = array_map('intval', $params['image_id']); 2434 2435 $image_ids = array(); 2436 foreach ($params['image_id'] as $image_id) 2437 { 2438 if ($image_id > 0) 2439 { 2440 $image_ids[] = $image_id; 2441 } 2442 } 2443 2444 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2445 delete_elements($image_ids, true); 2446 invalidate_user_cache(); 2447 } 2448 2449 function ws_add_image_category_relations($image_id, $categories_string, $replace_mode=false) 2450 { 2451 // let's add links between the image and the categories 2452 // 2453 // $params['categories'] should look like 123,12;456,auto;789 which means: 2454 // 2455 // 1. associate with category 123 on rank 12 2456 // 2. associate with category 456 on automatic rank 2457 // 3. associate with category 789 on automatic rank 2458 $cat_ids = array(); 2459 $rank_on_category = array(); 2460 $search_current_ranks = false; 2461 2462 $tokens = explode(';', $categories_string); 2463 foreach ($tokens as $token) 2464 { 2465 @list($cat_id, $rank) = explode(',', $token); 2466 2467 if (!preg_match('/^\d+$/', $cat_id)) 2468 { 2469 continue; 2470 } 2471 2472 $cat_ids[] = $cat_id; 2473 2474 if (!isset($rank)) 2475 { 2476 $rank = 'auto'; 2477 } 2478 $rank_on_category[$cat_id] = $rank; 2479 2480 if ($rank == 'auto') 2481 { 2482 $search_current_ranks = true; 2483 } 2484 } 2485 2486 $cat_ids = array_unique($cat_ids); 2487 2488 if (count($cat_ids) == 0) 2489 { 2490 return new PwgError( 2491 500, 2492 '[ws_add_image_category_relations] there is no category defined in "'.$categories_string.'"' 2493 ); 2494 } 2495 2496 $query = ' 2497 SELECT 2498 id 2499 FROM '.CATEGORIES_TABLE.' 2500 WHERE id IN ('.implode(',', $cat_ids).') 2501 ;'; 2502 $db_cat_ids = array_from_query($query, 'id'); 2503 2504 $unknown_cat_ids = array_diff($cat_ids, $db_cat_ids); 2505 if (count($unknown_cat_ids) != 0) 2506 { 2507 return new PwgError( 2508 500, 2509 '[ws_add_image_category_relations] the following categories are unknown: '.implode(', ', $unknown_cat_ids) 2510 ); 2511 } 2512 2513 $to_update_cat_ids = array(); 2514 2515 // in case of replace mode, we first check the existing associations 2516 $query = ' 2517 SELECT 2518 category_id 2519 FROM '.IMAGE_CATEGORY_TABLE.' 2520 WHERE image_id = '.$image_id.' 2521 ;'; 2522 $existing_cat_ids = array_from_query($query, 'category_id'); 2523 2524 if ($replace_mode) 2525 { 2526 $to_remove_cat_ids = array_diff($existing_cat_ids, $cat_ids); 2527 if (count($to_remove_cat_ids) > 0) 2528 { 2529 $query = ' 2530 DELETE 2531 FROM '.IMAGE_CATEGORY_TABLE.' 2532 WHERE image_id = '.$image_id.' 2533 AND category_id IN ('.implode(', ', $to_remove_cat_ids).') 2534 ;'; 2535 pwg_query($query); 2536 update_category($to_remove_cat_ids); 2537 } 2538 } 2539 2540 $new_cat_ids = array_diff($cat_ids, $existing_cat_ids); 2541 if (count($new_cat_ids) == 0) 2542 { 2543 return true; 2544 } 2545 2546 if ($search_current_ranks) 2547 { 2548 $query = ' 2549 SELECT 2550 category_id, 2551 MAX(rank) AS max_rank 2552 FROM '.IMAGE_CATEGORY_TABLE.' 2553 WHERE rank IS NOT NULL 2554 AND category_id IN ('.implode(',', $new_cat_ids).') 2555 GROUP BY category_id 2556 ;'; 2557 $current_rank_of = simple_hash_from_query( 2558 $query, 2559 'category_id', 2560 'max_rank' 2561 ); 2562 2563 foreach ($new_cat_ids as $cat_id) 2564 { 2565 if (!isset($current_rank_of[$cat_id])) 2566 { 2567 $current_rank_of[$cat_id] = 0; 2568 } 2569 2570 if ('auto' == $rank_on_category[$cat_id]) 2571 { 2572 $rank_on_category[$cat_id] = $current_rank_of[$cat_id] + 1; 2573 } 2574 } 2575 } 2576 2577 $inserts = array(); 2578 2579 foreach ($new_cat_ids as $cat_id) 2580 { 2581 $inserts[] = array( 2582 'image_id' => $image_id, 2583 'category_id' => $cat_id, 2584 'rank' => $rank_on_category[$cat_id], 2585 ); 2586 } 2587 2588 mass_inserts( 2589 IMAGE_CATEGORY_TABLE, 2590 array_keys($inserts[0]), 2591 $inserts 2592 ); 2593 2594 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2595 update_category($new_cat_ids); 2596 } 2597 2598 function ws_categories_setInfo($params, $service) 2599 { 2600 global $conf; 2601 2602 // category_id 2603 // name 2604 // comment 2605 2606 // database registration 2607 $update = array( 2608 'id' => $params['category_id'], 2609 ); 2610 2611 $info_columns = array( 2612 'name', 2613 'comment', 2614 ); 2615 2616 $perform_update = false; 2617 foreach ($info_columns as $key) 2618 { 2619 if (isset($params[$key])) 2620 { 2621 $perform_update = true; 2622 $update[$key] = $params[$key]; 2623 } 2624 } 2625 2626 if ($perform_update) 2627 { 2628 single_update( 2629 CATEGORIES_TABLE, 2630 $update, 2631 array('id' => $update['id']) 2632 ); 2633 } 2634 } 2635 2636 function ws_categories_setRepresentative($params, $service) 2637 { 2638 global $conf; 2639 2640 // category_id 2641 // image_id 2642 2643 // does the category really exist? 2644 $query=' 2645 SELECT COUNT(*) 2646 FROM '.CATEGORIES_TABLE.' 2647 WHERE id = '.$params['category_id'].' 2648 ;'; 2649 list($count) = pwg_db_fetch_row(pwg_query($query)); 2650 if ($count == 0) 2651 { 2652 return new PwgError(404, "category_id not found"); 2653 } 2654 2655 // does the image really exist? 2656 $query=' 2657 SELECT COUNT(*) 2658 FROM '.IMAGES_TABLE.' 2659 WHERE id = '.$params['image_id'].' 2660 ;'; 2661 2662 list($count) = pwg_db_fetch_row(pwg_query($query)); 2663 if ($count == 0) 2664 { 2665 return new PwgError(404, "image_id not found"); 2666 } 2667 2668 // apply change 2669 $query = ' 2670 UPDATE '.CATEGORIES_TABLE.' 2671 SET representative_picture_id = '.$params['image_id'].' 2672 WHERE id = '.$params['category_id'].' 2673 ;'; 2674 pwg_query($query); 2675 2676 $query = ' 2677 UPDATE '.USER_CACHE_CATEGORIES_TABLE.' 2678 SET user_representative_picture_id = NULL 2679 WHERE cat_id = '.$params['category_id'].' 2680 ;'; 2681 pwg_query($query); 2682 } 2683 2684 function ws_categories_delete($params, $service) 2685 { 2686 global $conf; 2687 2688 if (get_pwg_token() != $params['pwg_token']) 2689 { 2690 return new PwgError(403, 'Invalid security token'); 2691 } 2692 2693 $modes = array('no_delete', 'delete_orphans', 'force_delete'); 2694 if (!in_array($params['photo_deletion_mode'], $modes)) 2695 { 2696 return new PwgError( 2697 500, 2698 '[ws_categories_delete]' 2699 .' invalid parameter photo_deletion_mode "'.$params['photo_deletion_mode'].'"' 2700 .', possible values are {'.implode(', ', $modes).'}.' 2701 ); 2702 } 2703 2704 if (!is_array($params['category_id'])) 2705 { 2706 $params['category_id'] = preg_split( 2707 '/[\s,;\|]/', 2708 $params['category_id'], 2709 -1, 2710 PREG_SPLIT_NO_EMPTY 2711 ); 2712 } 2713 $params['category_id'] = array_map('intval', $params['category_id']); 2714 2715 $category_ids = array(); 2716 foreach ($params['category_id'] as $category_id) 2717 { 2718 if ($category_id > 0) 2719 { 2720 $category_ids[] = $category_id; 2721 } 2722 } 2723 2724 if (count($category_ids) == 0) 2725 { 2726 return; 2727 } 2728 2729 $query = ' 2730 SELECT id 2731 FROM '.CATEGORIES_TABLE.' 2732 WHERE id IN ('.implode(',', $category_ids).') 2733 ;'; 2734 $category_ids = array_from_query($query, 'id'); 2735 2736 if (count($category_ids) == 0) 2737 { 2738 return; 2739 } 2740 2741 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2742 delete_categories($category_ids, $params['photo_deletion_mode']); 2743 update_global_rank(); 2744 } 2745 2746 function ws_categories_move($params, $service) 2747 { 2748 global $conf, $page; 2749 2750 if (get_pwg_token() != $params['pwg_token']) 2751 { 2752 return new PwgError(403, 'Invalid security token'); 2753 } 2754 2755 if (!is_array($params['category_id'])) 2756 { 2757 $params['category_id'] = preg_split( 2758 '/[\s,;\|]/', 2759 $params['category_id'], 2760 -1, 2761 PREG_SPLIT_NO_EMPTY 2762 ); 2763 } 2764 $params['category_id'] = array_map('intval', $params['category_id']); 2765 2766 $category_ids = array(); 2767 foreach ($params['category_id'] as $category_id) 2768 { 2769 if ($category_id > 0) 2770 { 2771 $category_ids[] = $category_id; 2772 } 2773 } 2774 2775 if (count($category_ids) == 0) 2776 { 2777 return new PwgError(403, 'Invalid category_id input parameter, no category to move'); 2778 } 2779 2780 // we can't move physical categories 2781 $categories_in_db = array(); 2782 2783 $query = ' 2784 SELECT 2785 id, 2786 name, 2787 dir 2788 FROM '.CATEGORIES_TABLE.' 2789 WHERE id IN ('.implode(',', $category_ids).') 2790 ;'; 2791 $result = pwg_query($query); 2792 while ($row = pwg_db_fetch_assoc($result)) 2793 { 2794 $categories_in_db[$row['id']] = $row; 2795 // we break on error at first physical category detected 2796 if (!empty($row['dir'])) 2797 { 2798 $row['name'] = strip_tags( 2799 trigger_event( 2800 'render_category_name', 2801 $row['name'], 2802 'ws_categories_move' 2803 ) 2804 ); 2805 2806 return new PwgError( 2807 403, 2808 sprintf( 2809 'Category %s (%u) is not a virtual category, you cannot move it', 2810 $row['name'], 2811 $row['id'] 2812 ) 2813 ); 2814 } 2815 } 2816 2817 if (count($categories_in_db) != count($category_ids)) 2818 { 2819 $unknown_category_ids = array_diff($category_ids, array_keys($categories_in_db)); 2820 2821 return new PwgError( 2822 403, 2823 sprintf( 2824 'Category %u does not exist', 2825 $unknown_category_ids[0] 2826 ) 2827 ); 2828 } 2829 2830 // does this parent exists? This check should be made in the 2831 // move_categories function, not here 2832 // 0 as parent means "move categories at gallery root" 2833 if (0 != $params['parent']) { 2834 $subcat_ids = get_subcat_ids(array($params['parent'])); 2835 if (count($subcat_ids) == 0) 2836 { 2837 return new PwgError(403, 'Unknown parent category id'); 2838 } 2839 } 2840 2841 $page['infos'] = array(); 2842 $page['errors'] = array(); 2843 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2844 move_categories($category_ids, $params['parent']); 2845 invalidate_user_cache(); 2846 2847 if (count($page['errors']) != 0) 2848 { 2849 return new PwgError(403, implode('; ', $page['errors'])); 2850 } 2851 } 2852 2853 function ws_logfile($string) 2854 { 2855 global $conf; 2856 2857 if (!$conf['ws_enable_log']) { 213 214 if (!$conf['ws_enable_log']) 215 { 2858 216 return true; 2859 217 } … … 2866 224 } 2867 225 2868 function ws_images_checkUpload($params, $service) 2869 { 2870 global $conf; 2871 2872 include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php'); 2873 $ret['message'] = ready_for_upload_message(); 2874 $ret['ready_for_upload'] = true; 2875 2876 if (!empty($ret['message'])) 2877 { 2878 $ret['ready_for_upload'] = false; 2879 } 2880 2881 return $ret; 2882 } 2883 2884 function ws_plugins_getList($params, $service) 2885 { 2886 global $conf; 2887 2888 include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php'); 2889 $plugins = new plugins(); 2890 $plugins->sort_fs_plugins('name'); 2891 $plugin_list = array(); 2892 2893 foreach($plugins->fs_plugins as $plugin_id => $fs_plugin) 2894 { 2895 if (isset($plugins->db_plugins_by_id[$plugin_id])) 2896 { 2897 $state = $plugins->db_plugins_by_id[$plugin_id]['state']; 226 /** 227 * create a tree from a flat list of categories, no recursivity for high speed 228 */ 229 function categories_flatlist_to_tree($categories) 230 { 231 $tree = array(); 232 $key_of_cat = array(); 233 234 foreach ($categories as $key => &$node) 235 { 236 $key_of_cat[$node['id']] = $key; 237 238 if (!isset($node['id_uppercat'])) 239 { 240 $tree[] = &$node; 2898 241 } 2899 242 else 2900 243 { 2901 $state = 'uninstalled'; 2902 } 2903 2904 $plugin_list[] = 2905 array( 2906 'id' => $plugin_id, 2907 'name' => $fs_plugin['name'], 2908 'version' => $fs_plugin['version'], 2909 'state' => $state, 2910 'description' => $fs_plugin['description'], 2911 ); 2912 } 2913 2914 return $plugin_list; 2915 } 2916 2917 function ws_plugins_performAction($params, &$service) 2918 { 2919 global $template; 2920 2921 if (get_pwg_token() != $params['pwg_token']) 2922 { 2923 return new PwgError(403, 'Invalid security token'); 2924 } 2925 2926 define('IN_ADMIN', true); 2927 include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php'); 2928 $plugins = new plugins(); 2929 $errors = $plugins->perform_action($params['action'], $params['plugin']); 2930 2931 2932 if (!empty($errors)) 2933 { 2934 return new PwgError(500, $errors); 2935 } 2936 else 2937 { 2938 if (in_array($params['action'], array('activate', 'deactivate'))) 2939 { 2940 $template->delete_compiled_templates(); 2941 } 2942 return true; 2943 } 2944 } 2945 2946 function ws_themes_performAction($params, $service) 2947 { 2948 global $template; 2949 2950 if (get_pwg_token() != $params['pwg_token']) 2951 { 2952 return new PwgError(403, 'Invalid security token'); 2953 } 2954 2955 define('IN_ADMIN', true); 2956 include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php'); 2957 $themes = new themes(); 2958 $errors = $themes->perform_action($params['action'], $params['theme']); 2959 2960 if (!empty($errors)) 2961 { 2962 return new PwgError(500, $errors); 2963 } 2964 else 2965 { 2966 if (in_array($params['action'], array('activate', 'deactivate'))) 2967 { 2968 $template->delete_compiled_templates(); 2969 } 2970 return true; 2971 } 2972 } 2973 2974 function ws_extensions_update($params, $service) 2975 { 2976 if (!is_webmaster()) 2977 { 2978 return new PwgError(401, l10n('Webmaster status is required.')); 2979 } 2980 2981 if (get_pwg_token() != $params['pwg_token']) 2982 { 2983 return new PwgError(403, 'Invalid security token'); 2984 } 2985 2986 if (!in_array($params['type'], array('plugins', 'themes', 'languages'))) 2987 { 2988 return new PwgError(403, "invalid extension type"); 2989 } 2990 2991 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 2992 include_once(PHPWG_ROOT_PATH.'admin/include/'.$params['type'].'.class.php'); 2993 2994 $type = $params['type']; 2995 $extension_id = $params['id']; 2996 $revision = $params['revision']; 2997 2998 $extension = new $type(); 2999 3000 if ($type == 'plugins') 3001 { 3002 if (isset($extension->db_plugins_by_id[$extension_id]) and $extension->db_plugins_by_id[$extension_id]['state'] == 'active') 3003 { 3004 $extension->perform_action('deactivate', $extension_id); 3005 3006 redirect(PHPWG_ROOT_PATH 3007 . 'ws.php' 3008 . '?method=pwg.extensions.update' 3009 . '&type=plugins' 3010 . '&id=' . $extension_id 3011 . '&revision=' . $revision 3012 . '&reactivate=true' 3013 . '&pwg_token=' . get_pwg_token() 3014 . '&format=json' 3015 ); 3016 } 3017 3018 $upgrade_status = $extension->extract_plugin_files('upgrade', $revision, $extension_id); 3019 $extension_name = $extension->fs_plugins[$extension_id]['name']; 3020 3021 if (isset($params['reactivate'])) 3022 { 3023 $extension->perform_action('activate', $extension_id); 3024 } 3025 } 3026 elseif ($type == 'themes') 3027 { 3028 $upgrade_status = $extension->extract_theme_files('upgrade', $revision, $extension_id); 3029 $extension_name = $extension->fs_themes[$extension_id]['name']; 3030 } 3031 elseif ($type == 'languages') 3032 { 3033 $upgrade_status = $extension->extract_language_files('upgrade', $revision, $extension_id); 3034 $extension_name = $extension->fs_languages[$extension_id]['name']; 3035 } 3036 3037 global $template; 3038 $template->delete_compiled_templates(); 3039 3040 switch ($upgrade_status) 3041 { 3042 case 'ok': 3043 return l10n('%s has been successfully updated.', $extension_name); 3044 3045 case 'temp_path_error': 3046 return new PwgError(null, l10n('Can\'t create temporary file.')); 3047 3048 case 'dl_archive_error': 3049 return new PwgError(null, l10n('Can\'t download archive.')); 3050 3051 case 'archive_error': 3052 return new PwgError(null, l10n('Can\'t read or extract archive.')); 3053 3054 default: 3055 return new PwgError(null, l10n('An error occured during extraction (%s).', $upgrade_status)); 3056 } 3057 } 3058 3059 function ws_extensions_ignoreupdate($params, $service) 3060 { 3061 global $conf; 3062 3063 define('IN_ADMIN', true); 3064 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3065 3066 if (!is_webmaster()) 3067 { 3068 return new PwgError(401, 'Access denied'); 3069 } 3070 3071 if (get_pwg_token() != $params['pwg_token']) 3072 { 3073 return new PwgError(403, 'Invalid security token'); 3074 } 3075 3076 $conf['updates_ignored'] = unserialize($conf['updates_ignored']); 3077 3078 // Reset ignored extension 3079 if ($params['reset']) 3080 { 3081 if (!empty($params['type']) and isset($conf['updates_ignored'][$params['type']])) 3082 { 3083 $conf['updates_ignored'][$params['type']] = array(); 3084 } 3085 else 3086 { 3087 $conf['updates_ignored'] = array( 3088 'plugins'=>array(), 3089 'themes'=>array(), 3090 'languages'=>array() 3091 ); 3092 } 3093 conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored']))); 3094 unset($_SESSION['extensions_need_update']); 3095 return true; 3096 } 3097 3098 if (empty($params['id']) or empty($params['type']) or !in_array($params['type'], array('plugins', 'themes', 'languages'))) 3099 { 3100 return new PwgError(403, 'Invalid parameters'); 3101 } 3102 3103 // Add or remove extension from ignore list 3104 if (!in_array($params['id'], $conf['updates_ignored'][$params['type']])) 3105 { 3106 $conf['updates_ignored'][ $params['type'] ][] = $params['id']; 3107 } 3108 conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored']))); 3109 unset($_SESSION['extensions_need_update']); 3110 return true; 3111 } 3112 3113 function ws_extensions_checkupdates($params, $service) 3114 { 3115 global $conf; 3116 3117 define('IN_ADMIN', true); 3118 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3119 include_once(PHPWG_ROOT_PATH.'admin/include/updates.class.php'); 3120 $update = new updates(); 3121 3122 $result = array(); 3123 3124 if (!isset($_SESSION['need_update'])) 3125 $update->check_piwigo_upgrade(); 3126 3127 $result['piwigo_need_update'] = $_SESSION['need_update']; 3128 3129 $conf['updates_ignored'] = unserialize($conf['updates_ignored']); 3130 3131 if (!isset($_SESSION['extensions_need_update'])) 3132 $update->check_extensions(); 3133 else 3134 $update->check_updated_extensions(); 3135 3136 if (!is_array($_SESSION['extensions_need_update'])) 3137 $result['ext_need_update'] = null; 3138 else 3139 $result['ext_need_update'] = !empty($_SESSION['extensions_need_update']); 3140 3141 return $result; 3142 } 3143 3144 /** 3145 * API method 3146 * Returns the list of groups 3147 * @param mixed[] $params 3148 * @option int[] group_id (optional) 3149 * @option string name (optional) 3150 */ 3151 function ws_groups_getList($params, &$service) 3152 { 3153 $where_clauses = array('1=1'); 3154 3155 if (!empty($params['name'])) 3156 { 3157 $where_clauses[] = 'LOWER(name) LIKE \''. pwg_db_real_escape_string($params['name']) .'\''; 3158 } 3159 3160 if (!empty($params['group_id'])) 3161 { 3162 $where_clauses[] = 'id IN('. implode(',', $params['group_id']) .')'; 3163 } 3164 3165 $query = ' 3166 SELECT 3167 g.*, 3168 COUNT(user_id) AS nb_users 3169 FROM '.GROUPS_TABLE.' AS g 3170 LEFT JOIN '.USER_GROUP_TABLE.' AS ug 3171 ON ug.group_id = g.id 3172 WHERE '. implode(' AND ', $where_clauses) .' 3173 GROUP BY id 3174 ORDER BY '.$params['order'].' 3175 LIMIT '.$params['per_page'].' 3176 OFFSET '.($params['per_page']*$params['page']).' 3177 ;'; 3178 3179 $groups = array_from_query($query); 3180 3181 return array( 3182 'paging' => new PwgNamedStruct(array( 3183 'page' => $params['page'], 3184 'per_page' => $params['per_page'], 3185 'count' => count($groups) 3186 )), 3187 'groups' => new PwgNamedArray($groups, 'group') 3188 ); 3189 } 3190 3191 /** 3192 * API method 3193 * Adds a group 3194 * @param mixed[] $params 3195 * @option string name 3196 * @option bool is_default 3197 */ 3198 function ws_groups_add($params, &$service) 3199 { 3200 $params['name'] = pwg_db_real_escape_string($params['name']); 3201 3202 // is the name not already used ? 3203 $query = ' 3204 SELECT COUNT(*) 3205 FROM '.GROUPS_TABLE.' 3206 WHERE name = \''.$params['name'].'\' 3207 ;'; 3208 list($count) = pwg_db_fetch_row(pwg_query($query)); 3209 if ($count != 0) 3210 { 3211 return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already used by another group.'); 3212 } 3213 3214 // creating the group 3215 single_insert( 3216 GROUPS_TABLE, 3217 array( 3218 'name' => $params['name'], 3219 'is_default' => boolean_to_string($params['is_default']), 3220 ) 3221 ); 3222 3223 return $service->invoke('pwg.groups.getList', array('group_id' => pwg_db_insert_id())); 3224 } 3225 3226 /** 3227 * API method 3228 * Deletes a group 3229 * @param mixed[] $params 3230 * @option int[] group_id 3231 */ 3232 function ws_groups_delete($params, &$service) 3233 { 3234 $group_id_string = implode(',', $params['group_id']); 3235 3236 // destruction of the access linked to the group 3237 $query = ' 3238 DELETE 3239 FROM '.GROUP_ACCESS_TABLE.' 3240 WHERE group_id IN('. $group_id_string .') 3241 ;'; 3242 pwg_query($query); 3243 3244 // destruction of the users links for this group 3245 $query = ' 3246 DELETE 3247 FROM '.USER_GROUP_TABLE.' 3248 WHERE group_id IN('. $group_id_string .') 3249 ;'; 3250 pwg_query($query); 3251 3252 $query = ' 3253 SELECT name 3254 FROM '.GROUPS_TABLE.' 3255 WHERE id IN('. $group_id_string .') 3256 ;'; 3257 $groupnames = array_from_query($query, 'name'); 3258 3259 // destruction of the group 3260 $query = ' 3261 DELETE 3262 FROM '.GROUPS_TABLE.' 3263 WHERE id IN('. $group_id_string .') 3264 ;'; 3265 pwg_query($query); 3266 3267 return new PwgNamedArray($groupnames, 'group_deleted'); 3268 } 3269 3270 /** 3271 * API method 3272 * Updates a group 3273 * @param mixed[] $params 3274 * @option int group_id 3275 * @option string name (optional) 3276 * @option bool is_default (optional) 3277 */ 3278 function ws_groups_setInfo($params, &$service) 3279 { 3280 $updates = array(); 3281 3282 // does the group exist ? 3283 $query = ' 3284 SELECT COUNT(*) 3285 FROM '.GROUPS_TABLE.' 3286 WHERE id = '.$params['group_id'].' 3287 ;'; 3288 list($count) = pwg_db_fetch_row(pwg_query($query)); 3289 if ($count == 0) 3290 { 3291 return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 3292 } 3293 3294 if (!empty($params['name'])) 3295 { 3296 $params['name'] = pwg_db_real_escape_string($params['name']); 3297 3298 // is the name not already used ? 3299 $query = ' 3300 SELECT COUNT(*) 3301 FROM '.GROUPS_TABLE.' 3302 WHERE name = \''.$params['name'].'\' 3303 ;'; 3304 list($count) = pwg_db_fetch_row(pwg_query($query)); 3305 if ($count != 0) 3306 { 3307 return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already used by another group.'); 3308 } 3309 3310 $updates['name'] = $params['name']; 3311 } 3312 3313 if (!empty($params['is_default']) or @$params['is_default']===false) 3314 { 3315 $updates['is_default'] = boolean_to_string($params['is_default']); 3316 } 3317 3318 single_update( 3319 GROUPS_TABLE, 3320 $updates, 3321 array('id' => $params['group_id']) 3322 ); 3323 3324 return $service->invoke('pwg.groups.getList', array('group_id' => $params['group_id'])); 3325 } 3326 3327 /** 3328 * API method 3329 * Adds user(s) to a group 3330 * @param mixed[] $params 3331 * @option int group_id 3332 * @option int[] user_id 3333 */ 3334 function ws_groups_addUser($params, &$service) 3335 { 3336 // does the group exist ? 3337 $query = ' 3338 SELECT COUNT(*) 3339 FROM '.GROUPS_TABLE.' 3340 WHERE id = '.$params['group_id'].' 3341 ;'; 3342 list($count) = pwg_db_fetch_row(pwg_query($query)); 3343 if ($count == 0) 3344 { 3345 return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 3346 } 3347 3348 $inserts = array(); 3349 foreach ($params['user_id'] as $user_id) 3350 { 3351 $inserts[] = array( 3352 'group_id' => $params['group_id'], 3353 'user_id' => $user_id, 3354 ); 3355 } 3356 3357 mass_inserts( 3358 USER_GROUP_TABLE, 3359 array('group_id', 'user_id'), 3360 $inserts, 3361 array('ignore'=>true) 3362 ); 3363 3364 return $service->invoke('pwg.users.getList', array('group_id' => $params['group_id'])); 3365 } 3366 3367 /** 3368 * API method 3369 * Removes user(s) from a group 3370 * @param mixed[] $params 3371 * @option int group_id 3372 * @option int[] user_id 3373 */ 3374 function ws_groups_deleteUser($params, &$service) 3375 { 3376 // does the group exist ? 3377 $query = ' 3378 SELECT COUNT(*) 3379 FROM '.GROUPS_TABLE.' 3380 WHERE id = '.$params['group_id'].' 3381 ;'; 3382 list($count) = pwg_db_fetch_row(pwg_query($query)); 3383 if ($count == 0) 3384 { 3385 return new PwgError(WS_ERR_INVALID_PARAM, 'This group does not exist.'); 3386 } 3387 3388 $query = ' 3389 DELETE FROM '.USER_GROUP_TABLE.' 3390 WHERE 3391 group_id = '.$params['group_id'].' 3392 AND user_id IN('. implode(',', $params['user_id']) .') 3393 ;'; 3394 pwg_query($query); 3395 3396 return $service->invoke('pwg.users.getList', array('group_id' => $params['group_id'])); 3397 } 3398 3399 /** 3400 * API method 3401 * Returns a list of users 3402 * @param mixed[] $params 3403 * @option int[] user_id (optional) 3404 * @option string username (optional) 3405 * @option string[] status (optional) 3406 * @option int min_level (optional) 3407 * @option int[] group_id (optional) 3408 * @option int per_page 3409 * @option int page 3410 * @option string order 3411 */ 3412 function ws_users_getList($params, &$service) 3413 { 3414 global $conf; 3415 3416 $where_clauses = array('1=1'); 3417 3418 if (!empty($params['user_id'])) 3419 { 3420 $where_clauses[] = 'u.'.$conf['user_fields']['id'].' IN('. implode(',', $params['user_id']) .')'; 3421 } 3422 3423 if (!empty($params['username'])) 3424 { 3425 $where_clauses[] = 'u.'.$conf['user_fields']['username'].' LIKE \''.pwg_db_real_escape_string($params['username']).'\''; 3426 } 3427 3428 if (!empty($params['status'])) 3429 { 3430 $params['status'] = array_intersect($params['status'], get_enums(USER_INFOS_TABLE, 'status')); 3431 if (count($params['status']) > 0) 3432 { 3433 $where_clauses[] = 'ui.status IN("'. implode('","', $params['status']) .'")'; 3434 } 3435 } 3436 3437 if (!empty($params['min_level'])) 3438 { 3439 if ( !in_array($params['min_level'], $conf['available_permission_levels']) ) 3440 { 3441 return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level'); 3442 } 3443 $where_clauses[] = 'ui.level >= '.$params['min_level']; 3444 } 3445 3446 if (!empty($params['group_id'])) 3447 { 3448 $where_clauses[] = 'ug.group_id IN('. implode(',', $params['group_id']) .')'; 3449 } 3450 3451 $display = array('u.'.$conf['user_fields']['id'] => 'id'); 3452 3453 if ($params['display'] != 'none') 3454 { 3455 $params['display'] = explode(',', $params['display']); 3456 3457 if (in_array('all', $params['display'])) 3458 { 3459 $params['display'] = array_merge($params['display'], array( 3460 'username','email','status','level','groups','language','theme', 3461 'nb_image_page','recent_period','expand','show_nb_comments','show_nb_hits', 3462 'enabled_high', 3463 )); 3464 } 3465 else if (in_array('basics', $params['display'])) 3466 { 3467 $params['display'] = array_merge($params['display'], array( 3468 'username','email','status','level','groups', 3469 )); 3470 } 3471 3472 if (in_array('username', $params['display'])) 3473 { 3474 $display['u.'.$conf['user_fields']['username']] = 'username'; 3475 } 3476 if (in_array('email', $params['display'])) 3477 { 3478 $display['u.'.$conf['user_fields']['email']] = 'email'; 3479 } 3480 3481 $ui_fields = array( 3482 'status','level','language','theme','nb_image_page','recent_period','expand', 3483 'show_nb_comments','show_nb_hits','enabled_high', 3484 ); 3485 foreach ($ui_fields as $field) 3486 { 3487 if (in_array($field, $params['display'])) 244 if (!isset($categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'])) 3488 245 { 3489 $display['ui.'.$field] = $field; 246 $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories'] = 247 new PwgNamedArray(array(), 'category', ws_std_get_category_xml_attributes()); 3490 248 } 3491 } 3492 } 3493 else 3494 { 3495 $params['display'] = array(); 3496 } 3497 3498 $query = ' 3499 SELECT DISTINCT '; 3500 3501 $first = true; 3502 foreach ($display as $field => $name) 3503 { 3504 if (!$first) $query.= ', '; 3505 else $first = false; 3506 $query.= $field .' AS '. $name; 3507 } 3508 if (in_array('groups', $params['display'])) 3509 { 3510 if (!$first) $query.= ', '; 3511 $query.= '"" AS groups'; 3512 } 3513 3514 $query.= ' 3515 FROM '.USERS_TABLE.' AS u 3516 INNER JOIN '.USER_INFOS_TABLE.' AS ui 3517 ON u.'.$conf['user_fields']['id'].' = ui.user_id 3518 LEFT JOIN '.USER_GROUP_TABLE.' AS ug 3519 ON u.'.$conf['user_fields']['id'].' = ug.user_id 3520 WHERE 3521 '. implode(' AND ', $where_clauses) .' 3522 ORDER BY '.$params['order'].' 3523 LIMIT '.$params['per_page'].' 3524 OFFSET '.($params['per_page']*$params['page']).' 3525 ;'; 3526 3527 $users = hash_from_query($query, 'id'); 3528 3529 if ( count($users) > 0 and in_array('groups', $params['display']) ) 3530 { 3531 $query = ' 3532 SELECT user_id, group_id 3533 FROM '.USER_GROUP_TABLE.' 3534 WHERE user_id IN ('.implode(',', array_keys($users)).') 3535 ;'; 3536 $result = pwg_query($query); 3537 3538 while ($row = pwg_db_fetch_assoc($result)) 3539 { 3540 $users[ $row['user_id'] ]['groups'][] = $row['group_id']; 3541 } 3542 } 3543 3544 return array( 3545 'paging' => new PwgNamedStruct(array( 3546 'page' => $params['page'], 3547 'per_page' => $params['per_page'], 3548 'count' => count($users) 3549 )), 3550 'users' => new PwgNamedArray(array_values($users), 'user') 3551 ); 3552 } 3553 3554 /** 3555 * API method 3556 * Adds a user 3557 * @param mixed[] $params 3558 * @option string username 3559 * @option string password (optional) 3560 * @option string email (optional) 3561 */ 3562 function ws_users_add($params, &$service) 3563 { 3564 global $conf; 3565 3566 if ($conf['double_password_type_in_admin']) 3567 { 3568 if ($params['password'] != $params['password_confirm']) 3569 { 3570 return new PwgError(WS_ERR_INVALID_PARAM, l10n('The passwords do not match')); 3571 } 3572 } 3573 3574 $user_id = register_user( 3575 $params['username'], 3576 $params['password'], 3577 $params['email'], 3578 false, // notify admin 3579 $errors, 3580 $params['send_password_by_mail'] 3581 ); 3582 3583 if (!$user_id) 3584 { 3585 return new PwgError(WS_ERR_INVALID_PARAM, $errors[0]); 3586 } 3587 3588 return $service->invoke('pwg.users.getList', array('user_id'=>$user_id)); 3589 } 3590 3591 /** 3592 * API method 3593 * Deletes users 3594 * @param mixed[] $params 3595 * @option int[] user_id 3596 */ 3597 function ws_users_delete($params, &$service) 3598 { 3599 global $conf, $user; 3600 3601 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3602 3603 // protect some users 3604 $params['user_id'] = array_diff( 3605 $params['user_id'], 3606 array( 3607 $user['id'], 3608 $conf['guest_id'], 3609 $conf['default_user_id'], 3610 $conf['webmaster_id'], 3611 ) 3612 ); 3613 3614 foreach ($params['user_id'] as $user_id) 3615 { 3616 delete_user($user_id); 3617 } 3618 3619 return l10n_dec( 3620 '%d user deleted', '%d users deleted', 3621 count($params['user_id']) 3622 ); 3623 } 3624 3625 /** 3626 * API method 3627 * Updates users 3628 * @param mixed[] $params 3629 * @option int[] user_id 3630 * @option string username (optional) 3631 * @option string password (optional) 3632 * @option string email (optional) 3633 * @option string status (optional) 3634 * @option int level (optional) 3635 * @option string language (optional) 3636 * @option string theme (optional) 3637 * @option int nb_image_page (optional) 3638 * @option int recent_period (optional) 3639 * @option bool expand (optional) 3640 * @option bool show_nb_comments (optional) 3641 * @option bool show_nb_hits (optional) 3642 * @option bool enabled_high (optional) 3643 */ 3644 function ws_users_setInfo($params, &$service) 3645 { 3646 global $conf, $user; 3647 3648 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3649 3650 $updates = $updates_infos = array(); 3651 $update_status = null; 3652 3653 if (count($params['user_id']) == 1) 3654 { 3655 if (get_username($params['user_id'][0]) === false) 3656 { 3657 return new PwgError(WS_ERR_INVALID_PARAM, 'This user does not exist.'); 3658 } 3659 3660 if (!empty($params['username'])) 3661 { 3662 $user_id = get_userid($params['username']); 3663 if ($user_id and $user_id != $params['user_id'][0]) 3664 { 3665 return new PwgError(WS_ERR_INVALID_PARAM, l10n('this login is already used')); 3666 } 3667 if ($params['username'] != strip_tags($params['username'])) 3668 { 3669 return new PwgError(WS_ERR_INVALID_PARAM, l10n('html tags are not allowed in login')); 3670 } 3671 $updates[ $conf['user_fields']['username'] ] = $params['username']; 3672 } 3673 3674 if (!empty($params['email'])) 3675 { 3676 if ( ($error = validate_mail_address($params['user_id'][0], $params['email'])) != '') 3677 { 3678 return new PwgError(WS_ERR_INVALID_PARAM, $error); 3679 } 3680 $updates[ $conf['user_fields']['email'] ] = $params['email']; 3681 } 3682 3683 if (!empty($params['password'])) 3684 { 3685 $updates[ $conf['user_fields']['password'] ] = $conf['password_hash']($params['password']); 3686 } 3687 } 3688 3689 if (!empty($params['status'])) 3690 { 3691 if ( $params['status'] == 'webmaster' and !is_webmaster() ) 3692 { 3693 return new PwgError(403, 'Only webmasters can grant "webmaster" status'); 3694 } 3695 if ( !in_array($params['status'], array('guest','generic','normal','admin','webmaster')) ) 3696 { 3697 return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid status'); 3698 } 3699 3700 /* 3701 * status update query is separated from the rest as not applying to the same 3702 * set of users (current, guest and webmaster can't be changed) 3703 */ 3704 $params['user_id_for_status'] = array_diff( 3705 $params['user_id'], 3706 array( 3707 $user['id'], 3708 $conf['guest_id'], 3709 $conf['webmaster_id'], 3710 ) 3711 ); 3712 3713 $update_status = $params['status']; 3714 } 3715 3716 if (!empty($params['level']) or @$params['level']===0) 3717 { 3718 if ( !in_array($params['level'], $conf['available_permission_levels']) ) 3719 { 3720 return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level'); 3721 } 3722 $updates_infos['level'] = $params['level']; 3723 } 3724 3725 if (!empty($params['language'])) 3726 { 3727 if ( !in_array($params['language'], array_keys(get_languages())) ) 3728 { 3729 return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid language'); 3730 } 3731 $updates_infos['language'] = $params['language']; 3732 } 3733 3734 if (!empty($params['theme'])) 3735 { 3736 if ( !in_array($params['theme'], array_keys(get_pwg_themes())) ) 3737 { 3738 return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid theme'); 3739 } 3740 $updates_infos['theme'] = $params['theme']; 3741 } 3742 3743 if (!empty($params['nb_image_page'])) 3744 { 3745 $updates_infos['nb_image_page'] = $params['nb_image_page']; 3746 } 3747 3748 if (!empty($params['recent_period']) or @$params['recent_period']===0) 3749 { 3750 $updates_infos['recent_period'] = $params['recent_period']; 3751 } 3752 3753 if (!empty($params['expand']) or @$params['expand']===false) 3754 { 3755 $updates_infos['expand'] = boolean_to_string($params['expand']); 3756 } 3757 3758 if (!empty($params['show_nb_comments']) or @$params['show_nb_comments']===false) 3759 { 3760 $updates_infos['show_nb_comments'] = boolean_to_string($params['show_nb_comments']); 3761 } 3762 3763 if (!empty($params['show_nb_hits']) or @$params['show_nb_hits']===false) 3764 { 3765 $updates_infos['show_nb_hits'] = boolean_to_string($params['show_nb_hits']); 3766 } 3767 3768 if (!empty($params['enabled_high']) or @$params['enabled_high']===false) 3769 { 3770 $updates_infos['enabled_high'] = boolean_to_string($params['enabled_high']); 3771 } 3772 3773 // perform updates 3774 single_update( 3775 USERS_TABLE, 3776 $updates, 3777 array($conf['user_fields']['id'] => $params['user_id'][0]) 3778 ); 3779 3780 if (isset($update_status) and count($params['user_id_for_status']) > 0) 3781 { 3782 $query = ' 3783 UPDATE '. USER_INFOS_TABLE .' SET 3784 status = "'. $update_status .'" 3785 WHERE user_id IN('. implode(',', $params['user_id_for_status']) .') 3786 ;'; 3787 pwg_query($query); 3788 } 3789 3790 if (count($updates_infos) > 0) 3791 { 3792 $query = ' 3793 UPDATE '. USER_INFOS_TABLE .' SET '; 3794 3795 $first = true; 3796 foreach ($updates_infos as $field => $value) 3797 { 3798 if (!$first) $query.= ', '; 3799 else $first = false; 3800 $query.= $field .' = "'. $value .'"'; 3801 } 3802 3803 $query.= ' 3804 WHERE user_id IN('. implode(',', $params['user_id']) .') 3805 ;'; 3806 pwg_query($query); 3807 } 3808 3809 return $service->invoke('pwg.users.getList', array( 3810 'user_id' => $params['user_id'], 3811 'display' => 'basics,'.implode(',', array_keys($updates_infos)), 3812 )); 3813 } 3814 3815 /** 3816 * API method 3817 * Returns permissions 3818 * @param mixed[] $params 3819 * @option int[] cat_id (optional) 3820 * @option int[] group_id (optional) 3821 * @option int[] user_id (optional) 3822 */ 3823 function ws_permissions_getList($params, &$service) 3824 { 3825 $my_params = array_intersect(array_keys($params), array('cat_id','group_id','user_id')); 3826 if (count($my_params) > 1) 3827 { 3828 return new PwgError(WS_ERR_INVALID_PARAM, 'Too many parameters, provide cat_id OR user_id OR group_id'); 3829 } 3830 3831 $cat_filter = ''; 3832 if (!empty($params['cat_id'])) 3833 { 3834 $cat_filter = 'WHERE cat_id IN('. implode(',', $params['cat_id']) .')'; 3835 } 3836 3837 $perms = array(); 3838 3839 // direct users 3840 $query = ' 3841 SELECT user_id, cat_id 3842 FROM '. USER_ACCESS_TABLE .' 3843 '. $cat_filter .' 3844 ;'; 3845 $result = pwg_query($query); 3846 3847 while ($row = pwg_db_fetch_assoc($result)) 3848 { 3849 if (!isset($perms[ $row['cat_id'] ])) 3850 { 3851 $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 3852 } 3853 $perms[ $row['cat_id'] ]['users'][] = $row['user_id']; 3854 } 3855 3856 // indirect users 3857 $query = ' 3858 SELECT ug.user_id, ga.cat_id 3859 FROM '. USER_GROUP_TABLE .' AS ug 3860 INNER JOIN '. GROUP_ACCESS_TABLE .' AS ga 3861 ON ug.group_id = ga.group_id 3862 '. $cat_filter .' 3863 ;'; 3864 $result = pwg_query($query); 3865 3866 while ($row = pwg_db_fetch_assoc($result)) 3867 { 3868 if (!isset($perms[ $row['cat_id'] ])) 3869 { 3870 $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 3871 } 3872 $perms[ $row['cat_id'] ]['users_indirect'][] = $row['user_id']; 3873 } 3874 3875 // groups 3876 $query = ' 3877 SELECT group_id, cat_id 3878 FROM '. GROUP_ACCESS_TABLE .' 3879 '. $cat_filter .' 3880 ;'; 3881 $result = pwg_query($query); 3882 3883 while ($row = pwg_db_fetch_assoc($result)) 3884 { 3885 if (!isset($perms[ $row['cat_id'] ])) 3886 { 3887 $perms[ $row['cat_id'] ]['id'] = $row['cat_id']; 3888 } 3889 $perms[ $row['cat_id'] ]['groups'][] = $row['group_id']; 3890 } 3891 3892 // filter by group and user 3893 foreach ($perms as $cat_id => &$cat) 3894 { 3895 if (isset($filters['group_id'])) 3896 { 3897 if (empty($cat['groups']) or count(array_intersect($cat['groups'], $params['group_id'])) == 0) 3898 { 3899 unset($perms[$cat_id]); 3900 continue; 3901 } 3902 } 3903 if (isset($filters['user_id'])) 3904 { 3905 if ( 3906 (empty($cat['users_indirect']) or count(array_intersect($cat['users_indirect'], $params['user_id'])) == 0) 3907 and (empty($cat['users']) or count(array_intersect($cat['users'], $params['user_id'])) == 0) 3908 ) { 3909 unset($perms[$cat_id]); 3910 continue; 3911 } 3912 } 3913 3914 $cat['groups'] = !empty($cat['groups']) ? array_unique($cat['groups']) : array(); 3915 $cat['users'] = !empty($cat['users']) ? array_unique($cat['users']) : array(); 3916 $cat['users_indirect'] = !empty($cat['users_indirect']) ? array_unique($cat['users_indirect']) : array(); 3917 } 3918 unset($cat); 3919 3920 return array('categories' => new PwgNamedArray(array_values($perms), 'category', array('id'))); 3921 } 3922 3923 /** 3924 * API method 3925 * Add permissions 3926 * @param mixed[] $params 3927 * @option int[] cat_id 3928 * @option int[] group_id (optional) 3929 * @option int[] user_id (optional) 3930 * @option bool recursive 3931 */ 3932 function ws_permissions_add($params, &$service) 3933 { 3934 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3935 3936 if (!empty($params['group_id'])) 3937 { 3938 $cat_ids = get_uppercat_ids($params['cat_id']); 3939 if ($params['recursive']) 3940 { 3941 $cat_ids = array_merge($cat_ids, get_subcat_ids($params['cat_id'])); 3942 } 3943 3944 $query = ' 3945 SELECT id 3946 FROM '.CATEGORIES_TABLE.' 3947 WHERE id IN ('.implode(',', $cat_ids).') 3948 AND status = \'private\' 3949 ;'; 3950 $private_cats = array_from_query($query, 'id'); 3951 3952 $inserts = array(); 3953 foreach ($private_cats as $cat_id) 3954 { 3955 foreach ($params['group_id'] as $group_id) 3956 { 3957 $inserts[] = array( 3958 'group_id' => $group_id, 3959 'cat_id' => $cat_id 3960 ); 3961 } 3962 } 3963 3964 mass_inserts( 3965 GROUP_ACCESS_TABLE, 3966 array('group_id','cat_id'), 3967 $inserts, 3968 array('ignore'=>true) 3969 ); 3970 } 3971 3972 if (!empty($params['user_id'])) 3973 { 3974 if ($params['recursive']) $_POST['apply_on_sub'] = true; 3975 add_permission_on_category($params['cat_id'], $params['user_id']); 3976 } 3977 3978 return $service->invoke('pwg.permissions.getList', array('cat_id'=>$params['cat_id'])); 3979 } 3980 3981 /** 3982 * API method 3983 * Removes permissions 3984 * @param mixed[] $params 3985 * @option int[] cat_id 3986 * @option int[] group_id (optional) 3987 * @option int[] user_id (optional) 3988 */ 3989 function ws_permissions_remove($params, &$service) 3990 { 3991 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); 3992 3993 $cat_ids = get_subcat_ids($params['cat_id']); 3994 3995 if (!empty($params['group_id'])) 3996 { 3997 $query = ' 3998 DELETE 3999 FROM '. GROUP_ACCESS_TABLE .' 4000 WHERE group_id IN ('. implode(',', $params['group_id']).') 4001 AND cat_id IN ('. implode(',', $cat_ids).') 4002 ;'; 4003 pwg_query($query); 4004 } 4005 4006 if (!empty($params['user_id'])) 4007 { 4008 $query = ' 4009 DELETE 4010 FROM '. USER_ACCESS_TABLE .' 4011 WHERE user_id IN ('. implode(',', $params['user_id']) .') 4012 AND cat_id IN ('. implode(',', $cat_ids) .') 4013 ;'; 4014 pwg_query($query); 4015 } 4016 4017 return $service->invoke('pwg.permissions.getList', array('cat_id'=>$params['cat_id'])); 249 250 $categories[ $key_of_cat[ $node['id_uppercat'] ] ]['sub_categories']->_content[] = &$node; 251 } 252 } 253 254 return $tree; 4018 255 } 4019 256
Note: See TracChangeset
for help on using the changeset viewer.