source: extensions/UserCollections/include/UserCollection.class.php @ 24421

Last change on this file since 24421 was 24421, checked in by mistic100, 11 years ago

new system for shares : password protection, link timeout, management popup + for mails
handle lightbox conflicts
menublock is visible by AMM

File size: 15.7 KB
Line 
1<?php
2defined('USER_COLLEC_PATH') or die('Hacking attempt!');
3
4class UserCollection
5{
6  private $data;
7  private $images;
8 
9  /**
10   * __construct
11   * @param: mixed col id (##|'new')
12   * @param: array images
13   */
14  function __construct($col_id, $name=null, $comment=null, $user_id=null)
15  {
16    global $user;
17   
18    if (empty($user_id))
19    {
20      $user_id = $user['id'];
21    }
22   
23    $this->data = array(
24      'id' => 0,
25      'user_id' => $user_id,
26      'name' => null,
27      'date_creation' => '0000-00-00 00:00:00',
28      'comment' => null,
29      'nb_images' => 0,
30      );
31    $this->images = array();
32   
33    // load specific collection
34    if (preg_match('#^[0-9]+$#', $col_id))
35    {
36      $query = '
37SELECT *
38  FROM '.COLLECTIONS_TABLE.'
39  WHERE id = '.$col_id.'
40;';
41      $result = pwg_query($query);
42     
43      if (pwg_db_num_rows($result))
44      {
45        $this->data = array_merge(
46          $this->data,
47          pwg_db_fetch_assoc($result)
48          );
49       
50        // make sure all pictures of the collection exist
51        $query = '
52DELETE FROM '.COLLECTION_IMAGES_TABLE.'
53  WHERE image_id NOT IN (
54    SELECT id FROM '.IMAGES_TABLE.'
55    )
56;';
57        pwg_query($query);
58     
59        // select images of the collection
60        $query = '
61SELECT image_id
62  FROM '.COLLECTION_IMAGES_TABLE.'
63  WHERE col_id = '.$this->data['id'].'
64;';
65        $this->images = array_from_query($query, 'image_id');
66       
67        $this->updateParam('nb_images', count($this->images));
68      }
69      else
70      {
71        throw new Exception(l10n('Invalid collection'), WS_ERR_INVALID_PARAM);
72      }
73    }
74    // create a new collection
75    else if ($col_id == 'new')
76    {
77      $this->data['name'] = $name;
78      $this->data['comment'] = $comment;
79     
80      $query = '
81INSERT INTO '.COLLECTIONS_TABLE.'(
82    user_id,
83    name,
84    date_creation,
85    comment
86  )
87  VALUES(
88    '.$this->data['user_id'].',
89    "'.$this->data['name'].'",
90    NOW(),
91    "'.$this->data['comment'].'"
92  )
93;';
94      pwg_query($query);
95      $this->data['id'] = pwg_db_insert_id();
96     
97      $date = pwg_query('SELECT NOW();');
98      list($this->data['date_creation']) = pwg_db_fetch_row($date);
99    }
100    else
101    {
102      trigger_error('UserCollection::__construct, invalid input parameter', E_USER_ERROR);
103    }
104  }
105 
106  /**
107   * check if current user is owner of the collection or admin
108   */
109  function checkUser()
110  {
111    global $user;
112   
113    if (!is_admin() && $user['id'] != $this->data['user_id'])
114    {
115      throw new Exception('Forbidden', 403);
116    }
117  }
118 
119  /**
120   * updateParam
121   * @param: string param name
122   * @param: mixed param value
123   */
124  function updateParam($name, $value)
125  {
126    if ($value != $this->data[$name])
127    {
128      $this->data[$name] = $value;
129      pwg_query('UPDATE '.COLLECTIONS_TABLE.' SET '.$name.' = "'.pwg_db_real_escape_string($value).'" WHERE id = '.$this->data['id'].';');
130    }
131  }
132 
133  /**
134   * getParam
135   * @param: string param name
136   * @return: mixed param value
137   */
138  function getParam($name)
139  {
140    return $this->data[$name];
141  }
142 
143  /**
144   * getImages
145   * @return: array
146   */
147  function getImages()
148  {
149    return $this->images;
150  }
151 
152  /**
153   * isInSet
154   * @param: int image id
155   * @return: bool
156   */
157  function isInSet($image_id)
158  {
159    return in_array($image_id, $this->images);
160  }
161 
162  /**
163   * removeImages
164   * @param: array image ids
165   */
166  function removeImages($image_ids)
167  {
168    if (empty($image_ids) or !is_array($image_ids)) return;
169   
170    $this->images = array_diff($this->images, $image_ids);
171   
172    $query = '
173DELETE FROM '.COLLECTION_IMAGES_TABLE.'
174  WHERE
175    col_id = '.$this->data['id'].'
176    AND image_id IN('.implode(',', $image_ids).')
177;';
178    pwg_query($query);
179   
180    $this->updateParam('nb_images', count($this->images));
181  }
182 
183  /**
184   * addImages
185   * @param: array image ids
186   */
187  function addImages($image_ids)
188  {
189    if (empty($image_ids) or !is_array($image_ids)) return;
190   
191    $image_ids = array_unique($image_ids);
192    $inserts = array();
193   
194    foreach ($image_ids as $image_id)
195    {
196      if ($this->isInSet($image_id)) continue;
197     
198      $this->images[] = $image_id;
199      $inserts[] = array(
200        'col_id' => $this->data['id'],
201        'image_id' => $image_id,
202        );
203    }
204   
205    mass_inserts(
206      COLLECTION_IMAGES_TABLE,
207      array('col_id', 'image_id'),
208      $inserts
209      );
210     
211    $query = '
212UPDATE '.COLLECTION_IMAGES_TABLE.'
213  SET add_date = NOW()
214  WHERE
215    col_id = '.$this->data['id'].'
216    AND image_id IN ('.implode(',', $image_ids).')
217    AND add_date IS NULL
218';
219    pwg_query($query);
220     
221    $this->updateParam('nb_images', count($this->images));
222  }
223 
224  /**
225   * toggleImage
226   * @param: int image id
227   */
228  function toggleImage($image_id)
229  {
230    if ($this->isInSet($image_id))
231    {
232      $this->removeImages(array($image_id));
233    }
234    else
235    {
236      $this->addImages(array($image_id));
237    }
238  }
239 
240  /**
241   * clearImages
242   */
243  function clearImages()
244  {
245    $this->images = array();
246    $this->updateParam('nb_images', 0);
247   
248    $query = '
249DELETE FROM '.COLLECTION_IMAGES_TABLE.'
250  WHERE col_id = '.$this->data['id'].'
251;';
252    pwg_query($query);
253  }
254 
255  /**
256   * getCollectionInfo
257   * @return: array
258   */
259  function getCollectionInfo()
260  {
261    $set = array(
262      'ID' => $this->data['id'],
263      'NAME' => $this->data['name'],
264      'COMMENT' => $this->data['comment'],
265      'NB_IMAGES' => $this->data['nb_images'],
266      'DATE_CREATION' => $this->data['date_creation'],
267      );
268   
269    return $set;
270  }
271 
272  /**
273   * get share links
274   */
275  function getShares()
276  {
277    $query = '
278SELECT * FROM '.COLLECTION_SHARES_TABLE.'
279  WHERE col_id = '.$this->data['id'].'
280  ORDER BY add_date DESC
281;';
282    $result = pwg_query($query);
283   
284    $shares = array();
285    while ($row = pwg_db_fetch_assoc($result))
286    {
287      $row['expired'] = false;
288     
289      $row['params'] = unserialize($row['params']);
290      if (!empty($row['params']['deadline']))
291      {
292        $row['expired'] = strtotime($row['params']['deadline']) < time();
293        $row['params']['deadline_readable'] = format_date($row['params']['deadline'], true, false);
294      }
295     
296      $row['url'] = USER_COLLEC_PUBLIC . 'view/' . $row['share_key'];
297      $row['u_delete'] = USER_COLLEC_PUBLIC . 'edit/' . $this->data['id'] . '&amp;delete_share=' . $row['id'];
298      $row['add_date_readable'] = format_date($row['add_date'], true, false);
299     
300      $shares[] = $row;
301    }
302   
303    return $shares;
304  }
305 
306  /**
307   * delete a share
308   */
309  function deleteShare($id)
310  {
311    $query = '
312DELETE FROM '.COLLECTION_SHARES_TABLE.'
313  WHERE id = "'.pwg_db_real_escape_string($id).'"
314  AND col_id = '.$this->data['id'].'
315;';
316    pwg_query($query);
317   
318    return pwg_db_changes() != 0;
319  }
320 
321  /**
322   * Add a share URL
323   * @param: array
324   *          - share_key
325   *          - password
326   *          - deadline
327   * @return: array errors
328   */
329  function addShare($share, $abord_on_duplicate=true)
330  {
331    global $conf, $page;
332   
333    $errors = array();
334   
335    $share = array_map('stripslashes', $share);
336   
337    // check key
338    if (empty($share['share_key']) || strlen($share['share_key']) < 8)
339    {
340      $errors[] = l10n('The key must be at least 8 characters long');
341    }
342    else
343    {
344      $share['share_key'] = $this->data['id'].'-'.str2url($share['share_key']);
345     
346      $query = '
347SELECT id FROM '.COLLECTION_SHARES_TABLE.'
348  WHERE col_id = '.$this->data['id'].'
349  AND share_key = "'.$share['share_key'].'"
350;';
351      $result = pwg_query($query);
352      if (pwg_db_num_rows($result))
353      {
354        if ($abord_on_duplicate)
355        {
356          $errors[] = l10n('This key is already used');
357        }
358        else
359        {
360          return USER_COLLEC_PUBLIC . 'view/' . $share['share_key'];
361        }
362      }
363    }
364   
365    // filter date
366    if (!empty($share['deadline']))
367    {
368      $date = DateTime::createFromFormat('Y-m-d H:i', $share['deadline']);
369      $share['deadline'] = $date->format('Y-m-d H:i');
370    }
371   
372    // hash password
373    if (!empty($share['password']))
374    {
375      $share['password'] = sha1($conf['secret_key'].$share['password'].$share['share_key']);
376    }
377   
378    if (empty($errors))
379    {
380      $params = serialize(array(
381        'password' => @$share['password'],
382        'deadline' => @$share['deadline'],
383        ));
384     
385      $query = '
386INSERT INTO '.COLLECTION_SHARES_TABLE.'(
387    col_id,
388    share_key,
389    params,
390    add_date
391  )
392  VALUES(
393    '.$this->data['id'].',
394    "'.$share['share_key'].'",
395    "'.pwg_db_real_escape_string($params).'",
396    "'.date('Y-m-d H:i:s').'"
397  )
398;';
399      pwg_query($query);
400     
401      return USER_COLLEC_PUBLIC . 'view/' . $share['share_key'];
402    }
403   
404    return $errors;
405  }
406 
407  /**
408   * Send the collection by email
409   * @param: array
410   *          - sender_name
411   *          - sender_email
412   *          - recipient_email
413   *          - recipient_name
414   *          - nb_images
415   *          - message
416   * @return: array errors
417   */
418  function sendEmail($comm)
419  {
420    global $conf;
421   
422    $errors = array();
423   
424    $comm = array_map('stripslashes', $comm);
425
426    $comment_action='validate';
427
428    // check author
429    if (empty($comm['sender_name']))
430    {
431      array_push($errors, l10n('Please enter your name'));
432      $comment_action='reject';
433    }     
434    if (empty($comm['recipient_name']))
435    {
436      array_push($errors, l10n('Please enter the recipient name'));
437      $comment_action='reject';
438    }
439   
440    // check email
441    if (empty($comm['sender_email']))
442    {
443      array_push($errors, l10n('Please enter your e-mail'));
444      $comment_action='reject';
445    }
446    else if ( !empty($comm['sender_email']) and !uc_check_email_validity($comm['sender_email']) )
447    {
448      array_push($errors, l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
449      $comment_action='reject';
450    }
451    if (empty($comm['recipient_email']))
452    {
453      array_push($errors, l10n('Please enter the recipient e-mail'));
454      $comment_action='reject';
455    }
456    else if ( !empty($comm['recipient_email']) and !uc_check_email_validity($comm['recipient_email']) )
457    {
458      array_push($errors, l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
459      $comment_action='reject';
460    }
461     
462    // check content
463    if (!empty($comm['message']))
464    {
465      $comm['message'] = nl2br($comm['message']);
466    }
467   
468    include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
469   
470    if ($comment_action == 'validate')
471    {
472      // format subject
473      $subject = '['.$conf['gallery_title'].'] '.sprintf(l10n('A photo collection by %s'), $comm['sender_name']);
474      $subject = encode_mime_header($subject);
475           
476      // format expeditor
477      $args['from'] = format_email($comm['sender_name'], $comm['sender_email']);
478      $args['to'] = format_email($comm['recipient_name'], $comm['recipient_email']);
479     
480      // hearders
481      $headers = 'From: '.$args['from']."\n"; 
482      $headers.= 'MIME-Version: 1.0'."\n";
483      $headers.= 'X-Mailer: Piwigo Mailer'."\n";
484      $headers.= 'Content-Transfer-Encoding: 8bit'."\n";
485      $headers.= 'Content-Type: text/html; charset="'.get_pwg_charset().'";'."\n";
486           
487      // mail content
488      $content = $this->getMailContent($comm);
489      $content = wordwrap($content, 70, "\n", true);
490     
491      // send mail
492      $result =
493        trigger_event('send_mail',
494          false, /* Result */
495          trigger_event('send_mail_to', $args['to']),
496          trigger_event('send_mail_subject', $subject),
497          trigger_event('send_mail_content', $content),
498          trigger_event('send_mail_headers', $headers),
499          $args
500        );
501     
502      if ($result == false)
503      {
504        array_push($errors, l10n('Error while sending e-mail'));
505      }
506      else
507      {
508        return true;
509      }
510    }
511   
512    return $errors;
513  }
514 
515  /**
516   * get mail content for sendMail()
517   */
518  function getMailContent($params)
519  {
520    global $user, $conf, $template;
521   
522    // switch to guest user
523    $user_save = $user;
524    $user = build_user($conf['guest_id'], true);
525   
526    // get pictures
527    $query = '
528SELECT
529    id,
530    file,
531    name,
532    path
533  FROM '.IMAGES_TABLE.' AS i
534    JOIN '.IMAGE_CATEGORY_TABLE.' AS ci ON ci.image_id = i.id
535  WHERE id IN ('.implode(',', $this->images).')
536    '.get_sql_condition_FandF(array(
537                'forbidden_categories' => 'category_id',
538                'forbidden_images' => 'id'
539                ),
540              'AND'
541              ).'
542  GROUP BY i.id
543  ORDER BY '.DB_RANDOM_FUNCTION.'()
544  LIMIT '.$params['nb_images'].'
545;';
546    $pictures = hash_from_query($query, 'id');
547   
548    // switch back to current user
549    $user = $user_save;
550    unset($user_save);
551 
552    // picture sinfos
553    set_make_full_url();
554    $tpl_vars = array();
555    foreach ($pictures as $row)
556    {
557      $name = render_element_name($row);
558     
559      $tpl_vars[] = array(
560        'TN_ALT' => htmlspecialchars(strip_tags($name)),
561        'NAME' => $name,
562        'URL' => make_picture_url(array('image_id' => $row['id'])),
563        'THUMB' => DerivativeImage::url(IMG_SQUARE, $row),
564        );
565    }
566   
567    // template
568    $mail_css = file_get_contents(dirname(__FILE__).'/../template/mail.css');
569   
570    $share_key = 'mail-' . substr(sha1($this->data['id'].$conf['secret_key']), 0, 11);
571   
572    $template->assign(array(
573      'GALLERY_URL' => get_gallery_home_url(),
574      'PHPWG_URL' => PHPWG_URL,
575      'UC_MAIL_CSS' => str_replace("\n", null, $mail_css),
576      'MAIL_TITLE' => $this->getParam('name').' ('.sprintf(l10n('by %s'), $params['sender_name']).')',
577      'COL_URL' => $this->addShare(array('share_key'=>$share_key), false),
578      'PARAMS' => $params,
579      'derivative_params' => ImageStdParams::get_by_type(IMG_SQUARE),
580      'thumbnails' => $tpl_vars,
581      ));
582     
583    $template->set_filename('uc_mail', dirname(__FILE__).'/../template/mail.tpl');
584    $content = $template->parse('uc_mail', true);
585 
586    unset_make_full_url();
587   
588    return $content;
589  }
590
591  /**
592   * generate a listing of the collection
593   */
594  function serialize($params)
595  {
596    $params = array_intersect($params, array('id','file','name','url','path','date_creation','collection_add_date','filesize','width','height'));
597   
598    $content = null;
599     
600    // get images infos
601    $query = '
602SELECT
603    id,
604    file,
605    name,
606    path,
607    date_creation,
608    filesize,
609    width,
610    height,
611    add_date AS collection_add_date
612  FROM '.IMAGES_TABLE.'
613    JOIN '.COLLECTION_IMAGES_TABLE.' ON id = image_id
614  WHERE col_id = '.$this->data['id'].'
615  ORDER BY id
616;';
617    $pictures = hash_from_query($query, 'id');
618   
619    if (count($pictures))
620    {
621      // generate csv
622      set_make_full_url();
623      $root_url = get_root_url();
624     
625      $fp = fopen('php://temp', 'r+');
626      fputcsv($fp, $params);
627       
628      foreach ($pictures as $row)
629      {
630        $element = array();
631        foreach ($params as $field)
632        {
633          switch ($field)
634          {
635          case 'name':
636            $element[] = render_element_name($row);
637            break;
638          case 'url':
639            $element[] = make_picture_url(array('image_id'=>$row['id'], 'image_file'=>$row['file']));
640            break;
641          case 'path':
642            $element[] = $root_url.ltrim($row['path'], './');
643            break;
644          default:
645            $element[] = $row[$field];
646            break;
647          }
648        }
649        if (!empty($element))
650        {
651          fputcsv($fp, $element);
652        }
653      }
654     
655      rewind($fp);
656      $content = stream_get_contents($fp);
657      fclose($fp);
658     
659      unset_make_full_url();
660    }
661   
662    return $content;
663  }
664 
665  /**
666   * delete
667   */
668  function delete()
669  {
670    $this->clearImages();
671    pwg_query('DELETE FROM '.COLLECTIONS_TABLE.' WHERE id = '.$this->data['id'].';');
672  }
673}
674
675?>
Note: See TracBrowser for help on using the repository browser.