<?php

/**
 * HTML class for a file upload field
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.01 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_01.txt If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @author      Adam Daniel <adaniel1@eesus.jnj.com>
 * @author      Bertrand Mansion <bmansion@mamasam.com>
 * @author      Alexey Borzov <avb@php.net>
 * @copyright   2001-2009 The PHP Group
 * @license     http://www.php.net/license/3_01.txt PHP License 3.01
 * @version     CVS: $Id: file.php,v 1.25 2009/04/04 21:34:02 avb Exp $
 * @link        http://pear.php.net/package/HTML_QuickForm
 * @version     Release: 3.2.11
 * @since       1.0
 */
class HTML_QuickForm_file extends HTML_QuickForm_input
{
   /**
    * Uploaded file data, from $_FILES
    * @var array
    */
    var $_value = null;

    /**
     * Class constructor
     *
     * @param     string    Input field name attribute
     * @param     string    Input field label
     * @param     mixed     (optional)Either a typical HTML attribute string
     *                      or an associative array
     * @since     1.0
     * @access    public
     */
    public function __construct($elementName=null, $elementLabel=null, $attributes=null)
    {
        parent::__construct($elementName, $elementLabel, $attributes);
        $this->setType('file');
    }

    /**
     * Sets size of file element
     *
     * @param     int    Size of file element
     * @since     1.0
     * @access    public
     */
    function setSize($size)
    {
        $this->updateAttributes(array('size' => $size));
    }

    /**
     * Returns size of file element
     *
     * @since     1.0
     * @access    public
     * @return    int
     */
    function getSize()
    {
        return $this->getAttribute('size');
    }

    /**
     * Freeze the element so that only its value is returned
     *
     * @access    public
     * @return    bool
     */
    function freeze()
    {
        return false;
    }

    /**
     * Sets value for file element.
     *
     * Actually this does nothing. The function is defined here to override
     * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
     * no sane user-agent uses <input type="file">'s value for anything
     * (because of security implications) we implement file's value as a
     * read-only property with a special meaning.
     *
     * @param     mixed    Value for file element
     * @since     3.0
     * @access    public
     */
    function setValue($value)
    {
        return null;
    }

    /**
     * Returns information about the uploaded file
     *
     * @since     3.0
     * @access    public
     * @return    array
     */
    public function getValue()
    {
        return $this->_value;
    } // end func getValue

    // }}}
    // {{{ onQuickFormEvent()

    /**
     * Called by HTML_QuickForm whenever form event is made on this element
     *
     * @param     string    Name of event
     * @param     mixed     event arguments
     * @param     object    calling object
     * @since     1.0
     * @access    public
     * @return    bool
     */
    public function onQuickFormEvent($event, $arg, &$caller)
    {
        switch ($event) {
            case 'updateValue':
                if ($caller->getAttribute('method') == 'get') {
                    throw new \Exception('Cannot add a file upload field to a GET method form');
                }
                $this->_value = $this->_findValue();
                $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
                $caller->setMaxFileSize();
                break;
            case 'addElement':
                $this->onQuickFormEvent('createElement', $arg, $caller);

                return $this->onQuickFormEvent('updateValue', null, $caller);
                break;
            case 'createElement':
                //$className = get_class($this);
                //$this &= new $className($arg[0], $arg[1], $arg[2]);

                break;
        }
        return true;
    }

    /**
     * Checks if the element contains an uploaded file
     *
     * @access    public
     * @return    bool      true if file has been uploaded, false otherwise
     */
    public function isUploadedFile()
    {
        return self::_ruleIsUploadedFile($this->_value);
    }

    /**
     * Checks if the given element contains an uploaded file
     *
     * @param     array     Uploaded file info (from $_FILES)
     * @access    private
     * @return    bool      true if file has been uploaded, false otherwise
     */
    public static function _ruleIsUploadedFile($elementValue)
    {
        if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
            (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
            return is_uploaded_file($elementValue['tmp_name']);
        } else {
            return false;
        }
    }


   /**
    * Tries to find the element value from the values array
    *
    * Needs to be redefined here as $_FILES is populated differently from
    * other arrays when element name is of the form foo[bar]
    *
    * @access    public
    * @return    mixed
    */
    public function _findValue(&$values = null)
    {
        if (empty($_FILES)) {
            return null;
        }
        $elementName = $this->getName();
        if (isset($_FILES[$elementName])) {
            return $_FILES[$elementName];
        } elseif (false !== ($pos = strpos($elementName, '['))) {
            $base  = str_replace(
                        array('\\', '\''), array('\\\\', '\\\''),
                        substr($elementName, 0, $pos)
                    );
            $idx   = "['" . str_replace(
                        array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
                        substr($elementName, $pos + 1, -1)
                     ) . "']";
            $props = array('name', 'type', 'size', 'tmp_name', 'error');
            $code  = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
                     "    return null;\n" .
                     "} else {\n" .
                     "    \$value = array();\n";
            foreach ($props as $prop) {
                $code .= "    \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
            }
            return eval($code . "    return \$value;\n}\n");
        } else {
            return null;
        }
    }

