<?php
/**
 * File containing the ezcMailMultipart class.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 * @package Mail
 * @version //autogen//
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

/**
 * Abstract base class for all multipart types.
 *
 * This class provides writing functionality that is common for all multipart
 * types. Multiparts will be written to the mail in the order that they are set
 * to the $parts variable.
 *
 * @property string $boundary
 *           The boundary string to use between parts. This string is
 *           automatically generated and should only be changed for special
 *           requirements.
 * @property string $noMimeMessage
 *           Message to display to non-MIME capable email clients. The default
 *           value is stored in the constant {@link self::DEFAULT_NO_MIME_MESSAGE}.
 *
 * @package Mail
 * @version //autogen//
 */
abstract class ezcMailMultipart extends ezcMailPart
{
    /**
     * Default message displayed to non-MIME capable email clients.
     */
    const DEFAULT_NO_MIME_MESSAGE = "This message is in MIME format. Since your mail reader does not understand\r\nthis format, some or all of this message may not be legible.";

    /**
     * An array holding the parts of this multipart.
     *
     * @var array(ezcMailPart)
     */
    protected $parts = array();

    /**
     * The counter is unique between all multipart types and is used to
     * generate unique boundary strings.
     *
     * @var int
     */
    private static $counter = 0;

    /**
     * Constructs a new ezcMailMultipart with the parts $parts.
     *
     * Subclasses typically accept an arbitrary number of parts in the
     * constructor and pass them along using func_get_args().
     *
     * $parts should be of the format array(array(ezcMailPart)|ezcMailPart)
     *
     * Subclasses must call this method in the constructor.
     * @param array $parts
     */
    public function __construct( array $parts )
    {
        parent::__construct();

        $this->noMimeMessage = self::DEFAULT_NO_MIME_MESSAGE;
        $this->boundary = $this->generateBoundary();
        $this->setHeader( "Content-Type", 'multipart/' . $this->multipartType() . '; '
                                           . 'boundary="' . $this->boundary . '"' );
        foreach ( $parts as $part )
        {
            if ( $part instanceof ezcMailPart  )
            {
                $this->parts[] = $part;
            }
            elseif ( is_array( $part ) ) // add each and everyone of the parts in the array
            {
                foreach ( $part as $array_part )
                {
                    if ( $array_part instanceof ezcMailPart )
                    {
                        $this->parts[] = $array_part;;
                    }
                }
            }
        }
    }

    /**
     * Sets the property $name to $value.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the property does not exist.
     * @param string $name
     * @param mixed $value
     * @ignore
     */
    public function __set( $name, $value )
    {
        switch ( $name )
        {
            case 'boundary':
                $this->properties[$name] = $value;
                $this->setHeader( 'Content-Type', 'multipart/' . $this->multipartType() . '; ' .
                                  'boundary="' . $this->boundary . '"' );
                break;

            case 'noMimeMessage':
                $this->properties[$name] = $value;
                break;

            default:
                return parent::__set( $name, $value );
                break;
        }
    }

    /**
     * Returns the property $name.
     *
     * @throws ezcBasePropertyNotFoundException
     *         if the property does not exist.
     * @param string $name
     * @return mixed
     * @ignore
     */
    public function __get( $name )
    {
        switch ( $name )
        {
            case 'boundary':
            case 'noMimeMessage':
                return $this->properties[$name];
                break;

            default:
                return parent::__get( $name );
                break;
        }
    }

    /**
     * Returns true if the property $name is set, otherwise false.
     *
     * @param string $name
     * @return bool
     * @ignore
     */
    public function __isset( $name )
    {
        switch ( $name )
        {
            case 'boundary':
            case 'noMimeMessage':
                return isset( $this->properties[$name] );

            default:
                return parent::__isset( $name );
        }
    }

    /**
     * Returns the generated body for all multipart types.
     *
     * @return string
     */
    public function generateBody()
    {
        $data = $this->noMimeMessage . ezcMailTools::lineBreak();
        foreach ( $this->parts as $part )
        {
            $data .= ezcMailTools::lineBreak() . '--' . $this->boundary . ezcMailTools::lineBreak();
            $data .= $part->generate();
        }
        $data .= ezcMailTools::lineBreak() . '--' . $this->boundary . '--';
        return $data;
    }

    /**
     * Returns the type of multipart.
     *
     * @return string
     */
    abstract public function multipartType();

    /**
     * Returns a unique boundary string.
     *
     * @return string
     */
    protected static function generateBoundary()
    {
        return date( "YmdGHjs" ) . ':' . getmypid() . ':' . self::$counter++;
    }
}
?>
