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

Last change on this file since 23085 was 23085, checked in by plg, 7 years ago

New feature: user album. Only for registered users, no recursivity. Piwigo
will automatically create an upload album for each user with appropriate
community permissions, at first connection.

Bug fixed: on activation, do not create a new "Community" album if it already
exists.

Bug fixed: remove debug for quota

Bug fixed: round corners for number of pending pictures in admin menu.

File size: 15.9 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  WHERE state = \'moderation_pending\'
88;';
89  $result = pwg_query($query);
90  list($page['community_nb_pendings']) = pwg_db_fetch_row($result);
91
92  $name = 'Community';
93  if ($page['community_nb_pendings'] > 0)
94  {
95    $style = 'background-color:#666;';
96    $style.= 'color:white;';
97    $style.= 'padding:1px 5px;';
98    $style.= '-moz-border-radius:10px;';
99    $style.= '-webkit-border-radius:10px;';
100    $style.= 'border-radius:10px;';
101    $style.= 'margin-left:5px;';
102   
103    $name.= '<span style="'.$style.'">'.$page['community_nb_pendings'].'</span>';
104
105    if (defined('IN_ADMIN') and IN_ADMIN and $page['page'] == 'intro')
106    {
107      global $template;
108     
109      $template->set_prefilter('intro', 'community_pendings_on_intro');
110      $template->assign(
111        array(
112          'COMMUNITY_PENDINGS' => sprintf(
113            '<a href="%s">'.l10n('%u pending photos').'</a>',
114            get_root_url().'admin.php?page=plugin-community-pendings',
115            $page['community_nb_pendings']
116            ),
117          )
118        );
119    }
120  }
121
122  array_push(
123    $menu,
124    array(
125      'NAME' => $name,
126      'URL'  => get_root_url().'admin.php?page=plugin-community'
127      )
128    );
129
130  return $menu;
131}
132
133function community_pendings_on_intro($content, &$smarty)
134{
135  $pattern = '#<li>\s*{\$DB_ELEMENTS\}#ms';
136  $replacement = '<li>{$COMMUNITY_PENDINGS}</li><li>{$DB_ELEMENTS}';
137  return preg_replace($pattern, $replacement, $content);
138}
139
140add_event_handler('init', 'community_load_language');
141function community_load_language()
142{
143  if (!defined('IN_ADMIN') or !IN_ADMIN)
144  {
145    load_language('admin.lang');
146  }
147 
148  load_language('plugin.lang', COMMUNITY_PATH);
149}
150
151
152add_event_handler('loc_end_section_init', 'community_section_init');
153function community_section_init()
154{
155  global $tokens, $page;
156 
157  if ($tokens[0] == 'add_photos')
158  {
159    $page['section'] = 'add_photos';
160  }
161}
162
163add_event_handler('loc_end_index', 'community_index');
164function community_index()
165{
166  global $page;
167 
168  if (isset($page['section']) and $page['section'] == 'add_photos')
169  {
170    include(COMMUNITY_PATH.'add_photos.php');
171  }
172}
173
174add_event_handler('blockmanager_apply' , 'community_gallery_menu', EVENT_HANDLER_PRIORITY_NEUTRAL+10);
175function community_gallery_menu($menu_ref_arr)
176{
177  global $conf, $user;
178
179  // conditional : depending on community permissions, display the "Add
180  // photos" link in the gallery menu
181  $user_permissions = $user['community_permissions'];
182
183  if (!$user_permissions['community_enabled'])
184  {
185    return;
186  }
187
188  $menu = & $menu_ref_arr[0];
189
190  if (($block = $menu->get_block('mbMenu')) != null )
191  {
192    load_language('plugin.lang', COMMUNITY_PATH);
193
194    array_splice(
195      $block->data,
196      count($block->data),
197      0,
198      array(
199        '' => array(
200          'URL' => make_index_url(array('section' => 'add_photos')),
201          'TITLE' => l10n('Upload your own photos'),
202          'NAME' => l10n('Upload Photos')
203          )
204        )
205      );
206  }
207}
208
209
210add_event_handler('ws_invoke_allowed', 'community_switch_user_to_admin', EVENT_HANDLER_PRIORITY_NEUTRAL, 3);
211function community_switch_user_to_admin($res, $methodName, $params)
212{
213  global $user, $community;
214
215  if (is_admin())
216  {
217    return $res;
218  }
219 
220  $community = array('method' => $methodName);
221
222  if ('pwg.images.addSimple' == $community['method'])
223  {
224    $community['category'] = $params['category'];
225  }
226  elseif ('pwg.images.add' == $community['method'])
227  {
228    $community['category'] = $params['categories'];
229    $community['md5sum'] = $params['original_sum'];
230  }
231
232  // $print_params = $params;
233  // unset($print_params['data']);
234  // file_put_contents('/tmp/community.log', '['.$methodName.'] '.json_encode($print_params)."\n" ,FILE_APPEND);
235
236  // conditional : depending on community permissions, display the "Add
237  // photos" link in the gallery menu
238  $user_permissions = community_get_user_permissions($user['id']);
239
240  if (count($user_permissions['upload_categories']) == 0 and !$user_permissions ['create_whole_gallery'])
241  {
242    return $res;
243  }
244
245  // if level of trust is low, then we have to set level to 16
246
247  $methods = array();
248  $methods[] = 'pwg.tags.add';
249  $methods[] = 'pwg.images.exist';
250  $methods[] = 'pwg.images.add';
251  $methods[] = 'pwg.images.addSimple';
252  $methods[] = 'pwg.images.addChunk';
253  $methods[] = 'pwg.images.checkUpload';
254  $methods[] = 'pwg.images.checkFiles';
255  $methods[] = 'pwg.images.setInfo';
256
257  if (in_array($methodName, $methods))
258  {
259    $user['status'] = 'admin';
260  }
261
262  if ('pwg.categories.add' == $methodName)
263  {
264    if (in_array($params['parent'], $user_permissions['create_categories'])
265        or $user_permissions['create_whole_gallery'])
266    {
267      $user['status'] = 'admin';
268    }
269  }
270
271  return $res;
272}
273
274add_event_handler('ws_add_methods', 'community_ws_replace_methods', EVENT_HANDLER_PRIORITY_NEUTRAL+5);
275function community_ws_replace_methods($arr)
276{
277  global $conf, $user;
278 
279  $service = &$arr[0];
280
281  if (is_admin())
282  {
283    return;
284  }
285
286  $user_permissions = community_get_user_permissions($user['id']);
287 
288  if (count($user_permissions['permission_ids']) == 0)
289  {
290    return;
291  }
292 
293  // the plugin Community is activated, the user has upload permissions, we
294  // use a specific function to list available categories, assuming the user
295  // wants to list categories where upload is possible for him
296 
297  $service->addMethod(
298    'pwg.categories.getList',
299    'community_ws_categories_getList',
300    array(
301      'cat_id' =>       array('default'=>0),
302      'recursive' =>    array('default'=>false),
303      'public' =>       array('default'=>false),
304      'tree_output' =>  array('default'=>false),
305      'fullname' =>     array('default'=>false),
306      ),
307    'retrieves a list of categories'
308    );
309 
310  $service->addMethod(
311    'pwg.tags.getAdminList',
312    'community_ws_tags_getAdminList',
313    array(),
314    'administration method only'
315    );
316}
317
318/**
319 * returns a list of categories (web service method)
320 */
321function community_ws_categories_getList($params, &$service)
322{
323  global $user, $conf;
324
325  if ($params['tree_output'])
326  {
327    if (!isset($_GET['format']) or !in_array($_GET['format'], array('php', 'json')))
328    {
329      // the algorithm used to build a tree from a flat list of categories
330      // keeps original array keys, which is not compatible with
331      // PwgNamedArray.
332      //
333      // PwgNamedArray is useful to define which data is an attribute and
334      // which is an element in the XML output. The "hierarchy" output is
335      // only compatible with json/php output.
336
337      return new PwgError(405, "The tree_output option is only compatible with json/php output formats");
338    }
339  }
340 
341  $where = array('1=1');
342  $join_type = 'LEFT';
343  $join_user = $user['id'];
344
345  if (!$params['recursive'])
346  {
347    if ($params['cat_id']>0)
348      $where[] = '(id_uppercat='.(int)($params['cat_id']).'
349    OR id='.(int)($params['cat_id']).')';
350    else
351      $where[] = 'id_uppercat IS NULL';
352  }
353  else if ($params['cat_id']>0)
354  {
355    $where[] = 'uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.
356      (int)($params['cat_id'])
357      .'(,|$)\'';
358  }
359
360  if ($params['public'])
361  {
362    $where[] = 'status = "public"';
363    $where[] = 'visible = "true"';
364   
365    $join_user = $conf['guest_id'];
366  }
367
368  $user_permissions = community_get_user_permissions($user['id']);
369  $upload_categories = $user_permissions['upload_categories'];
370  if (count($upload_categories) == 0)
371  {
372    $upload_categories = array(-1);
373  }
374
375  $where[] = 'id IN ('.implode(',', $upload_categories).')';
376
377  $query = '
378SELECT
379    id,
380    name,
381    permalink,
382    uppercats,
383    global_rank,
384    comment,
385    nb_images,
386    count_images AS total_nb_images,
387    date_last,
388    max_date_last,
389    count_categories AS nb_categories
390  FROM '.CATEGORIES_TABLE.'
391   '.$join_type.' JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id AND user_id='.$join_user.'
392  WHERE '. implode('
393    AND ', $where);
394
395  $result = pwg_query($query);
396
397  $cats = array();
398  while ($row = pwg_db_fetch_assoc($result))
399  {
400    $row['url'] = make_index_url(
401        array(
402          'category' => $row
403          )
404      );
405    foreach( array('id','nb_images','total_nb_images','nb_categories') as $key)
406    {
407      $row[$key] = (int)$row[$key];
408    }
409
410    if ($params['fullname'])
411    {
412      $row['name'] = strip_tags(get_cat_display_name_cache($row['uppercats'], null, false));
413    }
414    else
415    {
416      $row['name'] = strip_tags(
417        trigger_event(
418          'render_category_name',
419          $row['name'],
420          'ws_categories_getList'
421          )
422        );
423    }
424   
425    $row['comment'] = strip_tags(
426      trigger_event(
427        'render_category_description',
428        $row['comment'],
429        'ws_categories_getList'
430        )
431      );
432   
433    array_push($cats, $row);
434  }
435  usort($cats, 'global_rank_compare');
436
437  if ($params['tree_output'])
438  {
439    return categories_flatlist_to_tree($cats);
440  }
441  else
442  {
443    return array(
444      'categories' => new PwgNamedArray(
445        $cats,
446        'category',
447        array(
448          'id',
449          'url',
450          'nb_images',
451          'total_nb_images',
452          'nb_categories',
453          'date_last',
454          'max_date_last',
455          )
456        )
457      );
458  }
459}
460
461function community_ws_tags_getAdminList($params, &$service)
462{
463  $tags = get_available_tags();
464
465  // keep orphan tags
466  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
467  $orphan_tags = get_orphan_tags();
468  if (count($orphan_tags) > 0)
469  {
470    $orphan_tag_ids = array();
471    foreach ($orphan_tags as $tag)
472    {
473      $orphan_tag_ids[] = $tag['id'];
474    }
475   
476    $query = '
477SELECT *
478  FROM '.TAGS_TABLE.'
479  WHERE id IN ('.implode(',', $orphan_tag_ids).')
480;';
481    $result = pwg_query($query);
482    while ($row = pwg_db_fetch_assoc($result))
483    {
484      $tags[] = $row;
485    }
486  }
487
488  usort($tags, 'tag_alpha_compare');
489 
490  return array(
491    'tags' => new PwgNamedArray(
492      $tags,
493      'tag',
494      array(
495        'name',
496        'id',
497        'url_name',
498        )
499      )
500    );
501}
502
503add_event_handler('sendResponse', 'community_sendResponse');
504function community_sendResponse($encodedResponse)
505{
506  global $community, $user;
507
508  if (!isset($community['method']))
509  {
510    return;
511  }
512
513  if ('pwg.images.addSimple' == $community['method'])
514  {
515    $response = json_decode($encodedResponse);
516    $image_id = $response->result->image_id;
517  }
518  elseif ('pwg.images.add' == $community['method'])
519  {   
520    $query = '
521SELECT
522    id
523  FROM '.IMAGES_TABLE.'
524  WHERE md5sum = \''.$community['md5sum'].'\'
525  ORDER BY id DESC
526  LIMIT 1
527;';
528    list($image_id) = pwg_db_fetch_row(pwg_query($query));
529  }
530  else
531  {
532    return;
533  }
534 
535  $image_ids = array($image_id);
536
537  // $category_id is set in the photos_add_direct_process.inc.php included script
538  $category_infos = get_cat_info($community['category']);
539
540  // should the photos be moderated?
541  //
542  // if one of the user community permissions is not moderated on the path
543  // to gallery root, then the upload is not moderated. For example, if the
544  // user is allowed to upload to events/parties with no admin moderation,
545  // then he's not moderated when uploading in
546  // events/parties/happyNewYear2011
547  $moderate = true;
548
549  $user_permissions = community_get_user_permissions($user['id']);
550  $query = '
551SELECT
552    cp.category_id,
553    c.uppercats
554  FROM '.COMMUNITY_PERMISSIONS_TABLE.' AS cp
555    LEFT JOIN '.CATEGORIES_TABLE.' AS c ON category_id = c.id
556  WHERE cp.id IN ('.implode(',', $user_permissions['permission_ids']).')
557    AND cp.moderated = \'false\'
558;';
559  $result = pwg_query($query);
560  while ($row = pwg_db_fetch_assoc($result))
561  {
562    if (empty($row['category_id']))
563    {
564      $moderate = false;
565    }
566    elseif (preg_match('/^'.$row['uppercats'].'(,|$)/', $category_infos['uppercats']))
567    {
568      $moderate = false;
569    }
570  }
571 
572  if ($moderate)
573  {
574    $inserts = array();
575
576    $query = '
577SELECT
578    id,
579    date_available
580  FROM '.IMAGES_TABLE.'
581  WHERE id IN ('.implode(',', $image_ids).')
582;';
583    $result = pwg_query($query);
584    while ($row = pwg_db_fetch_assoc($result))
585    {
586      array_push(
587        $inserts,
588        array(
589          'image_id' => $row['id'],
590          'added_on' => $row['date_available'],
591          'state' => 'moderation_pending',
592          )
593        );
594    }
595   
596    mass_inserts(
597      COMMUNITY_PENDINGS_TABLE,
598      array_keys($inserts[0]),
599      $inserts
600      );
601   
602    // the level of a user upload photo with moderation is 16
603    $level = 16;
604  }
605  else
606  {
607    // the level of a user upload photo with no moderation is 0
608    $level = 0;
609  }
610
611  $query = '
612UPDATE '.IMAGES_TABLE.'
613  SET level = '.$level.'
614  WHERE id IN ('.implode(',', $image_ids).')
615;';
616  pwg_query($query);
617
618  invalidate_user_cache();
619}
620
621add_event_handler('delete_user', 'community_delete_user');
622function community_delete_user($user_id)
623{
624  $query = '
625DELETE
626  FROM '.COMMUNITY_PERMISSIONS_TABLE.'
627  WHERE user_id = '.$user_id.'
628;';
629  pwg_query($query);
630
631  community_reject_user_pendings($user_id);
632}
633
634add_event_handler('delete_categories', 'community_delete_category');
635function community_delete_category($category_ids)
636{
637  // $category_ids includes all the sub-category ids
638  $query = '
639DELETE
640  FROM '.COMMUNITY_PERMISSIONS_TABLE.'
641  WHERE category_id IN ('.implode(',', $category_ids).')
642;';
643  pwg_query($query);
644 
645  community_update_cache_key();
646}
647
648add_event_handler('invalidate_user_cache', 'community_refresh_cache_update_time');
649function community_refresh_cache_update_time()
650{
651  community_update_cache_key();
652}
653
654add_event_handler('init', 'community_uploadify_privacy_level');
655function community_uploadify_privacy_level()
656{
657  if (script_basename() == 'uploadify' and !is_admin())
658  {
659    $_POST['level'] = 16;
660  }
661}
662?>
Note: See TracBrowser for help on using the repository browser.