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

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

compatibility with Piwigo 2.7

For now, we keep uploadify (Flash) on Community because it is more compatible
with old browsers like IE8/IE9. Once the new HTML5 upload form will be more
mature, we will replace uploadify on Community too.

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