    /**
     * @return string
     */
    public function getElementJS($param)
    {
        $id = $this->getAttribute('id');
        $ratio = 'aspectRatio: 16 / 9';
        if (!empty($param['ratio'])) {
            $ratio = 'aspectRatio: '.$param['ratio'].',';
        }
        $scalable = 'false';
        if (!empty($param['scalable']) && $param['scalable'] !== 'false') {
            $ratio = '';
            $scalable = $param['scalable'];
        }

        return '<script>
        $(function() {
            var $inputFile = $(\'#'.$id.'\'),
                $image = $(\'#'.$id.'_preview_image\'),
                $input = $(\'[name="'.$id.'_crop_result"]\'),
                $cropButton = $(\'#'.$id.'_crop_button\'),
                $formGroup = $(\'#'.$id.'-form-group\');

            function isValidType(file) {
                var fileTypes = [\'image/jpg\', \'image/jpeg\', \'image/gif\', \'image/png\'];

                for(var i = 0; i < fileTypes.length; i++) {
                    if(file.type === fileTypes[i]) {
                        return true;
                    }
                }

                return false;
            }

            function imageCropper() {
                $formGroup.show();
                $cropButton.show();

                $image
                    .cropper(\'destroy\')
                    .cropper({
                        '.$ratio.'
                        responsive : true,
                        preview: \'.img-preview\',
                        center : false,
                        guides : false,
                        movable: false,
                        zoomable: false,
                        rotatable: false,
                        scalable: '.$scalable.',
                        crop: function(e) {
                            // Output the result data for cropping image.
                            //$input.val(event.detail.x + \',\' + event.detail.y + \',\' + event.detail.width + \',\' + event.detail.height);
                            $input.val(
                                parseInt(event.detail.width) + \',\' + parseInt(event.detail.height) + \',\' +  parseInt(event.detail.x) + \',\' + parseInt(event.detail.y)
                            );
                        }
                    });
            }

            $inputFile.on(\'change\', function () {
                var inputFile = this,
                    file = inputFile.files[0],
                    fileReader = new FileReader();
                    $(".img-box").hide();
                    $(".img-preview").show();
                if (!isValidType(file)) {
                    $formGroup.hide();
                    $cropButton.hide();

                    if (inputFile.setCustomValidity) {
                        inputFile.setCustomValidity(
                            inputFile.title ? inputFile.title : \''.get_lang('Only PNG, JPG or GIF images allowed').'\'
                        );
                    }

                    return;
                }

                if (inputFile.setCustomValidity) {
                    inputFile.setCustomValidity(\'\');
                }

                fileReader.readAsDataURL(file);
                fileReader.onload = function () {
                    $image
                        .attr(\'src\', this.result)
                        .on(\'load\', imageCropper);
                };
            });

            $cropButton.on(\'click\', function () {
                var $imageLarge = $("#image-cut-lg");
                var canvas = $image.cropper(\'getCroppedCanvas\'),
                    dataUrl = canvas.toDataURL();

                $(".img-box").show();
                $(".img-preview").hide();

                $image.attr(\'src\', dataUrl).cropper(\'destroy\').off(\'load\', imageCropper);
                $imageLarge.attr(\'src\', dataUrl).cropper(\'destroy\').off(\'load\', imageCropper);
                $(\'[name="'.$id.'_crop_image_base_64"]\').val(dataUrl);
                $cropButton.hide();
            });
        });
        </script>';
    }

    /**
     * @return string
     */
    public function toHtml()
    {
        $js = '';
        if (isset($this->_attributes['crop_image'])) {
            $ratio = '16 / 9';
            if (!empty($this->_attributes['crop_ratio'])) {
                $ratio = $this->_attributes['crop_ratio'];
            }
            $scalable = 'false';
            if (!empty($this->_attributes['crop_scalable'])) {
                $scalable = $this->_attributes['crop_scalable'];
            }
            $js = $this->getElementJS(array('ratio' => $ratio, 'scalable' => $scalable));
        }

        if ($this->isFrozen()) {
            return $this->getFrozenHtml();
        } else {
            $class = 'mt-1';
            if (isset($this->_attributes['custom']) && $this->_attributes['custom']) {
                $class = 'input-file';
        }

        return $js.$this->_getTabs().
                '<input class="'.$class.'" '.$this->_getAttrString($this->_attributes).' />';
        }
    }
}
