source: extensions/community/main.inc.php @ 26557

Last change on this file since 26557 was 26557, checked in by plg, 10 years ago

bug 2512 fixed: safely remove photos in community pending list when photo is
deleted (outside Community).

File size: 18.8 KB
Line 
1<?php
2/*
3Plugin Name: Community
4Version: auto
5Description: Non admin users can add photos
6Plugin URI: http://piwigo.org/ext/extension_view.php?eid=303
7Author: plg
8Author URI: http://piwigo.wordpress.com
9*/
10
11if (!defined('PHPWG_ROOT_PATH'))
12{
13  die('Hacking attempt!');
14}
15
16global $prefixeTable;
17
18// +-----------------------------------------------------------------------+
19// | Define plugin constants                                               |
20// +-----------------------------------------------------------------------+
21
22defined('COMMUNITY_ID') or define('COMMUNITY_ID', basename(dirname(__FILE__)));
23define('COMMUNITY_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
24define('COMMUNITY_PERMISSIONS_TABLE', $prefixeTable.'community_permissions');
25define('COMMUNITY_PENDINGS_TABLE', $prefixeTable.'community_pendings');
26define('COMMUNITY_VERSION', 'auto');
27
28include_once(COMMUNITY_PATH.'include/functions_community.inc.php');
29
30// init the plugin
31add_event_handler('init', 'community_init');
32/**
33 * plugin initialization
34 *   - check for upgrades
35 *   - unserialize configuration
36 *   - load language
37 */
38function community_init()
39{
40  global $conf, $user, $pwg_loaded_plugins;
41
42  // apply upgrade if needed
43  if (
44    COMMUNITY_VERSION == 'auto' or
45    $pwg_loaded_plugins[COMMUNITY_ID]['version'] == 'auto' or
46    version_compare($pwg_loaded_plugins[COMMUNITY_ID]['version'], COMMUNITY_VERSION, '<')
47  )
48  {
49    // call install function
50    include_once(COMMUNITY_PATH.'include/install.inc.php');
51    community_install();
52
53    // update plugin version in database
54    if ( $pwg_loaded_plugins[COMMUNITY_ID]['version'] != 'auto' and COMMUNITY_VERSION != 'auto' )
55    {
56      $query = '
57UPDATE '. PLUGINS_TABLE .'
58SET version = "'. COMMUNITY_VERSION .'"
59WHERE id = "'. COMMUNITY_ID .'"';
60      pwg_query($query);
61
62      $pwg_loaded_plugins[COMMUNITY_ID]['version'] = COMMUNITY_VERSION;
63    }
64  }
65
66  // prepare plugin configuration
67  $conf['community'] = unserialize($conf['community']);
68
69  // TODO: generate permissions in $user['community_permissions'] if ws.php
70  // + remove all calls of community_get_user_permissions related to webservices
71  if (!defined('IN_ADMIN') or !IN_ADMIN)
72  {
73    $user['community_permissions'] = community_get_user_permissions($user['id']);
74  }
75}
76
77/* Plugin admin */
78add_event_handler('get_admin_plugin_menu_links', 'community_admin_menu');
79function community_admin_menu($menu)
80{
81  global $page;
82 
83  $query = '
84SELECT
85    COUNT(*)
86  FROM '.COMMUNITY_PENDINGS_TABLE.'
87    JOIN '.IMAGES_TABLE.' ON image_id = id
88  WHERE state = \'moderation_pending\'
89;';
90  $result = pwg_query($query);
91  list($page['community_nb_pendings']) = pwg_db_fetch_row($result);
92
93  $name = 'Community';
94  if ($page['community_nb_pendings'] > 0)
95  {
96    $style = 'background-color:#666;';
97    $style.= 'color:white;';
98    $style.= 'padding:1px 5px;';
99    $style.= 'border-radius:10px;';
100    $style.= 'margin-left:5px;';
101   
102    $name.= '<span style="'.$style.'">'.$page['community_nb_pendings'].'</span>';
103
104    if (defined('IN_ADMIN') and IN_ADMIN and $page['page'] == 'intro')
105    {
106      global $template;
107     
108      $template->set_prefilter('intro', 'community_pendings_on_intro');
109      $template->assign(
110        array(
111          'COMMUNITY_PENDINGS' => sprintf(
112            '<a href="%s">'.l10n('%u pending photos').'</a>',
113            get_root_url().'admin.php?page=plugin-community-pendings',
114            $page['community_nb_pendings']
115            ),
116          )
117        );
118    }
119  }
120
121  array_push(
122    $menu,
123    array(
124      'NAME' => $name,
125      'URL'  => get_root_url().'admin.php?page=plugin-community'
126      )
127    );
128
129  return $menu;
130}
131
132function community_pendings_on_intro($content, &$smarty)
133{
134  $pattern = '#<li>\s*{\$DB_ELEMENTS\}#ms';
135  $replacement = '<li>{$COMMUNITY_PENDINGS}</li><li>{$DB_ELEMENTS}';
136  return preg_replace($pattern, $replacement, $content);
137}
138
139add_event_handler('init', 'community_load_language');
140function community_load_language()
141{
142  if (!defined('IN_ADMIN') or !IN_ADMIN)
143  {
144    load_language('admin.lang');
145  }
146 
147  load_language('plugin.lang', COMMUNITY_PATH);
148}
149
150
151add_event_handler('loc_end_section_init', 'community_section_init');
152function community_section_init()
153{
154  global $tokens, $page;
155 
156  if ($tokens[0] == 'add_photos')
157  {
158    $page['section'] = 'add_photos';
159  }
160}
161
162add_event_handler('loc_end_index', 'community_index');
163function community_index()
164{
165  global $page;
166 
167  if (isset($page['section']) and $page['section'] == 'add_photos')
168  {
169    include(COMMUNITY_PATH.'add_photos.php');
170  }
171}
172
173add_event_handler('blockmanager_apply' , 'community_gallery_menu', EVENT_HANDLER_PRIORITY_NEUTRAL+10);
174function community_gallery_menu($menu_ref_arr)
175{
176  global $conf, $user;
177
178  // conditional : depending on community permissions, display the "Add
179  // photos" link in the gallery menu
180  $user_permissions = $user['community_permissions'];
181
182  if (!$user_permissions['community_enabled'])
183  {
184    return;
185  }
186
187  $menu = & $menu_ref_arr[0];
188
189  if (($block = $menu->get_block('mbMenu')) != null )
190  {
191    load_language('plugin.lang', COMMUNITY_PATH);
192
193    array_splice(
194      $block->data,
195      count($block->data),
196      0,
197      array(
198        '' => array(
199          'URL' => make_index_url(array('section' => 'add_photos')),
200          'TITLE' => l10n('Upload your own photos'),
201          'NAME' => l10n('Upload Photos')
202          )
203        )
204      );
205  }
206}
207
208
209add_event_handler('ws_invoke_allowed', 'community_switch_user_to_admin', EVENT_HANDLER_PRIORITY_NEUTRAL, 3);
210function community_switch_user_to_admin($res, $methodName, $params)
211{
212  global $user, $community;
213
214  if (is_admin())
215  {
216    return $res;
217  }
218 
219  $community = array('method' => $methodName);
220
221  if ('pwg.images.addSimple' == $community['method'])
222  {
223    $community['category'] = $params['category'];
224  }
225  elseif ('pwg.images.add' == $community['method'])
226  {
227    $community['category'] = $params['categories'];
228    $community['md5sum'] = $params['original_sum'];
229  }
230
231  // $print_params = $params;
232  // unset($print_params['data']);
233  // file_put_contents('/tmp/community.log', '['.$methodName.'] '.json_encode($print_params)."\n" ,FILE_APPEND);
234
235  // conditional : depending on community permissions, display the "Add
236  // photos" link in the gallery menu
237  $user_permissions = community_get_user_permissions($user['id']);
238
239  if (count($user_permissions['upload_categories']) == 0 and !$user_permissions ['create_whole_gallery'])
240  {
241    return $res;
242  }
243
244  // if level of trust is low, then we have to set level to 16
245
246  $methods = array();
247  $methods[] = 'pwg.tags.add';
248  $methods[] = 'pwg.images.exist';
249  $methods[] = 'pwg.images.add';
250  $methods[] = 'pwg.images.addSimple';
251  $methods[] = 'pwg.images.addChunk';
252  $methods[] = 'pwg.images.checkUpload';
253  $methods[] = 'pwg.images.checkFiles';
254  $methods[] = 'pwg.images.setInfo';
255
256  if (in_array($methodName, $methods))
257  {
258    $user['status'] = 'admin';
259  }
260
261  if ('pwg.categories.add' == $methodName)
262  {
263    if (in_array($params['parent'], $user_permissions['create_categories'])
264        or $user_permissions['create_whole_gallery'])
265    {
266      $user['status'] = 'admin';
267    }
268  }
269
270  return $res;
271}
272
273add_event_handler('ws_add_methods', 'community_ws_replace_methods', EVENT_HANDLER_PRIORITY_NEUTRAL+5);
274function community_ws_replace_methods($arr)
275{
276  global $conf, $user;
277 
278  $service = &$arr[0];
279
280  if (is_admin())
281  {
282    return;
283  }
284
285  $user_permissions = community_get_user_permissions($user['id']);
286 
287  if (count($user_permissions['permission_ids']) == 0)
288  {
289    return;
290  }
291 
292  // the plugin Community is activated, the user has upload permissions, we
293  // use a specific function to list available categories, assuming the user
294  // wants to list categories where upload is possible for him
295 
296  $service->addMethod(
297    'pwg.categories.getList',
298    'community_ws_categories_getList',
299    array(
300      'cat_id' =>       array('default'=>0),
301      'recursive' =>    array('default'=>false),
302      'public' =>       array('default'=>false),
303      'tree_output' =>  array('default'=>false),
304      'fullname' =>     array('default'=>false),
305      ),
306    'retrieves a list of categories'
307    );
308 
309  $service->addMethod(
310    'pwg.tags.getAdminList',
311    'community_ws_tags_getAdminList',
312    array(),
313    'administration method only'
314    );
315}
316
317/**
318 * returns a list of categories (web service method)
319 */
320function community_ws_categories_getList($params, &$service)
321{
322  global $user, $conf;
323
324  if ($params['tree_output'])
325  {
326    if (!isset($_GET['format']) or !in_array($_GET['format'], array('php', 'json')))
327    {
328      // the algorithm used to build a tree from a flat list of categories
329      // keeps original array keys, which is not compatible with
330      // PwgNamedArray.
331      //
332      // PwgNamedArray is useful to define which data is an attribute and
333      // which is an element in the XML output. The "hierarchy" output is
334      // only compatible with json/php output.
335
336      return new PwgError(405, "The tree_output option is only compatible with json/php output formats");
337    }
338  }
339 
340  $where = array('1=1');
341  $join_type = 'LEFT';
342  $join_user = $user['id'];
343
344  if (!$params['recursive'])
345  {
346    if ($params['cat_id']>0)
347      $where[] = '(id_uppercat='.(int)($params['cat_id']).'
348    OR id='.(int)($params['cat_id']).')';
349    else
350      $where[] = 'id_uppercat IS NULL';
351  }
352  else if ($params['cat_id']>0)
353  {
354    $where[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.
355      (int)($params['cat_id'])
356      .'(,|$)\'';
357  }
358
359  if ($params['public'])
360  {
361    $where[] = 'status = "public"';
362    $where[] = 'visible = "true"';
363   
364    $join_user = $conf['guest_id'];
365  }
366
367  $user_permissions = community_get_user_permissions($user['id']);
368  $upload_categories = $user_permissions['upload_categories'];
369  if (count($upload_categories) == 0)
370  {
371    $upload_categories = array(-1);
372  }
373
374  $where[] = 'id IN ('.implode(',', $upload_categories).')';
375
376  $query = '
377SELECT
378    id,
379    name,
380    permalink,
381    uppercats,
382    global_rank,
383    comment,
384    nb_images,
385    count_images AS total_nb_images,
386    date_last,
387    max_date_last,
388    count_categories AS nb_categories
389  FROM '.CATEGORIES_TABLE.'
390   '.$join_type.' JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id AND user_id='.$join_user.'
391  WHERE '. implode('
392    AND ', $where);
393
394  $result = pwg_query($query);
395
396  $cats = array();
397  while ($row = pwg_db_fetch_assoc($result))
398  {
399    $row['url'] = make_index_url(
400        array(
401          'category' => $row
402          )
403      );
404    foreach( array('id','nb_images','total_nb_images','nb_categories') as $key)
405    {
406      $row[$key] = (int)$row[$key];
407    }
408
409    if ($params['fullname'])
410    {
411      $row['name'] = strip_tags(get_cat_display_name_cache($row['uppercats'], null, false));
412    }
413    else
414    {
415      $row['name'] = strip_tags(
416        trigger_event(
417          'render_category_name',
418          $row['name'],
419          'ws_categories_getList'
420          )
421        );
422    }
423   
424    $row['comment'] = strip_tags(
425      trigger_event(
426        'render_category_description',
427        $row['comment'],
428        'ws_categories_getList'
429        )
430      );
431   
432    array_push($cats, $row);
433  }
434  usort($cats, 'global_rank_compare');
435
436  if ($params['tree_output'])
437  {
438    return categories_flatlist_to_tree($cats);
439  }
440  else
441  {
442    return array(
443      'categories' => new PwgNamedArray(
444        $cats,
445        'category',
446        array(
447          'id',
448          'url',
449          'nb_images',
450          'total_nb_images',
451          'nb_categories',
452          'date_last',
453          'max_date_last',
454          )
455        )
456      );
457  }
458}
459
460function community_ws_tags_getAdminList($params, &$service)
461{
462  $tags = get_available_tags();
463
464  // keep orphan tags
465  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
466  $orphan_tags = get_orphan_tags();
467  if (count($orphan_tags) > 0)
468  {
469    $orphan_tag_ids = array();
470    foreach ($orphan_tags as $tag)
471    {
472      $orphan_tag_ids[] = $tag['id'];
473    }
474   
475    $query = '
476SELECT *
477  FROM '.TAGS_TABLE.'
478  WHERE id IN ('.implode(',', $orphan_tag_ids).')
479;';
480    $result = pwg_query($query);
481    while ($row = pwg_db_fetch_assoc($result))
482    {
483      $tags[] = $row;
484    }
485  }
486
487  usort($tags, 'tag_alpha_compare');
488 
489  return array(
490    'tags' => new PwgNamedArray(
491      $tags,
492      'tag',
493      array(
494        'name',
495        'id',
496        'url_name',
497        )
498      )
499    );
500}
501
502add_event_handler('sendResponse', 'community_sendResponse');
503function community_sendResponse($encodedResponse)
504{
505  global $community, $user;
506
507  if (!isset($community['method']))
508  {
509    return;
510  }
511
512  if ('pwg.images.addSimple' == $community['method'])
513  {
514    $response = json_decode($encodedResponse);
515    $image_id = $response->result->image_id;
516  }
517  elseif ('pwg.images.add' == $community['method'])
518  {   
519    $query = '
520SELECT
521    id
522  FROM '.IMAGES_TABLE.'
523  WHERE md5sum = \''.$community['md5sum'].'\'
524  ORDER BY id DESC
525  LIMIT 1
526;';
527    list($image_id) = pwg_db_fetch_row(pwg_query($query));
528  }
529  else
530  {
531    return;
532  }
533 
534  $image_ids = array($image_id);
535
536  // $category_id is set in the photos_add_direct_process.inc.php included script
537  $category_infos = get_cat_info($community['category']);
538
539  // should the photos be moderated?
540  //
541  // if one of the user community permissions is not moderated on the path
542  // to gallery root, then the upload is not moderated. For example, if the
543  // user is allowed to upload to events/parties with no admin moderation,
544  // then he's not moderated when uploading in
545  // events/parties/happyNewYear2011
546  $moderate = true;
547
548  $user_permissions = community_get_user_permissions($user['id']);
549  $query = '
550SELECT
551    cp.category_id,
552    c.uppercats
553  FROM '.COMMUNITY_PERMISSIONS_TABLE.' AS cp
554    LEFT JOIN '.CATEGORIES_TABLE.' AS c ON category_id = c.id
555  WHERE cp.id IN ('.implode(',', $user_permissions['permission_ids']).')
556    AND cp.moderated = \'false\'
557;';
558  $result = pwg_query($query);
559  while ($row = pwg_db_fetch_assoc($result))
560  {
561    if (empty($row['category_id']))
562    {
563      $moderate = false;
564    }
565    elseif (preg_match('/^'.$row['uppercats'].'(,|$)/', $category_infos['uppercats']))
566    {
567      $moderate = false;
568    }
569  }
570 
571  if ($moderate)
572  {
573    $inserts = array();
574
575    $query = '
576SELECT
577    id,
578    date_available
579  FROM '.IMAGES_TABLE.'
580  WHERE id IN ('.implode(',', $image_ids).')
581;';
582    $result = pwg_query($query);
583    while ($row = pwg_db_fetch_assoc($result))
584    {
585      array_push(
586        $inserts,
587        array(
588          'image_id' => $row['id'],
589          'added_on' => $row['date_available'],
590          'state' => 'moderation_pending',
591          )
592        );
593    }
594   
595    mass_inserts(
596      COMMUNITY_PENDINGS_TABLE,
597      array_keys($inserts[0]),
598      $inserts
599      );
600   
601    // the level of a user upload photo with moderation is 16
602    $level = 16;
603  }
604  else
605  {
606    // the level of a user upload photo with no moderation is 0
607    $level = 0;
608  }
609
610  $query = '
611UPDATE '.IMAGES_TABLE.'
612  SET level = '.$level.'
613  WHERE id IN ('.implode(',', $image_ids).')
614;';
615  pwg_query($query);
616
617  invalidate_user_cache();
618}
619
620add_event_handler('delete_user', 'community_delete_user');
621function community_delete_user($user_id)
622{
623  $query = '
624DELETE
625  FROM '.COMMUNITY_PERMISSIONS_TABLE.'
626  WHERE user_id = '.$user_id.'
627;';
628  pwg_query($query);
629
630  community_reject_user_pendings($user_id);
631}
632
633add_event_handler('delete_categories', 'community_delete_category');
634function community_delete_category($category_ids)
635{
636  // $category_ids includes all the sub-category ids
637  $query = '
638DELETE
639  FROM '.COMMUNITY_PERMISSIONS_TABLE.'
640  WHERE category_id IN ('.implode(',', $category_ids).')
641;';
642  pwg_query($query);
643 
644  community_update_cache_key();
645}
646
647add_event_handler('delete_elements', 'community_delete_elements');
648function community_delete_elements($image_ids)
649{
650  $query = '
651DELETE
652  FROM '.COMMUNITY_PENDINGS_TABLE.'
653  WHERE image_id IN ('.implode(',', $image_ids).')
654;';
655  pwg_query($query);
656}
657
658add_event_handler('invalidate_user_cache', 'community_refresh_cache_update_time');
659function community_refresh_cache_update_time()
660{
661  community_update_cache_key();
662}
663
664add_event_handler('init', 'community_uploadify_privacy_level');
665function community_uploadify_privacy_level()
666{
667  if (script_basename() == 'uploadify' and !is_admin())
668  {
669    $_POST['level'] = 16;
670  }
671}
672
673// +-----------------------------------------------------------------------+
674// | User Albums                                                           |
675// +-----------------------------------------------------------------------+
676
677add_event_handler('loc_end_cat_modify', 'community_set_prefilter_cat_modify', 50);
678// add_event_handler('loc_begin_admin_page', 'community_cat_modify_submit', 45);
679
680// Change the variables used by the function that changes the template
681// add_event_handler('loc_begin_admin_page', 'community_cat_modify_add_vars_to_template');
682
683function community_set_prefilter_cat_modify()
684{
685        global $template, $conf, $category;
686
687  if (!isset($conf['community']['user_albums']) or !$conf['community']['user_albums'])
688  {
689    return;
690  }
691 
692  $template->set_prefilter('album_properties', 'community_cat_modify_prefilter');
693
694  $query = '
695SELECT
696    '.$conf['user_fields']['id'].' AS id,
697    '.$conf['user_fields']['username'].' AS username
698  FROM '.USERS_TABLE.' AS u
699    INNER JOIN '.USER_INFOS_TABLE.' AS uf ON uf.user_id = id
700  WHERE uf.status IN (\'normal\',\'generic\')
701;';
702  $result = pwg_query($query);
703  $users = array();
704  while ($row = pwg_db_fetch_assoc($result))
705  {
706    $users[$row['id']] = $row['username'];
707  }
708
709  $template->assign(
710    array(
711      'community_user_options' => $users,
712      'community_user_selected' => $category['community_user'],
713      )
714    );
715}
716
717function community_cat_modify_prefilter($content, &$smarty)
718{
719        $search = "#<strong>{'Name'#";
720
721        // We use the <tr> from the Creation date, and give them a new <tr>
722        $replacement = '<strong>(Community) {\'Album of user\'|@translate}</strong>
723                <br>
724                        <select name="community_user">
725                                <option value="">--</option>
726                                {html_options options=$community_user_options selected=$community_user_selected}
727                        </select>
728      <em>{\'a user can own only one album\'|@translate}</em>
729                </p>
730       
731        </p>
732  <p>
733                <strong>{\'Name\'';
734
735  return preg_replace($search, $replacement, $content);
736}
737
738add_event_handler('loc_begin_cat_modify', 'community_cat_modify_submit');
739function community_cat_modify_submit()
740{
741  global $category, $conf;
742
743  if (!isset($conf['community']['user_albums']) or !$conf['community']['user_albums'])
744  {
745    return;
746  }
747 
748  if (isset($_POST['community_user']))
749  {
750    // echo '<pre>'; print_r($_POST); echo '</pre>'; exit();
751    // only one album for each user, first we remove ownership on any other album
752    single_update(
753      CATEGORIES_TABLE,
754      array('community_user' => null),
755      array('community_user' => $_POST['community_user'])
756      );
757
758    // then we give the album to the user
759    single_update(
760      CATEGORIES_TABLE,
761      array('community_user' => $_POST['community_user']),
762      array('id' => $category['id'])
763      );
764  }
765}
766?>
Note: See TracBrowser for help on using the repository browser.