Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

  • Swift_Plugins_Logger
  • Swift_Plugins_Pop_Pop3Exception
  • Swift_Transport
  • Swift_Transport_Esmtp_Authenticator
  • Swift_Transport_EsmtpHandler
  • Swift_Transport_IoBuffer
  • Swift_Transport_MailInvoker
  • Swift_Transport_SmtpAgent
  • Swift_TransportException
  • Overview
  • Package
  • Function
  • Todo
  • Download
  1: <?php
  2: 
  3: /*
  4:  * This file is part of SwiftMailer.
  5:  * (c) 2004-2009 Chris Corbyn
  6:  *
  7:  * For the full copyright and license information, please view the LICENSE
  8:  * file that was distributed with this source code.
  9:  */
 10: 
 11: /**
 12:  * A MIME entity, in a multipart message.
 13:  * @package Swift
 14:  * @subpackage Mime
 15:  * @author Chris Corbyn
 16:  */
 17: class Swift_Mime_SimpleMimeEntity implements Swift_Mime_MimeEntity
 18: {
 19:     /** A collection of Headers for this mime entity */
 20:     private $_headers;
 21: 
 22:     /** The body as a string, or a stream */
 23:     private $_body;
 24: 
 25:     /** The encoder that encodes the body into a streamable format */
 26:     private $_encoder;
 27: 
 28:     /** The grammar to use for id validation */
 29:     private $_grammar;
 30: 
 31:     /** A mime bounary, if any is used */
 32:     private $_boundary;
 33: 
 34:     /** Mime types to be used based on the nesting level */
 35:     private $_compositeRanges = array(
 36:         'multipart/mixed' => array(self::LEVEL_TOP, self::LEVEL_MIXED),
 37:         'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
 38:         'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED)
 39:         );
 40: 
 41:     /** A set of filter rules to define what level an entity should be nested at */
 42:     private $_compoundLevelFilters = array();
 43: 
 44:     /** The nesting level of this entity */
 45:     private $_nestingLevel = self::LEVEL_ALTERNATIVE;
 46: 
 47:     /** A KeyCache instance used during encoding and streaming */
 48:     private $_cache;
 49: 
 50:     /** Direct descendants of this entity */
 51:     private $_immediateChildren = array();
 52: 
 53:     /** All descendants of this entity */
 54:     private $_children = array();
 55: 
 56:     /** The maximum line length of the body of this entity */
 57:     private $_maxLineLength = 78;
 58: 
 59:     /** The order in which alternative mime types should appear */
 60:     private $_alternativePartOrder = array(
 61:         'text/plain' => 1,
 62:         'text/html' => 2,
 63:         'multipart/related' => 3
 64:         );
 65: 
 66:     /** The CID of this entity */
 67:     private $_id;
 68: 
 69:     /** The key used for accessing the cache */
 70:     private $_cacheKey;
 71: 
 72:     protected $_userContentType;
 73: 
 74:     /**
 75:      * Create a new SimpleMimeEntity with $headers, $encoder and $cache.
 76:      * @param Swift_Mime_HeaderSet      $headers
 77:      * @param Swift_Mime_ContentEncoder $encoder
 78:      * @param Swift_KeyCache            $cache
 79:      * @param Swift_Mime_Grammar        $grammar
 80:      */
 81:     public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar)
 82:     {
 83:         $this->_cacheKey = uniqid();
 84:         $this->_cache = $cache;
 85:         $this->_headers = $headers;
 86:         $this->_grammar = $grammar;
 87:         $this->setEncoder($encoder);
 88:         $this->_headers->defineOrdering(
 89:             array('Content-Type', 'Content-Transfer-Encoding')
 90:             );
 91: 
 92:         // This array specifies that, when the entire MIME document contains
 93:         // $compoundLevel, then for each child within $level, if its Content-Type
 94:         // is $contentType then it should be treated as if it's level is
 95:         // $neededLevel instead.  I tried to write that unambiguously! :-\
 96:         // Data Structure:
 97:         // array (
 98:         //   $compoundLevel => array(
 99:         //     $level => array(
100:         //       $contentType => $neededLevel
101:         //     )
102:         //   )
103:         // )
104: 
105:         $this->_compoundLevelFilters = array(
106:             (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
107:                 self::LEVEL_ALTERNATIVE => array(
108:                     'text/plain' => self::LEVEL_ALTERNATIVE,
109:                     'text/html' => self::LEVEL_RELATED
110:                     )
111:                 )
112:             );
113: 
114:         $this->_id = $this->getRandomId();
115:     }
116: 
117:     /**
118:      * Generate a new Content-ID or Message-ID for this MIME entity.
119:      * @return string
120:      */
121:     public function generateId()
122:     {
123:         $this->setId($this->getRandomId());
124: 
125:         return $this->_id;
126:     }
127: 
128:     /**
129:      * Get the {@link Swift_Mime_HeaderSet} for this entity.
130:      * @return Swift_Mime_HeaderSet
131:      */
132:     public function getHeaders()
133:     {
134:         return $this->_headers;
135:     }
136: 
137:     /**
138:      * Get the nesting level of this entity.
139:      * @return int
140:      * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE
141:      */
142:     public function getNestingLevel()
143:     {
144:         return $this->_nestingLevel;
145:     }
146: 
147:     /**
148:      * Get the Content-type of this entity.
149:      * @return string
150:      */
151:     public function getContentType()
152:     {
153:         return $this->_getHeaderFieldModel('Content-Type');
154:     }
155: 
156:     /**
157:      * Set the Content-type of this entity.
158:      * @param  string                      $type
159:      * @return Swift_Mime_SimpleMimeEntity
160:      */
161:     public function setContentType($type)
162:     {
163:         $this->_setContentTypeInHeaders($type);
164:         // Keep track of the value so that if the content-type changes automatically
165:         // due to added child entities, it can be restored if they are later removed
166:         $this->_userContentType = $type;
167: 
168:         return $this;
169:     }
170: 
171:     /**
172:      * Get the CID of this entity.
173:      * The CID will only be present in headers if a Content-ID header is present.
174:      * @return string
175:      */
176:     public function getId()
177:     {
178:         return $this->_headers->has($this->_getIdField())
179:             ? current((array) $this->_getHeaderFieldModel($this->_getIdField()))
180:             : $this->_id;
181:     }
182: 
183:     /**
184:      * Set the CID of this entity.
185:      * @param  string                      $id
186:      * @return Swift_Mime_SimpleMimeEntity
187:      */
188:     public function setId($id)
189:     {
190:         if (!$this->_setHeaderFieldModel($this->_getIdField(), $id)) {
191:             $this->_headers->addIdHeader($this->_getIdField(), $id);
192:         }
193:         $this->_id = $id;
194: 
195:         return $this;
196:     }
197: 
198:     /**
199:      * Get the description of this entity.
200:      * This value comes from the Content-Description header if set.
201:      * @return string
202:      */
203:     public function getDescription()
204:     {
205:         return $this->_getHeaderFieldModel('Content-Description');
206:     }
207: 
208:     /**
209:      * Set the description of this entity.
210:      * This method sets a value in the Content-ID header.
211:      * @param  string                      $description
212:      * @return Swift_Mime_SimpleMimeEntity
213:      */
214:     public function setDescription($description)
215:     {
216:         if (!$this->_setHeaderFieldModel('Content-Description', $description)) {
217:             $this->_headers->addTextHeader('Content-Description', $description);
218:         }
219: 
220:         return $this;
221:     }
222: 
223:     /**
224:      * Get the maximum line length of the body of this entity.
225:      * @return int
226:      */
227:     public function getMaxLineLength()
228:     {
229:         return $this->_maxLineLength;
230:     }
231: 
232:     /**
233:      * Set the maximum line length of lines in this body.
234:      * Though not enforced by the library, lines should not exceed 1000 chars.
235:      * @param  int                         $length
236:      * @return Swift_Mime_SimpleMimeEntity
237:      */
238:     public function setMaxLineLength($length)
239:     {
240:         $this->_maxLineLength = $length;
241: 
242:         return $this;
243:     }
244: 
245:     /**
246:      * Get all children added to this entity.
247:      * @return array of Swift_Mime_Entity
248:      */
249:     public function getChildren()
250:     {
251:         return $this->_children;
252:     }
253: 
254:     /**
255:      * Set all children of this entity.
256:      * @param  array                       $children      Swiift_Mime_Entity instances
257:      * @param  int                         $compoundLevel For internal use only
258:      * @return Swift_Mime_SimpleMimeEntity
259:      */
260:     public function setChildren(array $children, $compoundLevel = null)
261:     {
262:         //TODO: Try to refactor this logic
263: 
264:         $compoundLevel = isset($compoundLevel)
265:             ? $compoundLevel
266:             : $this->_getCompoundLevel($children)
267:             ;
268: 
269:         $immediateChildren = array();
270:         $grandchildren = array();
271:         $newContentType = $this->_userContentType;
272: 
273:         foreach ($children as $child) {
274:             $level = $this->_getNeededChildLevel($child, $compoundLevel);
275:             if (empty($immediateChildren)) { //first iteration
276:                 $immediateChildren = array($child);
277:             } else {
278:                 $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
279:                 if ($nextLevel == $level) {
280:                     $immediateChildren[] = $child;
281:                 } elseif ($level < $nextLevel) {
282:                     //Re-assign immediateChildren to grandchilden
283:                     $grandchildren = array_merge($grandchildren, $immediateChildren);
284:                     //Set new children
285:                     $immediateChildren = array($child);
286:                 } else {
287:                     $grandchildren[] = $child;
288:                 }
289:             }
290:         }
291: 
292:         if (!empty($immediateChildren)) {
293:             $lowestLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
294: 
295:             //Determine which composite media type is needed to accomodate the
296:             // immediate children
297:             foreach ($this->_compositeRanges as $mediaType => $range) {
298:                 if ($lowestLevel > $range[0]
299:                     && $lowestLevel <= $range[1])
300:                 {
301:                     $newContentType = $mediaType;
302:                     break;
303:                 }
304:             }
305: 
306:             //Put any grandchildren in a subpart
307:             if (!empty($grandchildren)) {
308:                 $subentity = $this->_createChild();
309:                 $subentity->_setNestingLevel($lowestLevel);
310:                 $subentity->setChildren($grandchildren, $compoundLevel);
311:                 array_unshift($immediateChildren, $subentity);
312:             }
313:         }
314: 
315:         $this->_immediateChildren = $immediateChildren;
316:         $this->_children = $children;
317:         $this->_setContentTypeInHeaders($newContentType);
318:         $this->_fixHeaders();
319:         $this->_sortChildren();
320: 
321:         return $this;
322:     }
323: 
324:     /**
325:      * Get the body of this entity as a string.
326:      * @return string
327:      */
328:     public function getBody()
329:     {
330:         return ($this->_body instanceof Swift_OutputByteStream)
331:             ? $this->_readStream($this->_body)
332:             : $this->_body;
333:     }
334: 
335:     /**
336:      * Set the body of this entity, either as a string, or as an instance of
337:      * {@link Swift_OutputByteStream}.
338:      * @param  mixed                       $body
339:      * @param  string                      $contentType optional
340:      * @return Swift_Mime_SimpleMimeEntity
341:      */
342:     public function setBody($body, $contentType = null)
343:     {
344:         if ($body !== $this->_body) {
345:             $this->_clearCache();
346:         }
347: 
348:         $this->_body = $body;
349:         if (isset($contentType)) {
350:             $this->setContentType($contentType);
351:         }
352: 
353:         return $this;
354:     }
355: 
356:     /**
357:      * Get the encoder used for the body of this entity.
358:      * @return Swift_Mime_ContentEncoder
359:      */
360:     public function getEncoder()
361:     {
362:         return $this->_encoder;
363:     }
364: 
365:     /**
366:      * Set the encoder used for the body of this entity.
367:      * @param  Swift_Mime_ContentEncoder   $encoder
368:      * @return Swift_Mime_SimpleMimeEntity
369:      */
370:     public function setEncoder(Swift_Mime_ContentEncoder $encoder)
371:     {
372:         if ($encoder !== $this->_encoder) {
373:             $this->_clearCache();
374:         }
375: 
376:         $this->_encoder = $encoder;
377:         $this->_setEncoding($encoder->getName());
378:         $this->_notifyEncoderChanged($encoder);
379: 
380:         return $this;
381:     }
382: 
383:     /**
384:      * Get the boundary used to separate children in this entity.
385:      * @return string
386:      */
387:     public function getBoundary()
388:     {
389:         if (!isset($this->_boundary)) {
390:             $this->_boundary = '_=_swift_v4_' . time() . uniqid() . '_=_';
391:         }
392: 
393:         return $this->_boundary;
394:     }
395: 
396:     /**
397:      * Set the boundary used to separate children in this entity.
398:      * @param  string                       $boundary
399:      * @throws Swift_RfcComplianceException
400:      * @return Swift_Mime_SimpleMimeEntity
401:      */
402:     public function setBoundary($boundary)
403:     {
404:         $this->_assertValidBoundary($boundary);
405:         $this->_boundary = $boundary;
406: 
407:         return $this;
408:     }
409: 
410:     /**
411:      * Receive notification that the charset of this entity, or a parent entity
412:      * has changed.
413:      * @param string $charset
414:      */
415:     public function charsetChanged($charset)
416:     {
417:         $this->_notifyCharsetChanged($charset);
418:     }
419: 
420:     /**
421:      * Receive notification that the encoder of this entity or a parent entity
422:      * has changed.
423:      * @param Swift_Mime_ContentEncoder $encoder
424:      */
425:     public function encoderChanged(Swift_Mime_ContentEncoder $encoder)
426:     {
427:         $this->_notifyEncoderChanged($encoder);
428:     }
429: 
430:     /**
431:      * Get this entire entity as a string.
432:      * @return string
433:      */
434:     public function toString()
435:     {
436:         $string = $this->_headers->toString();
437:         if (isset($this->_body) && empty($this->_immediateChildren)) {
438:             if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
439:                 $body = $this->_cache->getString($this->_cacheKey, 'body');
440:             } else {
441:                 $body = "\r\n" . $this->_encoder->encodeString($this->getBody(), 0,
442:                     $this->getMaxLineLength()
443:                     );
444:                 $this->_cache->setString($this->_cacheKey, 'body', $body,
445:                     Swift_KeyCache::MODE_WRITE
446:                     );
447:             }
448:             $string .= $body;
449:         }
450: 
451:         if (!empty($this->_immediateChildren)) {
452:             foreach ($this->_immediateChildren as $child) {
453:                 $string .= "\r\n\r\n--" . $this->getBoundary() . "\r\n";
454:                 $string .= $child->toString();
455:             }
456:             $string .= "\r\n\r\n--" . $this->getBoundary() . "--\r\n";
457:         }
458: 
459:         return $string;
460:     }
461: 
462:     /**
463:      * Returns a string representation of this object.
464:      *
465:      * @return string
466:      *
467:      * @see toString()
468:      */
469:     public function __toString()
470:     {
471:         return $this->toString();
472:     }
473: 
474:     /**
475:      * Write this entire entity to a {@link Swift_InputByteStream}.
476:      * @param Swift_InputByteStream
477:      */
478:     public function toByteStream(Swift_InputByteStream $is)
479:     {
480:         $is->write($this->_headers->toString());
481:         $is->commit();
482: 
483:         if (empty($this->_immediateChildren)) {
484:             if (isset($this->_body)) {
485:                 if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
486:                     $this->_cache->exportToByteStream($this->_cacheKey, 'body', $is);
487:                 } else {
488:                     $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 'body');
489:                     if ($cacheIs) {
490:                         $is->bind($cacheIs);
491:                     }
492: 
493:                     $is->write("\r\n");
494: 
495:                     if ($this->_body instanceof Swift_OutputByteStream) {
496:                         $this->_body->setReadPointer(0);
497: 
498:                         $this->_encoder->encodeByteStream($this->_body, $is, 0,
499:                             $this->getMaxLineLength()
500:                             );
501:                     } else {
502:                         $is->write($this->_encoder->encodeString(
503:                             $this->getBody(), 0, $this->getMaxLineLength()
504:                             ));
505:                     }
506: 
507:                     if ($cacheIs) {
508:                         $is->unbind($cacheIs);
509:                     }
510:                 }
511:             }
512:         }
513: 
514:         if (!empty($this->_immediateChildren)) {
515:             foreach ($this->_immediateChildren as $child) {
516:                 $is->write("\r\n\r\n--" . $this->getBoundary() . "\r\n");
517:                 $child->toByteStream($is);
518:             }
519:             $is->write("\r\n\r\n--" . $this->getBoundary() . "--\r\n");
520:         }
521:     }
522: 
523:     // -- Protected methods
524: 
525:     /**
526:      * Get the name of the header that provides the ID of this entity */
527:     protected function _getIdField()
528:     {
529:         return 'Content-ID';
530:     }
531: 
532:     /**
533:      * Get the model data (usually an array or a string) for $field.
534:      */
535:     protected function _getHeaderFieldModel($field)
536:     {
537:         if ($this->_headers->has($field)) {
538:             return $this->_headers->get($field)->getFieldBodyModel();
539:         }
540:     }
541: 
542:     /**
543:      * Set the model data for $field.
544:      */
545:     protected function _setHeaderFieldModel($field, $model)
546:     {
547:         if ($this->_headers->has($field)) {
548:             $this->_headers->get($field)->setFieldBodyModel($model);
549: 
550:             return true;
551:         } else {
552:             return false;
553:         }
554:     }
555: 
556:     /**
557:      * Get the parameter value of $parameter on $field header.
558:      */
559:     protected function _getHeaderParameter($field, $parameter)
560:     {
561:         if ($this->_headers->has($field)) {
562:             return $this->_headers->get($field)->getParameter($parameter);
563:         }
564:     }
565: 
566:     /**
567:      * Set the parameter value of $parameter on $field header.
568:      */
569:     protected function _setHeaderParameter($field, $parameter, $value)
570:     {
571:         if ($this->_headers->has($field)) {
572:             $this->_headers->get($field)->setParameter($parameter, $value);
573: 
574:             return true;
575:         } else {
576:             return false;
577:         }
578:     }
579: 
580:     /**
581:      * Re-evaluate what content type and encoding should be used on this entity.
582:      */
583:     protected function _fixHeaders()
584:     {
585:         if (count($this->_immediateChildren)) {
586:             $this->_setHeaderParameter('Content-Type', 'boundary',
587:                 $this->getBoundary()
588:                 );
589:             $this->_headers->remove('Content-Transfer-Encoding');
590:         } else {
591:             $this->_setHeaderParameter('Content-Type', 'boundary', null);
592:             $this->_setEncoding($this->_encoder->getName());
593:         }
594:     }
595: 
596:     /**
597:      * Get the KeyCache used in this entity.
598:      */
599:     protected function _getCache()
600:     {
601:         return $this->_cache;
602:     }
603: 
604:     /**
605:      * Get the grammar used for validation.
606:      * @return Swift_Mime_Grammar
607:      */
608:     protected function _getGrammar()
609:     {
610:         return $this->_grammar;
611:     }
612: 
613:     /**
614:      * Empty the KeyCache for this entity.
615:      */
616:     protected function _clearCache()
617:     {
618:         $this->_cache->clearKey($this->_cacheKey, 'body');
619:     }
620: 
621:     /**
622:      * Returns a random Content-ID or Message-ID.
623:      * @return string
624:      */
625:     protected function getRandomId()
626:     {
627:         $idLeft = time() . '.' . uniqid();
628:         $idRight = !empty($_SERVER['SERVER_NAME'])
629:             ? $_SERVER['SERVER_NAME']
630:             : 'swift.generated';
631:         $id = $idLeft . '@' . $idRight;
632: 
633:         try {
634:             $this->_assertValidId($id);
635:         } catch (Swift_RfcComplianceException $e) {
636:             $id = $idLeft . '@swift.generated';
637:         }
638: 
639:         return $id;
640:     }
641: 
642:     // -- Private methods
643: 
644:     private function _readStream(Swift_OutputByteStream $os)
645:     {
646:         $string = '';
647:         while (false !== $bytes = $os->read(8192)) {
648:             $string .= $bytes;
649:         }
650: 
651:         return $string;
652:     }
653: 
654:     private function _setEncoding($encoding)
655:     {
656:         if (!$this->_setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) {
657:             $this->_headers->addTextHeader('Content-Transfer-Encoding', $encoding);
658:         }
659:     }
660: 
661:     private function _assertValidBoundary($boundary)
662:     {
663:         if (!preg_match(
664:             '/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di',
665:             $boundary))
666:         {
667:             throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.');
668:         }
669:     }
670: 
671:     private function _setContentTypeInHeaders($type)
672:     {
673:         if (!$this->_setHeaderFieldModel('Content-Type', $type)) {
674:             $this->_headers->addParameterizedHeader('Content-Type', $type);
675:         }
676:     }
677: 
678:     private function _setNestingLevel($level)
679:     {
680:         $this->_nestingLevel = $level;
681:     }
682: 
683:     private function _getCompoundLevel($children)
684:     {
685:         $level = 0;
686:         foreach ($children as $child) {
687:             $level |= $child->getNestingLevel();
688:         }
689: 
690:         return $level;
691:     }
692: 
693:     private function _getNeededChildLevel($child, $compoundLevel)
694:     {
695:         $filter = array();
696:         foreach ($this->_compoundLevelFilters as $bitmask => $rules) {
697:             if (($compoundLevel & $bitmask) === $bitmask) {
698:                 $filter = $rules + $filter;
699:             }
700:         }
701: 
702:         $realLevel = $child->getNestingLevel();
703:         $lowercaseType = strtolower($child->getContentType());
704: 
705:         if (isset($filter[$realLevel])
706:             && isset($filter[$realLevel][$lowercaseType]))
707:         {
708:             return $filter[$realLevel][$lowercaseType];
709:         } else {
710:             return $realLevel;
711:         }
712:     }
713: 
714:     private function _createChild()
715:     {
716:         return new self($this->_headers->newInstance(),
717:             $this->_encoder, $this->_cache, $this->_grammar);
718:     }
719: 
720:     private function _notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder)
721:     {
722:         foreach ($this->_immediateChildren as $child) {
723:             $child->encoderChanged($encoder);
724:         }
725:     }
726: 
727:     private function _notifyCharsetChanged($charset)
728:     {
729:         $this->_encoder->charsetChanged($charset);
730:         $this->_headers->charsetChanged($charset);
731:         foreach ($this->_immediateChildren as $child) {
732:             $child->charsetChanged($charset);
733:         }
734:     }
735: 
736:     private function _sortChildren()
737:     {
738:         $shouldSort = false;
739:         foreach ($this->_immediateChildren as $child) {
740:             //NOTE: This include alternative parts moved into a related part
741:             if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE) {
742:                 $shouldSort = true;
743:                 break;
744:             }
745:         }
746: 
747:         //Sort in order of preference, if there is one
748:         if ($shouldSort) {
749:             usort($this->_immediateChildren, array($this, '_childSortAlgorithm'));
750:         }
751:     }
752: 
753:     private function _childSortAlgorithm($a, $b)
754:     {
755:         $typePrefs = array();
756:         $types = array(
757:             strtolower($a->getContentType()),
758:             strtolower($b->getContentType())
759:             );
760:         foreach ($types as $type) {
761:             $typePrefs[] = (array_key_exists($type, $this->_alternativePartOrder))
762:                 ? $this->_alternativePartOrder[$type]
763:                 : (max($this->_alternativePartOrder) + 1);
764:         }
765: 
766:         return ($typePrefs[0] >= $typePrefs[1]) ? 1 : -1;
767:     }
768: 
769:     // -- Destructor
770: 
771:     /**
772:      * Empties it's own contents from the cache.
773:      */
774:     public function __destruct()
775:     {
776:         $this->_cache->clearAll($this->_cacheKey);
777:     }
778: 
779:     /**
780:      * Throws an Exception if the id passed does not comply with RFC 2822.
781:      * @param  string                       $id
782:      * @throws Swift_RfcComplianceException
783:      */
784:     private function _assertValidId($id)
785:     {
786:         if (!preg_match(
787:             '/^' . $this->_grammar->getDefinition('id-left') . '@' .
788:             $this->_grammar->getDefinition('id-right') . '$/D',
789:             $id
790:             ))
791:         {
792:             throw new Swift_RfcComplianceException(
793:                 'Invalid ID given <' . $id . '>'
794:                 );
795:         }
796:     }
797: }
798: 
CMS CONTENIDO 4.9.7 API documentation generated by ApiGen