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

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

use of undefined constant, retard mobile detection

File size: 14.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   * @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
451    // check author
452    if (empty($comm['sender_name']))
453    {
454      $errors[] = l10n('Please enter your name');
455      $comment_action = 'reject';
456    }
457    if (empty($comm['recipient_name']))
458    {
459      $errors[] = l10n('Please enter the recipient name');
460      $comment_action = 'reject';
461    }
462
463    // check email
464    if (empty($comm['sender_email']))
465    {
466      $errors[] = l10n('Please enter your e-mail');
467      $comment_action = 'reject';
468    }
469    else if (!empty($comm['sender_email']) and !email_check_format($comm['sender_email']))
470    {
471      $errors[] = l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
472      $comment_action = 'reject';
473    }
474    if (empty($comm['recipient_email']))
475    {
476      $errors[] = l10n('Please enter the recipient e-mail');
477      $comment_action = 'reject';
478    }
479    else if (!empty($comm['recipient_email']) and !email_check_format($comm['recipient_email']))
480    {
481      $errors[] = l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
482      $comment_action = 'reject';
483    }
484
485    // check content
486    if (!empty($comm['message']))
487    {
488      $comm['message'] = nl2br($comm['message']);
489    }
490
491    include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
492
493    if ($comment_action == 'validate')
494    {
495      // switch to guest user for get_sql_condition_FandF
496      $user_save = $user;
497      $user = build_user($conf['guest_id'], true);
498
499      // get pictures
500      $query = '
501SELECT
502    id, file, name, path
503  FROM '.IMAGES_TABLE.' AS i
504    JOIN '.IMAGE_CATEGORY_TABLE.' AS ci ON ci.image_id = i.id
505  WHERE id IN ('. implode(',', $this->images) .')
506    '.get_sql_condition_FandF(
507        array(
508          'forbidden_categories' => 'category_id',
509          'forbidden_images' => 'id'
510          ),
511        'AND'
512        ).'
513  GROUP BY i.id
514  ORDER BY '. DB_RANDOM_FUNCTION .'()
515  LIMIT '. $comm['nb_images'] .'
516;';
517      $pictures = hash_from_query($query, 'id');
518
519      // switch back to current user
520      $user = $user_save;
521      unset($user_save);
522
523      $share_key = array('share_key'=>'mail-' . substr(sha1($this->data['id'].$conf['secret_key']), 0, 11));
524
525      $tpl_vars = array(
526        'COL_URL' => $this->addShare($share_key, false),
527        'PARAMS' => $comm,
528        'derivative_params' => ImageStdParams::get_by_type(IMG_SQUARE),
529        );
530
531      // pictures infos
532      set_make_full_url();
533
534      foreach ($pictures as $row)
535      {
536        $name = render_element_name($row);
537
538        $tpl_vars['THUMBNAILS'][] = array(
539          'TN_ALT' => htmlspecialchars(strip_tags($name)),
540          'NAME' =>   $name,
541          'URL' =>    make_picture_url(array('image_id' => $row['id'])),
542          'THUMB' =>  DerivativeImage::url(IMG_SQUARE, $row),
543          );
544      }
545
546      unset_make_full_url();
547
548      $result = pwg_mail(
549        array(
550          'name' => $comm['recipient_name'],
551          'email' => $comm['recipient_email'],
552          ),
553        array(
554          'subject' => '['.$conf['gallery_title'].'] '.l10n('A photo collection by %s', $comm['sender_name']),
555          'mail_title' => $this->getParam('name'),
556          'mail_subtitle' => l10n('by %s', $comm['sender_name']),
557          'content_format' => 'text/html',
558          'from' => array(
559            'name' => $comm['sender_name'],
560            'email' => $comm['sender_email'],
561            )
562          ),
563        array(
564          'filename' => 'mail',
565          'dirname' => realpath(USER_COLLEC_PATH . 'template'),
566          'assign' => $tpl_vars,
567          )
568        );
569
570      if ($result == false)
571      {
572        $errors[] = l10n('Error while sending e-mail');
573      }
574      else
575      {
576        return true;
577      }
578    }
579
580    return $errors;
581  }
582
583  /**
584   * Generate a listing of the collection
585   *
586   * @param string[] $fields
587   * @return string
588   */
589  function serialize($params)
590  {
591    $fields = array_intersect($fields, array('id','file','name','url','path','date_creation','collection_add_date','filesize','width','height'));
592
593    $content = null;
594
595    // get images infos
596    $query = '
597SELECT
598    id,
599    file,
600    name,
601    path,
602    date_creation,
603    filesize,
604    width,
605    height,
606    add_date AS collection_add_date
607  FROM '.IMAGES_TABLE.'
608    JOIN '.COLLECTION_IMAGES_TABLE.' ON id = image_id
609  WHERE col_id = '.$this->data['id'].'
610  ORDER BY id
611;';
612    $pictures = hash_from_query($query, 'id');
613
614    if (count($pictures))
615    {
616      // generate csv
617      set_make_full_url();
618      $root_url = get_root_url();
619
620      $fp = fopen('php://temp', 'r+');
621      fputcsv($fp, $fields);
622
623      foreach ($pictures as $row)
624      {
625        $element = array();
626        foreach ($fields as $field)
627        {
628          switch ($field)
629          {
630          case 'name':
631            $element[] = render_element_name($row);
632            break;
633          case 'url':
634            $element[] = make_picture_url(array('image_id'=>$row['id'], 'image_file'=>$row['file']));
635            break;
636          case 'path':
637            $element[] = $root_url.ltrim($row['path'], './');
638            break;
639          default:
640            $element[] = $row[$field];
641            break;
642          }
643        }
644        if (!empty($element))
645        {
646          fputcsv($fp, $element);
647        }
648      }
649
650      rewind($fp);
651      $content = stream_get_contents($fp);
652      fclose($fp);
653
654      unset_make_full_url();
655    }
656
657    return $content;
658  }
659
660  /**
661   * Delete the collection
662   */
663  function delete()
664  {
665    $this->clearImages();
666    pwg_query('DELETE FROM '.COLLECTIONS_TABLE.' WHERE id = '.$this->data['id'].';');
667  }
668}
Note: See TracBrowser for help on using the repository browser.