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
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2009-03-07
37 namespace Galette\Core
;
40 use Galette\Entity\Adherent
;
49 * @author Johan Cwiklinski <johan@x-tnd.be>
50 * @copyright 2009-2014 The Galette Team
51 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
52 * @link http://galette.tuxfamily.org
53 * @since Available since 0.7dev - 2009-03-07
55 class Mailing
extends GaletteMail
58 const STEP_PREVIEW
= 1;
62 const MIME_HTML
= 'text/html';
63 const MIME_TEXT
= 'text/plain';
64 const MIME_DEFAULT
= self
::MIME_TEXT
;
68 private $unreachables = array();
69 private $mrecipients = array();
70 private $current_step;
80 * @param Preferences $preferences Preferences instance
81 * @param array $members An array of members
82 * @param int $id Identifier, defaults to null
84 public function __construct(Preferences
$preferences, $members, $id = null)
86 parent
::__construct($preferences);
90 $this->generateNewId();
92 $this->current_step
= self
::STEP_START
;
93 $this->mime_type
= self
::MIME_DEFAULT
;
94 /** TODO: add a preference that propose default mime-type to use,
96 if ($members !== null) {
97 //Check which members have a valid email address and which have not
98 $this->setRecipients($members);
100 $this->loadAttachments();
104 * Generate new mailing id and temporary path
108 private function generateNewId()
112 $pass = new Password($zdb);
113 $this->id
= $pass->makeRandomPassword(30);
114 $this->generateTmpPath($this->id
);
118 * Generate temporary path
120 * @param string $id Random id, defautls to null
124 private function generateTmpPath($id = null)
129 $pass = new Password($zdb);
130 $id = $pass->makeRandomPassword(30);
132 $this->tmp_path
= GALETTE_ATTACHMENTS_PATH
. '/' . $id;
136 * Load mailing attachments
140 private function loadAttachments()
144 isset($this->tmp_path
)
145 && trim($this->tmp_path
) !== ''
147 $dir = $this->tmp_path
;
149 $dir = GALETTE_ATTACHMENTS_PATH
. $this->id
. '/';
152 $files = glob($dir . '*.*');
153 foreach ($files as $file) {
155 $f->setFileName(str_replace($dir, '', $file));
156 $this->attachments
[] = $f;
161 * Loads a mailing from history
163 * @param ResultSet $rs Mailing entry
164 * @param boolean $new True if we create a 'new' mailing,
165 * false otherwise (from preview for example)
169 public function loadFromHistory($rs, $new = true)
173 $orig_recipients = unserialize($rs->mailing_recipients
);
175 $_recipients = array();
176 $mdeps = ['parent' => true];
177 foreach ($orig_recipients as $k => $v) {
178 $m = new Adherent($zdb, $k, $mdeps);
181 $this->setRecipients($_recipients);
182 $this->subject
= $rs->mailing_subject
;
183 $this->message
= $rs->mailing_body
;
184 if ($rs->mailing_sender_name
!== null ||
$rs->mailing_sender_address
!== null) {
186 $rs->mailing_sender_name
,
187 $rs->mailing_sender_address
190 //if mailing has already been sent, generate a new id and copy attachments
191 if ($rs->mailing_sent
&& $new) {
192 $this->generateNewId();
193 $this->copyAttachments($rs->mailing_id
);
195 $this->tmp_path
= null;
196 $this->id
= $rs->mailing_id
;
197 if (!$this->attachments
) {
198 $this->loadAttachments();
200 $this->history_id
= $rs->mailing_id
;
205 * Copy attachments from another mailing
207 * @param int $id Original mailing id
211 private function copyAttachments($id)
213 $source_dir = GALETTE_ATTACHMENTS_PATH
. $id . '/';
214 $dest_dir = GALETTE_ATTACHMENTS_PATH
. $this->id
. '/';
216 if (file_exists($source_dir)) {
217 if (file_exists($dest_dir)) {
218 throw new \
RuntimeException(
222 'Attachments directory already exists for mailing %s!'
228 //copy attachments from source mailing and populate attachments
229 $this->attachments
= array();
230 $files = glob($source_dir . '*.*');
231 foreach ($files as $file) {
232 $f = new File($source_dir);
233 $f->setFileName(str_replace($source_dir, '', $file));
234 $f->copyTo($dest_dir);
235 $this->attachments
[] = $f;
240 'No attachments in source directory',
247 * Apply final header to email and send it :-)
249 * @return GaletteMail::MAIL_ERROR|GaletteMail::MAIL_SENT
251 public function send()
254 foreach ($this->mrecipients
as $member) {
255 $email = $member->getEmail();
256 $m[$email] = $member->sname
;
258 parent
::setRecipients($m);
259 return parent
::send();
263 * Set mailing recipients
265 * @param array $members Array of Adherent objects
269 public function setRecipients($members)
272 $this->mrecipients
= array();
273 $this->unreachables
= array();
275 foreach ($members as $member) {
276 $email = $member->getEmail();
278 if (trim($email) != '' && self
::isValidEmail($email)) {
279 if (!in_array($member, $this->mrecipients
)) {
280 $this->mrecipients
[] = $member;
282 $m[$email] = $member->sname
;
284 if (!in_array($member, $this->unreachables
)) {
285 $this->unreachables
[] = $member;
289 parent
::setRecipients($m);
293 * Store maling attachments
295 * @param array $files Array of uploaded files to store
297 * @return true|int error code
299 public function store($files)
301 if ($this->tmp_path
=== null) {
302 $this->generateTmpPath();
305 if (!file_exists($this->tmp_path
)) {
306 //directory does not exists, create it
307 mkdir($this->tmp_path
);
310 if (!is_dir($this->tmp_path
)) {
311 throw new \
RuntimeException(
312 $this->tmp_path
. ' should be a directory!'
317 $attachment = new File($this->tmp_path
);
318 $res = $attachment->store($files);
322 $this->attachments
[] = $attachment;
329 * Move attachments with final id once mailing has been stored
331 * @param int $id Mailing history id
335 public function moveAttachments($id)
338 isset($this->tmp_path
)
339 && trim($this->tmp_path
) !== ''
340 && count($this->attachments
) > 0
342 foreach ($this->attachments
as &$attachment) {
343 $old_path = $attachment->getDestDir() . $attachment->getFileName();
344 $new_path = GALETTE_ATTACHMENTS_PATH
. $this->id
. '/' .
345 $attachment->getFileName();
346 if (!file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
347 mkdir(GALETTE_ATTACHMENTS_PATH
. $this->id
);
349 $moved = rename($old_path, $new_path);
351 $attachment->setDestDir(GALETTE_ATTACHMENTS_PATH
);
354 rmdir($this->tmp_path
);
355 $this->tmp_path
= null;
360 * Remove specified attachment
362 * @param string $name Filename
366 public function removeAttachment($name)
370 isset($this->tmp_path
)
371 && trim($this->tmp_path
) !== ''
372 && file_exists($this->tmp_path
)
374 $to_remove = $this->tmp_path
;
375 } elseif (file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
376 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->id
;
379 if ($to_remove !== null) {
380 $to_remove .= '/' . $name;
382 if (!$this->attachments
) {
383 $this->loadAttachments();
386 if (file_exists($to_remove)) {
388 foreach ($this->attachments
as $att) {
389 if ($att->getFileName() == $name) {
390 unset($this->attachments
[$i]);
401 'File %file does not exists and cannot be removed!'
407 throw new \
RuntimeException(
408 'Unable to get attachments path!'
414 * Remove mailing attachments
416 * @param boolean $temp Remove only tmporary attachments,
417 * to avoid history breaking
421 public function removeAttachments($temp = false)
425 isset($this->tmp_path
)
426 && trim($this->tmp_path
) !== ''
427 && file_exists($this->tmp_path
)
429 $to_remove = $this->tmp_path
;
430 } elseif (file_exists(GALETTE_ATTACHMENTS_PATH
. $this->id
)) {
431 if ($temp === true) {
434 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->id
;
437 if ($to_remove !== null) {
438 $rdi = new \
RecursiveDirectoryIterator(
440 \FilesystemIterator
::SKIP_DOTS
442 $contents = new \
RecursiveIteratorIterator(
444 \RecursiveIteratorIterator
::CHILD_FIRST
446 foreach ($contents as $path) {
447 if ($path->isFile()) {
448 unlink($path->getPathname());
450 rmdir($path->getPathname());
458 * Return textual error message
460 * @param int $code The error code
462 * @return string Localized message
464 public function getAttachmentErrorMessage($code)
466 $f = new File($this->tmp_path
);
467 return $f->getErrorMessage($code);
471 * Does mailing already exists in history?
475 public function existsInHistory()
477 return isset($this->history_id
);
481 * Global getter method
483 * @param string $name name of the property we want to retrive
485 * @return false|object the called property
487 public function __get($name)
489 $forbidden = array('ordered');
490 if (!in_array($name, $forbidden)) {
493 return $this->cleanedHtml();
496 return $this->current_step
;
499 return $this->getSubject();
502 return $this->getMessage();
504 case 'wrapped_message':
505 return $this->getWrappedMessage();
508 return $this->isHTML();
512 return $this->getPhpMailer();
515 return $this->getErrors();
518 return $this->mrecipients
;
521 if (isset($this->tmp_path
) && trim($this->tmp_path
) !== '') {
522 return $this->tmp_path
;
529 return $this->attachments
;
532 return $this->getSenderName();
534 case 'sender_address':
535 return $this->getSenderAddress();
539 '[' . get_class($this) . 'Trying to get ' . $name,
547 '[' . get_class($this) . 'Unable to get ' . $name,
555 * Global setter method
557 * @param string $name name of the property we want to assign a value to
558 * @param object $value a relevant value for the property
562 public function __set($name, $value)
566 $this->setSubject($value);
569 $this->setMessage($value);
572 if (is_bool($value)) {
573 $this->isHTML($value);
576 '[' . get_class($this) . '] Value for field `' . $name .
577 '` should be boolean - (' . gettype($value) . ')' .
586 && ($value == self
::STEP_START
587 ||
$value == self
::STEP_PREVIEW
588 ||
$value == self
::STEP_SEND
589 ||
$value == self
::STEP_SENT
)
591 $this->current_step
= (int)$value;
594 '[' . get_class($this) . '] Value for field `' . $name .
595 '` should be integer and know - (' . gettype($value) . ')' .
606 '[' . get_class($this) . '] Unable to set proprety `' . $name . '`',