<?php
/**
 * -----------------------------------------------------------------------------
 *
 * SyL - Web Application Framework for PHP
 *
 * PHP version 4 (>= 4.3.x) or 5
 *
 * Copyright (C) 2006 k.watanabe
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -----------------------------------------------------------------------------
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_RequestParameterFile.php,v 1.2 2006/12/25 17:30:18 seasonstream Exp $
 * @link      http://www.syl.jp/
 * -----------------------------------------------------------------------------
 */

/**
 * パラメータ保持クラス
 */
require_once SYL_INCLUDE_DIR . '/framework/SyL_RequestParameter.php';

// アップロードされたファイルのパーミッション
define('SYL_UPLOAD_FILE_MODE', 0666);

/**
 * アップロードファイル保持クラス
 *
 * ※ファイルインデックスは、「getFileNext」「uploadAll」メソッドで
 *   インクリメントされる。
 *
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_RequestParameterFile.php,v 1.2 2006/12/25 17:30:18 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_RequestParameterFile extends SyL_RequestParameter
{
    /**
     * アップロードエラー配列
     * 
     * @access private
     * @var array
     */
    var $errors = array();
    /**
     * アップロードディレクトリ
     * 
     * @access private
     * @var string
     */
    var $upload_dir = SYL_UPLOAD_DEFAULT_DIR;

    /**
     * コンストラクタ
     *
     * @access public
     */
    function SyL_RequestParameterFile()
    {
        $parameters = array();

        if (isset($_FILES)) {
            // ファイルキャッシュクリア
            clearstatcache();

            // 取得パラメータが配列か判定
            foreach ($_FILES as $key => $value) {
                if (is_array($value['error'])) {
                    for ($i=0; $i<count($value['error']); $i++) {
                        if ($value['error'][$i] > 0) {
                            $this->errors[$key][$i] = $this->getErrorMessagePHP($value['error'][$i], $i);
                        } else if ($value['size'][$i] == 0) {
                            $this->errors[$key][$i] = '[SyL error] upload file is size of 0 (' . ($i+1) . ')';
                        } else if (!is_uploaded_file($value['tmp_name'][$i])) {
                            $this->errors[$key][$i] = "[SyL error] 'is_uploaded_file' function error (" . ($i+1) . ')';
                        }
                    }
                } else {
                    if ($value['error'] > 0) {
                        $this->errors[$key]['0'] = $this->getErrorMessagePHP($value['error']);
                    } else if ($value['size'] == 0) {
                        $this->errors[$key]['0'] = '[SyL error] upload file is size of 0';
                    } else if (!is_uploaded_file($value['tmp_name'])) {
                        $this->errors[$key]['0'] = "[SyL error] 'is_uploaded_file' function error ";
                    }
                }
            }

            // パラメータ取得
            $parameters =& $_FILES;
        }
        $this->parameters =& $parameters;
    }

    /**
     * エラーメッセージを取得
     * 
     * @access private
     * @param string エラーNo
     * @param int ファイル番号
     * @return string エラーメッセージ
     */
    function getErrorMessagePHP($errorno, $i='')
    {
        if (is_numeric($i)) {
            $i = '(' . ($i+1) . ')';
        }
        switch ($errorno) {
        case UPLOAD_ERR_INI_SIZE:   return '[SyL error] upload size is more than php.ini file ' . $i; break;
        case UPLOAD_ERR_FORM_SIZE:  return '[SyL error] upload size is more than html form init size ' . $i; break;
        case UPLOAD_ERR_PARTIAL:    return '[SyL error] upload file can not upload a part of upload file ' . $i; break;
        case UPLOAD_ERR_NO_FILE:    return '[SyL error] upload file is not exist ' . $i; break;
        case UPLOAD_ERR_NO_TMP_DIR: return '[SyL error] TMP_DIR undefined ' . $i; break;
        default:                    return '[SyL error] undefined upload error ' . $i; break;
        }
    }

    /**
     * パラメータをセット
     * 
     * @access public
     * @param string パラメータ名
     * @param string パラメータ値
     */
    function setParameter($name, $value)
    {
        trigger_error("[SyL error] SyL_RequestFile Object can't set parameter", E_USER_ERROR);
    }

    /**
     * エラー判定
     * 
     * @access public
     * @param bool true: エラーあり、false: エラー無し
     */
    function isError()
    {
        return (count($this->errors) > 0);
    }

    /**
     * エラーメッセージ取得
     * 
     * @access public
     * @param string フォーム名
     * @return string エラーメッセージ
     */
    function getErrorMessage($name)
    {
        return (isset($this->errors[$name]) ? $this->errors[$name] : '');
    }

    /**
     * アップロードディレクトリをセット
     * 
     * @access public
     * @param string アップロードディレクトリ
     */
    function setUploadDir($upload_dir)
    {
        // アップロードディレクトリ
        if ($upload_dir != '') {
            // 最後の「/」補完
            $this->upload_dir = preg_match( '/.*\/$/', $upload_dir) ? $upload_dir : $upload_dir . '/';
        }
    }

    /**
     * ファイルアップロード実行
     * 
     * @access public
     * @param string フォーム要素名
     * @param string アップロードディレクトリ
     * @return boolean true: アップロード成功, false: アップロードエラー
     */
    function upload($name, $upload_dir='')
    {
        if ($upload_dir != '') {
            $upload_dir = preg_match( '/.*\/$/', $upload_dir) ? $upload_dir : $upload_dir . '/';
        } else {
            $upload_dir = $this->upload_dir;
        }

        $upload_flag = true;

        $file = $this->getParameter($name);
        if (is_array($file['tmp_name'])) {
            for ($i=0; $i<count($file['tmp_name']); $i++) {
                if ($file['error'][$i] == 0) {
                    $upload_file = $upload_dir . $file['name'][$i];
                    if (!$this->_upload($name, $file['tmp_name'][$i], $upload_dir, $upload_file, $i)) {
                        $upload_flag = false;
                    }
                }
            }
        } else {
            if ($file['error'] == 0) {
                $upload_file = $upload_dir . $file['name'];
                if (!$this->_upload($name, $file['tmp_name'], $upload_dir, $upload_file)) {
                    $upload_flag = false;
                }
            }
        }
        return $upload_flag;
    }

    /**
     * ファイルアップロード実行
     * 
     * @access public
     * @param string フォーム要素名
     * @param string アップロードディレクトリ
     * @param string アップロードファイル
     * @return boolean true: アップロード成功, false: アップロードエラー
     */
    function _upload($name, $tmp_name, $upload_dir, $upload_file, $i='')
    {
        if (is_numeric($i)) {
            $num = '(' . ($i+1) . ')';
        } else {
            $num = '';
            $i   = '0';
        }
        if (!is_writable($upload_dir)) {
            $this->errors[$name][$i] = '[SyL error] permission denied ' . $num . ' (' . $upload_file . ')';
            return false;
        } else if (!@move_uploaded_file($tmp_name, $upload_file)) {
            $this->errors[$name][$i] = '[SyL error] upload error ' . $num . ' (' . $upload_file . ')';
            return false;
        } else {
            if (SYL_UPLOAD_FILE_MODE != '') {
                @chmod($upload_file, SYL_UPLOAD_FILE_MODE);
            }
            return true;
        }
    }

    /**
     * 全ファイルアップロード実行
     * 
     * @access public
     * @param string アップロードディレクトリ
     * @return boolean true: アップロード成功, false: アップロードエラー
     */
    function uploadAll($upload_dir='')
    {
        $upload_flag = true;
        foreach ($this->parameters as $name => $value) {
            if (!$this->upload($name, $upload_dir)) {
                $upload_flag = false;
            }
        }

        return $upload_flag;
    }
}

?>
