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

Last change on this file since 29354 was 29317, checked in by mistic100, 10 years ago

Add allow_send_admin parameter

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