3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2009-2014 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2009-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.7dev - 2009-03-07
38 namespace Galette\Core
;
41 use Galette\Entity\Adherent
;
50 * @author Johan Cwiklinski <johan@x-tnd.be>
51 * @copyright 2009-2014 The Galette Team
52 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
53 * @link http://galette.tuxfamily.org
54 * @since Available since 0.7dev - 2009-03-07
56 class Mailing
extends GaletteMail
59 const STEP_PREVIEW
= 1;
63 const MIME_HTML
= 'text/html';
64 const MIME_TEXT
= 'text/plain';
65 const MIME_DEFAULT
= self
::MIME_TEXT
;
69 private $unreachables;
71 private $current_step;
81 * @param array $members An array of members
82 * @param int $id Identifier, defaults to null
84 public function __construct($members, $id = null)
89 $this->generateNewId();
91 $this->current_step
= self
::STEP_START
;
92 $this->mime_type
= self
::MIME_DEFAULT
;
93 /** TODO: add a preference that propose default mime-type to use,
95 if ($members !== null) {
96 //Check which members have a valid email address and which have not
97 $this->setRecipients($members);
99 $this->loadAttachments();
103 * Generate new mailing id and temporary path
107 private function generateNewId()
111 $pass = new Password($zdb);
112 $this->id
= $pass->makeRandomPassword(30);
113 $this->generateTmpPath($this->id
);
117 * Generate temporary path
119 * @param string $id Random id, defautls to null
123 private function generateTmpPath($id = null)
128 $pass = new Password($zdb);
129 $id = $pass->makeRandomPassword(30);
131 $this->tmp_path
= GALETTE_ATTACHMENTS_PATH
. '/' . $id;
135 * Load mailing attachments
139 private function loadAttachments()
142 if (isset($this->tmp_path
)
143 && trim($this->tmp_path
) !== ''
145 $dir = $this->tmp_path
;
147 $dir = GALETTE_ATTACHMENTS_PATH
. $this->id
. '/';
150 $files = glob($dir . '*.*');
151 foreach ($files as $file) {
153 $f->setFileName(str_replace($dir, '', $file));
154 $this->attachments
[] = $f;
159 * Loads a mailing from history
161 * @param ResultSet $rs Mailing entry
162 * @param boolean $new True if we create a 'new' mailing,
163 * false otherwise (from preview for example)
167 public function loadFromHistory($rs, $new = true)
171 $orig_recipients = unserialize($rs->mailing_recipients
);
173 $_recipients = array();
174 $mdeps = ['parent' => true];
175 foreach ($orig_recipients as $k => $v) {
176 $m = new Adherent($zdb, $k, $mdeps);
179 $this->setRecipients($_recipients);
180 $this->subject
= $rs->mailing_subject
;
181 $this->message
= $rs->mailing_body
;
182 //if mailing has already been sent, generate a new id and copy attachments
183 if ($rs->mailing_sent
&& $new) {
184 $this->generateNewId();
185 $this->copyAttachments($rs->mailing_id
);
187 $this->tmp_path
= null;
188 $this->id
= $rs->mailing_id
;
189 if (!$this->attachments
) {
190 $this->loadAttachments();
192 $this->history_id
= $rs->mailing_id
;
197 * Copy attachments from another mailing
199 * @param int $id Original mailing id
203 private function copyAttachments($id)
205 $source_dir = GALETTE_ATTACHMENTS_PATH
. $id . '/';
206 $dest_dir = GALETTE_ATTACHMENTS_PATH
. $this->id
. '/';
208 if (file_exists($source_dir)) {
209 if (file_exists($dest_dir)) {
210 throw new \
RuntimeException(
214 'Attachments directory already exists for mailing %s!'
220 //copy attachments from source mailing and populate attachments
221 $this->attachments
= array();
222 $files = glob($source_dir . '*.*');
223 foreach ($files as $file) {
224 $f = new File($source_dir);
225 $f->setFileName(str_replace($source_dir, '', $file));
226 $f->copyTo($dest_dir);
227 $this->attachments
[] = $f;
232 'No attachments in source directory',
239 * Apply final header to mail and send it :-)
241 * @return GaletteMail::MAIL_ERROR|GaletteMail::MAIL_SENT
243 public function send()
246 foreach ($this->mrecipients
as $member) {
247 $email = $member->getEmail();
248 $m[$email] = $member->sname
;
250 parent
::setRecipients($m);
251 return parent
::send();
255 * Set mailing recipients
257 * @param array $members Array of Adherent objects
261 public function setRecipients($members)
264 $this->mrecipients
= array();
265 $this->unreachables
= array();
267 foreach ($members as $member) {
268 $email = $member->getEmail();
270 if (trim($email) != '' && self
::isValidEmail($email)) {
271 if (!in_array($member, $this->mrecipients
)) {
272 $this->mrecipients
[] = $member;
274 $m[$email] = $member->sname
;
276 if (!in_array($member, $this->unreachables
)) {
277 $this->unreachables
[] = $member;
281 parent
::setRecipients($m);
285 * Store maling attachments
287 * @param array $files Array of uploaded files to store
289 * @return true|int error code
291 public function store($files)
293 if ($this->tmp_path
=== null) {
294 $this->generateTmpPath();
297 if (!file_exists($this->tmp_path
)) {
298 //directory does not exists, create it
299 mkdir($this->tmp_path
);
302 if (!is_dir($this->tmp_path
)) {
303 throw new \
RuntimeException(
304 $this->tmp_path
. ' should be a directory!'
309 $attachment = new File($this->tmp_path
);
310 $res = $attachment->store($files);
314 $this->attachments
[] = $attachment;
321 * Move attachments with final id once mailing has been stored
323 * @param int $id Mailing history id
327 public function moveAttachments($id)
329 if (isset($this->tmp_path
)
330 && trim($this->tmp_path
) !== ''
331 && count($this->attachments
) > 0
333 foreach ($this->attachments
as &$attachment) {
334 $old_path = $attachment->getDestDir() . $attachment->getFileName();
335 $new_path = GALETTE_ATTACHMENTS_PATH
. $this->id
.'/' .
336 $attachment->getFileName();
337 if (!file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
338 mkdir(GALETTE_ATTACHMENTS_PATH
. $this->id
);
340 $moved = rename($old_path, $new_path);
342 $attachment->setDestDir(GALETTE_ATTACHMENTS_PATH
);
345 rmdir($this->tmp_path
);
346 $this->tmp_path
= null;
351 * Remove specified attachment
353 * @param string $name Filename
357 public function removeAttachment($name)
360 if (isset($this->tmp_path
)
361 && trim($this->tmp_path
) !== ''
362 && file_exists($this->tmp_path
)
364 $to_remove = $this->tmp_path
;
365 } elseif (file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
366 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->id
;
369 if ($to_remove !== null) {
370 $to_remove .= '/' . $name;
372 if (!$this->attachments
) {
373 $this->loadAttachments();
376 if (file_exists($to_remove)) {
378 foreach ($this->attachments
as $att) {
379 if ($att->getFileName() == $name) {
380 unset($this->attachments
[$i]);
391 'File %file does not exists and cannot be removed!'
397 throw new \
RuntimeException(
398 'Unable to get attachments path!'
404 * Remove mailing attachments
406 * @param boolean $temp Remove only tmporary attachments,
407 * to avoid history breaking
411 public function removeAttachments($temp = false)
414 if (isset($this->tmp_path
)
415 && trim($this->tmp_path
) !== ''
416 && file_exists($this->tmp_path
)
418 $to_remove = $this->tmp_path
;
419 } elseif (file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
420 if ($temp === true) {
423 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->id
;
426 if ($to_remove !== null) {
427 $rdi = new \
RecursiveDirectoryIterator(
429 \FilesystemIterator
::SKIP_DOTS
431 $contents = new \
RecursiveIteratorIterator(
433 \RecursiveIteratorIterator
::CHILD_FIRST
435 foreach ($contents as $path) {
436 if ($path->isFile()) {
437 unlink($path->getPathname());
439 rmdir($path->getPathname());
447 * Return textual error message
449 * @param int $code The error code
451 * @return string Localized message
453 public function getAttachmentErrorMessage($code)
455 $f = new File($this->tmp_path
);
456 return $f->getErrorMessage($code);
460 * Does mailing already exists in history?
464 public function existsInHistory()
466 return isset($this->history_id
);
470 * Global getter method
472 * @param string $name name of the property we want to retrive
474 * @return false|object the called property
476 public function __get($name)
478 $forbidden = array('ordered');
479 if (!in_array($name, $forbidden)) {
482 return $this->cleanedHtml();
485 return $this->current_step
;
488 return $this->getSubject();
491 return $this->getMessage();
493 case 'wrapped_message':
494 return $this->getWrappedMessage();
497 return $this->isHTML();
501 return $this->getPhpMailer();
504 return $this->getErrors();
507 return $this->mrecipients
;
510 if (isset($this->tmp_path
) && trim($this->tmp_path
) !== '') {
511 return $this->tmp_path
;
518 return $this->attachments
;
522 '[' . get_class($this) . 'Trying to get ' . $name,
530 '[' . get_class($this) . 'Unable to get ' . $name,
538 * Global setter method
540 * @param string $name name of the property we want to assign a value to
541 * @param object $value a relevant value for the property
545 public function __set($name, $value)
549 $this->setSubject($value);
552 $this->setMessage($value);
555 if (is_bool($value)) {
556 $this->isHTML($value);
559 '[' . get_class($this) . '] Value for field `' . $name .
560 '` should be boolean - (' . gettype($value) . ')' .
568 && ( $value == self
::STEP_START
569 ||
$value == self
::STEP_PREVIEW
570 ||
$value == self
::STEP_SEND
571 ||
$value == self
::STEP_SENT
)
573 $this->current_step
= (int)$value;
576 '[' . get_class($this) . '] Value for field `' . $name .
577 '` should be integer and know - (' . gettype($value) . ')' .
588 '[' . get_class($this) . '] Unable to set proprety `' . $name . '`',