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;
70 private $_mrecipients;
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()
109 $pass = new Password();
110 $this->_id
= $pass->makeRandomPassword(30);
111 $this->_generateTmpPath($this->_id
);
115 * Generate temporary path
117 * @param string $id Random id, defautls to null
121 private function _generateTmpPath($id = null)
123 if ( $id === null ) {
124 $pass = new Password();
125 $id = $pass->makeRandomPassword(30);
127 $this->_tmp_path
= GALETTE_ATTACHMENTS_PATH
. '/' . $id;
131 * Load mailing attachments
135 private function _loadAttachments()
138 if ( isset($this->_tmp_path
)
139 && trim($this->_tmp_path
) !== ''
141 $dir = $this->_tmp_path
;
143 $dir = GALETTE_ATTACHMENTS_PATH
. $this->_id
. '/';
146 $files = glob($dir . '*.*');
147 foreach ( $files as $file ) {
149 $f->setFileName(str_replace($dir, '', $file));
150 $this->attachments
[] = $f;
155 * Loads a mailing from history
157 * @param ResultSet $rs Mailing entry
158 * @param boolean $new True if we create a 'new' mailing,
159 * false otherwise (from preview for example)
163 public function loadFromHistory($rs, $new = true)
165 $orig_recipients = unserialize($rs->mailing_recipients
);
167 $_recipients = array();
168 foreach ( $orig_recipients as $k=>$v ) {
169 $m = new Adherent($k);
172 $this->setRecipients($_recipients);
173 $this->subject
= $rs->mailing_subject
;
174 $this->message
= $rs->mailing_body
;
175 //if mailing has already been sent, generate a new id and copy attachments
176 if ( $rs->mailing_sent
&& $new ) {
177 $this->_generateNewId();
178 $this->_copyAttachments($rs->mailing_id
);
180 $this->_tmp_path
= null;
181 $this->_id
= $rs->mailing_id
;
182 if ( !$this->attachments
) {
183 $this->_loadAttachments();
185 $this->_history_id
= $rs->mailing_id
;
190 * Copy attachments from another mailing
192 * @param int $id Original mailing id
196 private function _copyAttachments($id)
198 $source_dir = GALETTE_ATTACHMENTS_PATH
. $id . '/';
199 $dest_dir = GALETTE_ATTACHMENTS_PATH
. $this->_id
. '/';
201 if ( file_exists($source_dir) ) {
202 if ( file_exists($dest_dir) ) {
203 throw new \
RuntimeException(
207 'Attachments directory already exists for mailing %s!'
213 //copy attachments from source mailing and populate attachments
214 $this->attachments
= array();
215 $files = glob($source_dir . '*.*');
216 foreach ( $files as $file ) {
217 $f = new File($source_dir);
218 $f->setFileName(str_replace($source_dir, '', $file));
219 $f->copyTo($dest_dir);
220 $this->attachments
[] = $f;
225 'No attachments in source directory',
232 * Apply final header to mail and send it :-)
234 * @return GaletteMail::MAIL_ERROR|GaletteMail::MAIL_SENT
236 public function send()
239 foreach ( $this->_mrecipients
as $member ) {
240 $m[$member->email
] = $member->sname
;
242 parent
::setRecipients($m);
243 return parent
::send();
247 * Set mailing recipients
249 * @param array $members Array of Adherent objects
253 public function setRecipients($members)
256 $this->_mrecipients
= array();
257 $this->_unreachables
= array();
259 foreach ($members as $member) {
260 $email = $member->email
;
262 //if member mail is missing but there is a parent,
263 //take the parent email.
264 if (!$email && $member->hasParent()) {
265 $email = $member->parent
->email
;
268 if ( trim($email) != '' && self
::isValidEmail($email) ) {
269 if ( !in_array($member, $this->_mrecipients
) ) {
270 $this->_mrecipients
[] = $member;
272 $m[$email] = $member->sname
;
274 if ( !in_array($member, $this->_unreachables
) ) {
275 $this->_unreachables
[] = $member;
279 parent
::setRecipients($m);
283 * Store maling attachments
285 * @param array $files Array of uploaded files to store
287 * @return true|int error code
289 public function store($files)
291 if ( $this->_tmp_path
=== null ) {
292 $this->_generateTmpPath();
295 if ( !file_exists($this->_tmp_path
) ) {
296 //directory does not exists, create it
297 mkdir($this->_tmp_path
);
300 if ( !is_dir($this->_tmp_path
) ) {
301 throw new \
RuntimeException(
302 $this->_tmp_path
. ' should be a directory!'
307 $attachment = new File($this->_tmp_path
);
308 $res = $attachment->store($files);
312 $this->attachments
[] = $attachment;
319 * Move attachments with final id once mailing has been stored
321 * @param int $id Mailing history id
325 public function moveAttachments($id)
327 if ( isset($this->_tmp_path
)
328 && trim($this->_tmp_path
) !== ''
329 && count($this->attachments
) > 0
331 foreach ( $this->attachments
as &$attachment ) {
332 $old_path = $attachment->getDestDir() . $attachment->getFileName();
333 $new_path = GALETTE_ATTACHMENTS_PATH
. $this->_id
.'/' .
334 $attachment->getFileName();
335 if ( !file_exists(GALETTE_ATTACHMENTS_PATH
. $this->_id
) ) {
336 mkdir(GALETTE_ATTACHMENTS_PATH
. $this->_id
);
338 $moved = rename($old_path, $new_path);
340 $attachment->setDestDir(GALETTE_ATTACHMENTS_PATH
);
343 rmdir($this->_tmp_path
);
344 $this->_tmp_path
= null;
349 * Remove specified attachment
351 * @param string $name Filename
355 public function removeAttachment($name)
358 if ( isset($this->_tmp_path
)
359 && trim($this->_tmp_path
) !== ''
360 && file_exists($this->_tmp_path
)
362 $to_remove = $this->_tmp_path
;
363 } else if ( file_exists(GALETTE_ATTACHMENTS_PATH
. $this->_id
) ) {
364 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->_id
;
367 if ( $to_remove !== null ) {
368 $to_remove .= '/' . $name;
370 if ( !$this->attachments
) {
371 $this->_loadAttachments();
374 if ( file_exists($to_remove) ) {
376 foreach ( $this->attachments
as $att ) {
377 if ( $att->getFileName() == $name ) {
378 unset($this->attachments
[$i]);
389 'File %file does not exists and cannot be removed!'
395 throw new \
RuntimeException(
396 'Unable to get attachments path!'
402 * Remove mailing attachments
404 * @param boolean $temp Remove only tmporary attachments,
405 * to avoid history breaking
409 public function removeAttachments($temp = false)
412 if ( isset($this->_tmp_path
)
413 && trim($this->_tmp_path
) !== ''
414 && file_exists($this->_tmp_path
)
416 $to_remove = $this->_tmp_path
;
417 } else if ( file_exists(GALETTE_ATTACHMENTS_PATH
. $this->_id
) ) {
418 if ( $temp === true ) {
421 $to_remove = GALETTE_ATTACHMENTS_PATH
. $this->_id
;
424 if ( $to_remove !== null ) {
425 $rdi = new \
RecursiveDirectoryIterator(
427 \FilesystemIterator
::SKIP_DOTS
429 $contents = new \
RecursiveIteratorIterator(
431 \RecursiveIteratorIterator
::CHILD_FIRST
433 foreach ( $contents as $path) {
434 if ( $path->isFile() ) {
435 unlink($path->getPathname());
437 rmdir($path->getPathname());
445 * Return textual error message
447 * @param int $code The error code
449 * @return string Localized message
451 public function getAttachmentErrorMessage($code)
453 $f = new File($this->_tmp_path
);
454 return $f->getErrorMessage($code);
458 * Does mailing already exists in history?
462 public function existsInHistory()
464 return isset($this->_history_id
);
468 * Global getter method
470 * @param string $name name of the property we want to retrive
472 * @return false|object the called property
474 public function __get($name)
476 $forbidden = array('ordered');
477 if ( !in_array($name, $forbidden) ) {
480 return $this->cleanedHtml();
483 return $this->current_step
;
486 return $this->getSubject();
489 return $this->getMessage();
491 case 'wrapped_message':
492 return $this->getWrappedMessage();
495 return $this->isHTML();
499 return $this->getPhpMailer();
502 return $this->getErrors();
505 return $this->_mrecipients
;
508 if ( isset($this->_tmp_path
) && trim($this->_tmp_path
) !== '') {
509 return $this->_tmp_path
;
516 return $this->attachments
;
519 $rname = '_' . $name;
521 '[' . get_class($this) . 'Trying to get ' . $name .
522 ' renamed: ' . $rname,
525 return $this->$rname;
530 '[' . get_class($this) . 'Unable to get ' . $name .
531 ' renamed: ' . $rname,
539 * Global setter method
541 * @param string $name name of the property we want to assign a value to
542 * @param object $value a relevant value for the property
546 public function __set($name, $value)
548 $rname = '_' . $name;
552 $this->setSubject($value);
555 $this->setMessage($value);
558 if ( is_bool($value) ) {
559 $this->isHTML($value);
562 '[' . get_class($this) . '] Value for field `' . $name .
563 '` should be boolean - (' . gettype($value) . ')' .
571 && ( $value == self
::STEP_START
572 ||
$value == self
::STEP_PREVIEW
573 ||
$value == self
::STEP_SEND
574 ||
$value == self
::STEP_SENT
)
576 $this->_current_step
= (int)$value;
579 '[' . get_class($this) . '] Value for field `' . $name .
580 '` should be integer and know - (' . gettype($value) . ')' .
591 '[' . get_class($this) . '] Unable to set proprety `' . $name . '`',