root/trunk/include/ws_functions.inc.php @ 1852

Revision 1852, 30.4 KB (checked in by rvelices, 6 years ago)

Plugins:

  • display author and and author url (if present) on plugin admin page
  • uniformized versions/authors... for all plugins in svn
  • security fix (html escape name, version, uri, author... to avoid javascript injection which could automatically simulate click on Install)
  • added confirmation for install/uninstall plugins

Web services:

  • web service explorer now caches method details in order to avoid unnecessary web calls
  • web service explorer can now send parameters as arrays
  • web service explorer uses now prototype.js version 1.5
  • small improvements

- added and use function bad_request (sends http status code 400)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision URL
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | PhpWebGallery - a PHP based picture gallery                           |
4// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
5// +-----------------------------------------------------------------------+
6// | file          : $Id$
7// | last update   : $Date$
8// | last modifier : $Author$
9// | revision      : $Revision$
10// +-----------------------------------------------------------------------+
11// | This program is free software; you can redistribute it and/or modify  |
12// | it under the terms of the GNU General Public License as published by  |
13// | the Free Software Foundation                                          |
14// |                                                                       |
15// | This program is distributed in the hope that it will be useful, but   |
16// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
17// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
18// | General Public License for more details.                              |
19// |                                                                       |
20// | You should have received a copy of the GNU General Public License     |
21// | along with this program; if not, write to the Free Software           |
22// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
23// | USA.                                                                  |
24// +-----------------------------------------------------------------------+
25
26/**** IMPLEMENTATION OF WEB SERVICE METHODS ***********************************/
27
28/**
29 * Event handler for method invocation security check. Should return a PwgError
30 * if the preconditions are not satifsied for method invocation.
31 */
32function ws_isInvokeAllowed($res, $methodName, $params)
33{
34  global $conf, $calling_partner_id;
35 
36  if ( strpos($methodName,'reflection.')===0 )
37  { // OK for reflection
38    return $res;
39  }
40 
41  if ( !is_autorize_status(ACCESS_GUEST) and
42      strpos($methodName,'pwg.session.')!==0 )
43  {
44    return new PwgError(401, 'Access denied');
45  }
46 
47  if ( !$conf['ws_access_control'] )
48  {
49    return $res; // No controls are requested
50  }
51  $query = '
52SELECT * FROM '.WEB_SERVICES_ACCESS_TABLE."
53 WHERE `name` = '$calling_partner_id'
54   AND NOW() <= end; ";
55  $result = pwg_query($query);
56  $row = mysql_fetch_assoc($result);
57  if ( empty($row) )
58  {
59    return new PwgError(403, 'Partner id does not exist or is expired');
60  }
61  if ( !empty($row['request'])
62      and strpos($methodName, $row['request'])==false )
63  {
64    return new PwgError(403, 'Method not allowed');
65  }
66
67  return $res;
68}
69
70/**
71 * ws_addControls
72 * returns additionnal controls if requested
73 * usable for 99% of Web Service methods
74 *
75 * - Args
76 * $methodName: is the requested method
77 * $partner: is the key
78 * $tbl_name: is the alias_name in the query (sometimes called correlation name)
79 *            null if !getting picture informations
80 * - Logic
81 * Access_control is not active: Return
82 * Key is incorrect: Return 0 = 1 (False condition for MySQL)
83 * One of Params doesn't match with type of request: return 0 = 1 again
84 * Access list(id/cat/tag) is converted in expended image-id list
85 * image-id list: converted to an in-where-clause
86 *
87 * The additionnal in-where-clause is return
88 */
89function ws_addControls( $methodName, &$params, $tbl_name )
90{
91  global $conf, $calling_partner_id;
92  if ( !$conf['ws_access_control'] or !isset($calling_partner_id) )
93  {
94    return '1=1'; // No controls are requested
95  }
96
97// Is it an active Partner?
98  $query = '
99SELECT * FROM '.WEB_SERVICES_ACCESS_TABLE."
100 WHERE `name` = '$calling_partner_id'
101   AND NOW() <= end; ";
102$result = pwg_query($query);
103  if ( mysql_num_rows( $result ) == 0 )
104  {
105    return '0=1'; // Unknown partner or Obsolate agreement
106  }
107
108  $row = mysql_fetch_array($result);
109
110// Overide general object limit
111  $params['per_page'] = $row['limit'];
112
113// Target restrict
114// 3 cases: list, cat or tag
115// Behind / we could found img-ids, cat-ids or tag-ids
116  $target = $row['access'];
117  list($type, $str_ids) = explode('/',$target); // Find type list
118
119// (array) 1,2,21,3,22,4,5,9-12,6,11,12,13,2,4,6,
120  $arr_ids = expand_id_list( explode( ',',$str_ids ) );
121  $addings = implode(',', $arr_ids);
122// (string) 1,2,3,4,5,6,9,10,11,12,13,21,22,
123  if ( $type == 'list')
124  {
125    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
126  }
127
128  if ( $type == 'cat' )
129  {
130    $addings = implode(',', get_image_ids_for_cats($arr_ids));
131    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
132  }
133
134  if ( $type == 'tag' )
135  {
136    $addings = implode(',', get_image_ids_for_tags($arr_ids, 'OR'));
137    return $tbl_name . 'id IN ( ' . $addings . ' ) ';
138  }
139  // Unmanaged new type?
140  return ' 0 = 1 '; // ???
141}
142
143/**
144 * returns a "standard" (for our web service) array of sql where clauses that
145 * filters the images (images table only)
146 */
147function ws_std_image_sql_filter( $params, $tbl_name='' )
148{
149  $clauses = array();
150  if ( is_numeric($params['f_min_rate']) )
151  {
152    $clauses[] = $tbl_name.'average_rate>'.$params['f_min_rate'];
153  }
154  if ( is_numeric($params['f_max_rate']) )
155  {
156    $clauses[] = $tbl_name.'average_rate<='.$params['f_max_rate'];
157  }
158  if ( is_numeric($params['f_min_hit']) )
159  {
160    $clauses[] = $tbl_name.'hit>'.$params['f_min_hit'];
161  }
162  if ( is_numeric($params['f_max_hit']) )
163  {
164    $clauses[] = $tbl_name.'hit<='.$params['f_max_hit'];
165  }
166  if ( isset($params['f_min_date_posted']) )
167  {
168    $clauses[] = $tbl_name."date_available>='".$params['f_min_date_posted']."'";
169  }
170  if ( isset($params['f_max_date_posted']) )
171  {
172    $clauses[] = $tbl_name."date_available<'".$params['f_max_date_posted']."'";
173  }
174  if ( isset($params['f_min_date_created']) )
175  {
176    $clauses[] = $tbl_name."date_creation>='".$params['f_min_date_created']."'";
177  }
178  if ( isset($params['f_max_date_created']) )
179  {
180    $clauses[] = $tbl_name."date_creation<'".$params['f_max_date_created']."'";
181  }
182  if ( is_numeric($params['f_min_ratio']) )
183  {
184    $clauses[] = $tbl_name.'width/'.$tbl_name.'height>'.$params['f_min_ratio'];
185  }
186  if ( is_numeric($params['f_max_ratio']) )
187  {
188    $clauses[] = $tbl_name.'width/'.$tbl_name.'height<='.$params['f_max_ratio'];
189  }
190  if ( $params['f_with_thumbnail'] )
191  {
192    $clauses[] = $tbl_name.'tn_ext IS NOT NULL';
193  }
194  return $clauses;
195}
196
197/**
198 * returns a "standard" (for our web service) ORDER BY sql clause for images
199 */
200function ws_std_image_sql_order( $params, $tbl_name='' )
201{
202  $ret = '';
203  if ( empty($params['order']) )
204  {
205    return $ret;
206  }
207  $matches = array();
208  preg_match_all('/([a-z_]+) *(?:(asc|desc)(?:ending)?)? *(?:, *|$)/i',
209    $params['order'], $matches);
210  for ($i=0; $i<count($matches[1]); $i++)
211  {
212    switch ($matches[1][$i])
213    {
214      case 'date_created':
215        $matches[1][$i] = 'date_creation'; break;
216      case 'date_posted':
217        $matches[1][$i] = 'date_available'; break;
218      case 'rand': case 'random':
219        $matches[1][$i] = 'RAND()'; break;
220    }
221    $sortable_fields = array('id', 'file', 'name', 'hit', 'average_rate',
222      'date_creation', 'date_available', 'RAND()' );
223    if ( in_array($matches[1][$i], $sortable_fields) )
224    {
225      if (!empty($ret))
226        $ret .= ', ';
227      if ($matches[1][$i] != 'RAND()' )
228      {
229        $ret .= $tbl_name;
230      }
231      $ret .= $matches[1][$i];
232      $ret .= ' '.$matches[2][$i];
233    }
234  }
235  return $ret;
236}
237
238/**
239 * returns an array map of urls (thumb/element) for image_row - to be returned
240 * in a standard way by different web service methods
241 */
242function ws_std_get_urls($image_row)
243{
244  $ret = array(
245    'tn_url' => get_thumbnail_url($image_row),
246    'element_url' => get_element_url($image_row)
247  );
248  global $user;
249  if ($user['enabled_high'] and $image_row['has_high'] )
250  {
251    $ret['high_url'] = get_high_url($image_row);
252  }
253  return $ret;
254}
255
256/**
257 * returns an array of image attributes that are to be encoded as xml attributes
258 * instead of xml elements
259 */
260function ws_std_get_image_xml_attributes()
261{
262  return array(
263    'id','tn_url','element_url','high_url', 'file','width','height','hit'
264    );
265}
266
267/**
268 * returns PWG version (web service method)
269 */
270function ws_getVersion($params, &$service)
271{
272  global $conf;
273  if ($conf['show_version'])
274    return PHPWG_VERSION;
275  else
276    return new PwgError(403, 'Forbidden');
277}
278
279
280/**
281 * returns images per category (web service method)
282 */
283function ws_categories_getImages($params, &$service)
284{
285  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
286  global $user, $conf;
287
288  $images = array();
289
290  //------------------------------------------------- get the related categories
291  $where_clauses = array();
292  foreach($params['cat_id'] as $cat_id)
293  {
294    $cat_id = (int)$cat_id;
295    if ($cat_id<=0)
296      continue;
297    if ($params['recursive'])
298    {
299      $where_clauses[] = 'uppercats REGEXP \'(^|,)'.$cat_id.'(,|$)\'';
300    }
301    else
302    {
303      $where_clauses[] = 'id='.$cat_id;
304    }
305  }
306  if (!empty($where_clauses))
307  {
308    $where_clauses = array( '('.
309    implode('
310    OR ', $where_clauses) . ')'
311      );
312  }
313  $where_clauses[] = 'id NOT IN ('.$user['forbidden_categories'].')';
314
315  $query = '
316SELECT id, name, image_order
317  FROM '.CATEGORIES_TABLE.'
318  WHERE '. implode('
319    AND ', $where_clauses);
320  $result = pwg_query($query);
321  $cats = array();
322  while ($row = mysql_fetch_assoc($result))
323  {
324    $row['id'] = (int)$row['id'];
325    $cats[ $row['id'] ] = $row;
326  }
327
328  //-------------------------------------------------------- get the images
329  if ( !empty($cats) )
330  {
331    $where_clauses = ws_std_image_sql_filter( $params, 'i.' );
332    $where_clauses[] = 'category_id IN ('
333      .implode(',', array_keys($cats) )
334      .')';
335    $where_clauses[] = get_sql_condition_FandF( array(
336          'visible_images' => 'i.id'
337        ), null, true
338      );
339    $where_clauses[] = ws_addControls( 'categories.getImages', $params, 'i.' );
340
341    $order_by = ws_std_image_sql_order($params, 'i.');
342    if ( empty($order_by)
343          and count($params['cat_id'])==1
344          and isset($cats[ $params['cat_id'][0] ]['image_order'])
345        )
346    {
347      $order_by = $cats[ $params['cat_id'][0] ]['image_order'];
348    }
349    $order_by = empty($order_by) ? $conf['order_by'] : 'ORDER BY '.$order_by;
350
351    $query = '
352SELECT i.*, GROUP_CONCAT(category_id) cat_ids
353  FROM '.IMAGES_TABLE.' i
354    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id
355  WHERE '. implode('
356    AND ', $where_clauses).'
357GROUP BY i.id
358'.$order_by.'
359LIMIT '.$params['per_page']*$params['page'].','.$params['per_page'];
360
361    $result = pwg_query($query);
362    while ($row = mysql_fetch_assoc($result))
363    {
364      $image = array();
365      foreach ( array('id', 'width', 'height', 'hit') as $k )
366      {
367        if (isset($row[$k]))
368        {
369          $image[$k] = (int)$row[$k];
370        }
371      }
372      foreach ( array('name', 'file') as $k )
373      {
374        $image[$k] = $row[$k];
375      }
376      $image = array_merge( $image, ws_std_get_urls($row) );
377
378      $image_cats = array();
379      foreach ( explode(',', $row['cat_ids']) as $cat_id )
380      {
381        $url = make_index_url(
382                array(
383                  'category' => $cat_id,
384                  'cat_name' => $cats[$cat_id]['name'],
385                  )
386                );
387        $page_url = make_picture_url(
388                array(
389                  'category' => $cat_id,
390                  'cat_name' => $cats[$cat_id]['name'],
391                  'image_id' => $row['id'],
392                  'image_file' => $row['file'],
393                  )
394                );
395        array_push( $image_cats,  array(
396              WS_XML_ATTRIBUTES => array (
397                  'id' => (int)$cat_id,
398                  'url' => $url,
399                  'page_url' => $page_url,
400                )
401            )
402          );
403      }
404
405      $image['categories'] = new PwgNamedArray(
406            $image_cats,'category', array('id','url','page_url')
407          );
408      array_push($images, $image);
409    }
410  }
411
412  return array( 'images' =>
413    array (
414      WS_XML_ATTRIBUTES =>
415        array(
416            'page' => $params['page'],
417            'per_page' => $params['per_page'],
418            'count' => count($images)
419          ),
420       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
421          ws_std_get_image_xml_attributes() )
422      )
423    );
424}
425
426
427/**
428 * returns a list of categories (web service method)
429 */
430function ws_categories_getList($params, &$service)
431{
432  global $user,$conf;
433
434  $where = array();
435
436  if (!$params['recursive'])
437  {
438    if ($params['cat_id']>0)
439      $where[] = '(id_uppercat='.(int)($params['cat_id']).'
440    OR id='.(int)($params['cat_id']).')';
441    else
442      $where[] = 'id_uppercat IS NULL';
443  }
444  else if ($params['cat_id']>0)
445  {
446    $where[] = 'uppercats REGEXP \'(^|,)'.
447      (int)($params['cat_id'])
448      .'(,|$)\'';
449  }
450
451  if ($params['public'])
452  {
453    $where[] = 'status = "public"';
454    $where[] = 'visible = "true"';
455    $where[]= 'user_id='.$conf['guest_id'];
456  }
457  else
458  {
459    $where[] = 'id NOT IN ('.$user['forbidden_categories'].')';
460    $where[]= 'user_id='.$user['id'];
461  }
462
463  $query = '
464SELECT id, name, uppercats, global_rank,
465    nb_images, count_images AS total_nb_images,
466    date_last, max_date_last, count_categories AS nb_categories
467  FROM '.CATEGORIES_TABLE.'
468   INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id
469  WHERE '. implode('
470    AND ', $where);
471  $query .= '
472ORDER BY global_rank';
473
474  $result = pwg_query($query);
475
476  $cats = array();
477  while ($row = mysql_fetch_assoc($result))
478  {
479    $row['url'] = make_index_url(
480        array(
481          'category' => $row['id'],
482          'cat_name' => $row['name'],
483          )
484      );
485    foreach( array('id','nb_images','total_nb_images','nb_categories') as $key)
486    {
487      $row[$key] = (int)$row[$key];
488    }
489    array_push($cats, $row);
490  }
491  usort($cats, 'global_rank_compare');
492  return array(
493      'categories' =>
494          new PwgNamedArray($cats,'category',
495            array('id','url','nb_images','total_nb_images','nb_categories','date_last','max_date_last')
496          )
497    );
498}
499
500
501/**
502 * returns detailed information for an element (web service method)
503 */
504function ws_images_addComment($params, &$service)
505{
506  if (!$service->isPost())
507  {
508    return new PwgError(405, "This method requires HTTP POST");
509  }
510  $params['image_id'] = (int)$params['image_id'];
511  $query = '
512SELECT DISTINCT image_id
513  FROM '.IMAGE_CATEGORY_TABLE.' INNER JOIN '.CATEGORIES_TABLE.' ON category_id=id
514  WHERE commentable="true"
515    AND image_id='.$params['image_id'].
516    get_sql_condition_FandF(
517      array(
518        'forbidden_categories' => 'id',
519        'visible_categories' => 'id',
520        'visible_images' => 'image_id'
521      ),
522      ' AND'
523    );
524  if ( !mysql_num_rows( pwg_query( $query ) ) )
525  {
526    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
527  }
528 
529  include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
530 
531  $comm = array(
532    'author' => trim( stripslashes($params['author']) ),
533    'content' => trim( stripslashes($params['content']) ),
534    'image_id' => $params['image_id'],
535   );
536
537  include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
538 
539  $comment_action = insert_user_comment( 
540      $comm, $params['key'], $infos
541    );
542
543  switch ($comment_action)
544  {
545    case 'reject':
546      array_push($infos, l10n('comment_not_added') );
547      return new PwgError(403, implode("\n", $infos) );
548    case 'validate':
549    case 'moderate':
550      $ret = array( 
551          'id' => $comm['id'],
552          'validation' => $comment_action=='validate',
553        );
554      return new PwgNamedStruct(
555          'comment',
556          $ret, 
557          null, array() 
558        );
559    default:
560      return new PwgError(500, "Unknown comment action ".$comment_action );
561  }
562}
563
564/**
565 * returns detailed information for an element (web service method)
566 */
567function ws_images_getInfo($params, &$service)
568{
569  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
570  global $user, $conf;
571  $params['image_id'] = (int)$params['image_id'];
572  if ( $params['image_id']<=0 )
573  {
574    return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id");
575  }
576
577  $query='
578SELECT * FROM '.IMAGES_TABLE.'
579  WHERE id='.$params['image_id'].
580    get_sql_condition_FandF(
581      array('visible_images' => 'id'),
582      ' AND'
583    ).' AND '.
584    ws_addControls( 'images.getInfo', $params, '' ).'
585LIMIT 1;';
586
587  $image_row = mysql_fetch_assoc(pwg_query($query));
588  if ($image_row==null)
589  {
590    return new PwgError(404, "image_id not found");
591  }
592  $image_row = array_merge( $image_row, ws_std_get_urls($image_row) );
593
594  //-------------------------------------------------------- related categories
595  $query = '
596SELECT id,name,uppercats,global_rank,commentable
597  FROM '.IMAGE_CATEGORY_TABLE.'
598    INNER JOIN '.CATEGORIES_TABLE.' ON category_id = id
599  WHERE image_id = '.$image_row['id'].'
600    AND category_id NOT IN ('.$user['forbidden_categories'].')
601;';
602  $result = pwg_query($query);
603  $is_commentable = false;
604  $related_categories = array();
605  while ($row = mysql_fetch_assoc($result))
606  {
607    if ($row['commentable']=='true')
608    {
609      $is_commentable = true;
610    }
611    unset($row['commentable']);
612    $row['url'] = make_index_url(
613        array(
614          'category' => $row['id'],
615          'cat_name' => $row['name'],
616          )
617      );
618
619    $row['page_url'] = make_picture_url(
620        array(
621          'image_id' => $image_row['id'],
622          'image_file' => $image_row['file'],
623          'category' => $row['id'],
624          'cat_name' => $row['name'],
625          )
626      );
627    $row['id']=(int)$row['id'];
628    array_push($related_categories, $row);
629  }
630  usort($related_categories, 'global_rank_compare');
631  if ( empty($related_categories) )
632  {
633    return new PwgError(401, 'Access denied');
634  }
635
636  //-------------------------------------------------------------- related tags
637  $related_tags = get_common_tags( array($image_row['id']), -1 );
638  foreach( $related_tags as $i=>$tag)
639  {
640    $tag['url'] = make_index_url(
641        array(
642          'tags' => array($tag)
643          )
644      );
645    $tag['page_url'] = make_picture_url(
646        array(
647          'image_id' => $image_row['id'],
648          'image_file' => $image_row['file'],
649          'tags' => array($tag),
650          )
651      );
652    unset($tag['counter']);
653    $tag['id']=(int)$tag['id'];
654    $related_tags[$i]=$tag;
655  }
656  //------------------------------------------------------------- related rates
657  $query = '
658SELECT COUNT(rate) AS count
659     , ROUND(AVG(rate),2) AS average
660     , ROUND(STD(rate),2) AS stdev
661  FROM '.RATE_TABLE.'
662  WHERE element_id = '.$image_row['id'].'
663;';
664  $rating = mysql_fetch_assoc(pwg_query($query));
665  $rating['count'] = (int)$rating['count'];
666
667  //---------------------------------------------------------- related comments
668  $related_comments = array();
669 
670  $where_comments = 'image_id = '.$image_row['id'];
671  if ( !is_admin() )
672  {
673    $where_comments .= '
674    AND validated="true"';
675  }
676
677  $query = '
678SELECT COUNT(id) nb_comments
679  FROM '.COMMENTS_TABLE.'
680  WHERE '.$where_comments;
681  list($nb_comments) = array_from_query($query, 'nb_comments');
682  $nb_comments = (int)$nb_comments;
683
684  if ( $nb_comments>0 and $params['comments_per_page']>0 )
685  {
686    $query = '
687SELECT id, date, author, content
688  FROM '.COMMENTS_TABLE.'
689  WHERE '.$where_comments.'
690  ORDER BY date
691  LIMIT '.$params['comments_per_page']*(int)$params['comments_page'].
692    ','.$params['comments_per_page'];
693
694    $result = pwg_query($query);
695    while ($row = mysql_fetch_assoc($result))
696    {
697      $row['id']=(int)$row['id'];
698      array_push($related_comments, $row);
699    }
700  }
701 
702  $comment_post_data = null;
703  if ($is_commentable and 
704      (!$user['is_the_guest']
705        or ($user['is_the_guest'] and $conf['comments_forall'] )
706      )
707      )
708  {
709    include_once(PHPWG_ROOT_PATH.'include/functions_comment.inc.php');
710    $comment_post_data['author'] = $user['username'];   
711    $comment_post_data['key'] = get_comment_post_key($params['image_id']);
712  }
713
714  $ret = $image_row;
715  foreach ( array('id','width','height','hit','filesize') as $k )
716  {
717    if (isset($ret[$k]))
718    {
719      $ret[$k] = (int)$ret[$k];
720    }
721  }
722  foreach ( array('path', 'storage_category_id') as $k )
723  {
724    unset($ret[$k]);
725  }
726
727  $ret['rates'] = array( WS_XML_ATTRIBUTES => $rating );
728  $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') );
729  $ret['tags'] = new PwgNamedArray($related_tags, 'tag', array('id','url_name','url','page_url') );
730  if ( isset($comment_post_data) )
731  {
732    $ret['comment_post'] = array( WS_XML_ATTRIBUTES => $comment_post_data );
733  }
734  $ret['comments'] = array(
735     WS_XML_ATTRIBUTES => 
736        array(
737          'page' => $params['comments_page'],
738          'per_page' => $params['comments_per_page'],
739          'count' => count($related_comments),
740          'nb_comments' => $nb_comments,
741        ),
742     WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id','date') )
743      );
744
745  return new PwgNamedStruct('image',$ret, null, array('name','comment') );
746}
747
748/**
749 * returns a list of elements corresponding to a query search
750 */
751function ws_images_search($params, &$service)
752{
753  global $page;
754  $images = array();
755  include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' );
756  include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
757
758  $where_clauses = ws_std_image_sql_filter( $params );
759  $order_by = ws_std_image_sql_order($params);
760
761  if ( !empty($where_clauses) and !empty($order_by) )
762  {
763    $page['super_order_by']=1; // quick_search_result might be faster
764  }
765  $search_result = get_quick_search_results($params['query']);
766
767  global $image_ids; //needed for sorting by rank (usort)
768  if ( ( !isset($search_result['as_is'])
769      or !empty($where_clauses)
770      or !empty($order_by) )
771      and !empty($search_result['items']) )
772  {
773    $where_clauses[] = 'id IN ('
774        .wordwrap(implode(', ', $search_result['items']), 80, "\n")
775        .')';
776    $where_clauses[] = get_sql_condition_FandF(
777        array
778          (
779            'forbidden_categories' => 'category_id',
780            'visible_categories' => 'category_id',
781            'visible_images' => 'id'
782          ),
783        '', true
784      );
785    $query = '
786SELECT DISTINCT id FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=image_id
787  WHERE '.implode('
788    AND ', $where_clauses);
789    if (!empty($order_by))
790    {
791      $query .= '
792  ORDER BY '.$order_by;
793    }
794    $image_ids = array_from_query($query, 'id');
795    global $ranks;
796    $ranks = array_flip( $search_result['items'] );
797    usort(
798      $image_ids,
799      create_function('$i1,$i2', 'global $ranks; return $ranks[$i1]-$ranks[$i2];')
800    );
801    unset ($ranks);
802  }
803  else
804  {
805    $image_ids = $search_result['items'];
806  }
807 
808  $image_ids = array_slice($image_ids,
809    $params['page']*$params['per_page'],
810    $params['per_page'] );
811
812  if ( count($image_ids) )
813  {
814    $query = '
815SELECT * FROM '.IMAGES_TABLE.'
816  WHERE id IN ('
817        .wordwrap(implode(', ', $image_ids), 80, "\n")
818        .')';
819
820    $result = pwg_query($query);
821    while ($row = mysql_fetch_assoc($result))
822    {
823      $image = array();
824      foreach ( array('id', 'width', 'height', 'hit') as $k )
825      {
826        if (isset($row[$k]))
827        {
828          $image[$k] = (int)$row[$k];
829        }
830      }
831      foreach ( array('name', 'file') as $k )
832      {
833        $image[$k] = $row[$k];
834      }
835      $image = array_merge( $image, ws_std_get_urls($row) );
836      array_push($images, $image);
837    }
838
839    $image_ids = array_flip($image_ids);
840    usort(
841        $images,
842        create_function('$i1,$i2', 'global $image_ids; return $image_ids[$i1["id"]]-$image_ids[$i2["id"]];')
843      );
844  }
845
846
847  return array( 'images' =>
848    array (
849      WS_XML_ATTRIBUTES =>
850        array(
851            'page' => $params['page'],
852            'per_page' => $params['per_page'],
853            'count' => count($images)
854          ),
855       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
856          ws_std_get_image_xml_attributes() )
857      )
858    );
859}
860
861/**
862 * perform a login (web service method)
863 */
864function ws_session_login($params, &$service)
865{
866  global $conf;
867
868  if (!$service->isPost())
869  {
870    return new PwgError(405, "This method requires HTTP POST");
871  }
872  if (try_log_user($params['username'], $params['password'],false))
873  {
874    return true;
875  }
876  return new PwgError(999, 'Invalid username/password');
877}
878
879
880/**
881 * performs a logout (web service method)
882 */
883function ws_session_logout($params, &$service)
884{
885  global $user, $conf;
886  if (!$user['is_the_guest'])
887  {
888    $_SESSION = array();
889    session_unset();
890    session_destroy();
891    setcookie(session_name(),'',0,
892        ini_get('session.cookie_path'),
893        ini_get('session.cookie_domain')
894      );
895    setcookie($conf['remember_me_name'], '', 0, cookie_path());
896  }
897  return true;
898}
899
900function ws_session_getStatus($params, &$service)
901{
902  global $user, $lang_info;
903  $res = array();
904  $res['username'] = $user['is_the_guest'] ? 'guest' : $user['username'];
905  foreach ( array('status', 'template', 'theme', 'language') as $k )
906  {
907    $res[$k] = $user[$k];
908  }
909  foreach ( array('charset') as $k )
910  {
911    $res[$k] = $lang_info[$k];
912  }
913  return $res;
914}
915
916
917/**
918 * returns a list of tags (web service method)
919 */
920function ws_tags_getList($params, &$service)
921{
922  $tags = get_available_tags();
923  if ($params['sort_by_counter'])
924  {
925    usort($tags, create_function('$a,$b', 'return -$a["counter"]+$b["counter"];') );
926  }
927  else
928  {
929    usort($tags, 'name_compare');
930  }
931  for ($i=0; $i<count($tags); $i++)
932  {
933    $tags[$i]['id'] = (int)$tags[$i]['id'];
934    $tags[$i]['counter'] = (int)$tags[$i]['counter'];
935    $tags[$i]['url'] = make_index_url(
936        array(
937          'section'=>'tags',
938          'tags'=>array($tags[$i])
939        )
940      );
941  }
942  return array('tags' => new PwgNamedArray($tags, 'tag', array('id','url_name','url', 'counter' )) );
943}
944
945
946/**
947 * returns a list of images for tags (web service method)
948 */
949function ws_tags_getImages($params, &$service)
950{
951  @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
952  global $conf;
953 
954  // first build all the tag_ids we are interested in
955  $params['tag_id'] = array_map( 'intval',$params['tag_id'] );
956  $tags = find_tags($params['tag_id'], $params['tag_url_name'], $params['tag_name']);
957  $tags_by_id = array();
958  foreach( $tags as $tag )
959  {
960    $tags['id'] = (int)$tag['id'];
961    $tags_by_id[ $tag['id'] ] = $tag;
962  }
963  unset($tags);
964  $tag_ids = array_keys($tags_by_id);
965
966
967  $image_ids = array();
968  $image_tag_map = array();
969
970  if ( !empty($tag_ids) )
971  { // build list of image ids with associated tags per image
972    if ($params['tag_mode_and'])
973    {
974      $image_ids = get_image_ids_for_tags( $tag_ids );
975    }
976    else
977    {
978      $query = '
979SELECT image_id, GROUP_CONCAT(tag_id) tag_ids
980  FROM '.IMAGE_TAG_TABLE.'
981  WHERE tag_id IN ('.implode(',',$tag_ids).')
982  GROUP BY image_id';
983      $result = pwg_query($query);
984      while ( $row=mysql_fetch_assoc($result) )
985      {
986        $row['image_id'] = (int)$row['image_id'];
987        array_push( $image_ids, $row['image_id'] );
988        $image_tag_map[ $row['image_id'] ] = explode(',', $row['tag_ids']);
989      }
990    }
991  }
992
993  $images = array();
994  if ( !empty($image_ids))
995  {
996    $where_clauses = ws_std_image_sql_filter($params);
997    $where_clauses[] = get_sql_condition_FandF(
998        array
999          (
1000            'forbidden_categories' => 'category_id',
1001            'visible_categories' => 'category_id',
1002            'visible_images' => 'i.id'
1003          ),
1004        '', true
1005      );
1006    $where_clauses[] = 'id IN ('.implode(',',$image_ids).')';
1007    $where_clauses[] = ws_addControls( 'tags.getImages', $params, 'i.' );
1008
1009    $order_by = ws_std_image_sql_order($params);
1010    if (empty($order_by))
1011    {
1012      $order_by = $conf['order_by'];
1013    }
1014    else
1015    {
1016      $order_by = 'ORDER BY '.$order_by;
1017    }
1018
1019    $query = '
1020SELECT DISTINCT i.* FROM '.IMAGES_TABLE.' i
1021  INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id
1022  WHERE '. implode('
1023    AND ', $where_clauses).'
1024'.$order_by.'
1025LIMIT '.$params['per_page']*$params['page'].','.$params['per_page'];
1026
1027    $result = pwg_query($query);
1028    while ($row = mysql_fetch_assoc($result))
1029    {
1030      foreach ( array('id', 'width', 'height', 'hit') as $k )
1031      {
1032        if (isset($row[$k]))
1033        {
1034          $image[$k] = (int)$row[$k];
1035        }
1036      }
1037      foreach ( array('name', 'file') as $k )
1038      {
1039        $image[$k] = $row[$k];
1040      }
1041      $image = array_merge( $image, ws_std_get_urls($row) );
1042
1043      $image_tag_ids = ($params['tag_mode_and']) ? $tag_ids : $image_tag_map[$image['id']];
1044      $image_tags = array();
1045      foreach ($image_tag_ids as $tag_id)
1046      {
1047        $url = make_index_url(
1048                 array(
1049                  'section'=>'tags',
1050                  'tags'=> array($tags_by_id[$tag_id])
1051                )
1052              );
1053        $page_url = make_picture_url(
1054                 array(
1055                  'section'=>'tags',
1056                  'tags'=> array($tags_by_id[$tag_id]),
1057                  'image_id' => $row['id'],
1058                  'image_file' => $row['file'],
1059                )
1060              );
1061        array_push($image_tags, array(
1062                'id' => (int)$tag_id,
1063                'url' => $url,
1064                'page_url' => $page_url,
1065              )
1066            );
1067      }
1068      $image['tags'] = new PwgNamedArray($image_tags, 'tag',
1069              array('id','url_name','url','page_url')
1070            );
1071      array_push($images, $image);
1072    }
1073  }
1074
1075  return array( 'images' =>
1076    array (
1077      WS_XML_ATTRIBUTES =>
1078        array(
1079            'page' => $params['page'],
1080            'per_page' => $params['per_page'],
1081            'count' => count($images)
1082          ),
1083       WS_XML_CONTENT => new PwgNamedArray($images, 'image',
1084          ws_std_get_image_xml_attributes() )
1085      )
1086    );
1087}
1088
1089
1090/**
1091 * expand_id_list($ids) convert a human list expression to a full ordered list
1092 * example : expand_id_list( array(5,2-3,2) ) returns array( 2, 3, 5)
1093 * */
1094function expand_id_list($ids)
1095{
1096  $tid = array();
1097  foreach ( $ids as $id )
1098  {
1099    if ( is_numeric($id) )
1100    {
1101      $tid[] = (int) $id;
1102    }
1103    else
1104    {
1105      $range = explode( '-', $id );
1106      if ( is_numeric($range[0]) and is_numeric($range[1]) )
1107      {
1108        $from = min($range[0],$range[1]);
1109        $to = max($range[0],$range[1]);
1110        for ($i = $from; $i <= $to; $i++)
1111        {
1112          $tid[] = (int) $i;
1113        }
1114      }
1115    }
1116  }
1117  $result = array_unique ($tid); // remove duplicates...
1118  sort ($result);
1119  return $result;
1120}
1121
1122
1123/**
1124 * converts a cat-ids array in image-ids array
1125 * FIXME Function which should already exist somewhere else
1126 * */
1127function get_image_ids_for_cats($cat_ids)
1128{
1129  $cat_list = implode(',', $cat_ids);
1130  $ret_ids = array();
1131  $query = '
1132  SELECT DISTINCT image_id
1133    FROM '.IMAGE_CATEGORY_TABLE.'
1134  WHERE category_id in ('.$cat_list.')
1135  ;';
1136  return array_from_query($query, 'image_id');
1137}
1138
1139?>
Note: See TracBrowser for help on using the browser.