<?php

Goweb::loadClass('Goweb_Controller_Action_Admin');

/**
 * Goweb Sitemanager 4 Framework
 * @version    5.1.9
 * @category   Backoffice
 * @package    Filemanager
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2010 (c) Goweb (http://www.goweb.pt)
 */
class Filemanager_GenericController extends Goweb_Controller_Action_Admin {

    /**
     * Titulo do Modulo
     * @var string
     */
    protected $_title;

    /**
     * Controller do Modulo
     * @var string
     */
    protected $_controller = 'filemanager';

    /**
     * Seccoes do Modulo
     * @var array
     */
    protected $_sections;

    /**
     * Seccao default do modulo
     * @var string
     */
    protected $_section = 'ficheiros';

    /**
     * Caminho absoluto do upload
     * @var string
     */
    protected $_uploadPath = '';

    /**
     * Caminho relativo do upload
     * @var string
     */
    protected $_uploadRelativePath = '';

    /**
     * Caminho base do upload
     * @var string
     */
    protected $_uploadBasePath = '/uploads/cms';

    /**
     * Caminho dos thumbnails
     * @var string
     */
    protected $_thumbnailsPath = '';

    /**
     * Caminho
     * @var string
     */
    protected $_path = '';

    /**
     * Directorios
     * @var array
     */
    protected $_dirs = array();

    /**
     * Ficheiros
     * @var array
     */
    protected $_files = array();

    /**
     * Ficheiros ordenados
     */
    protected $_filesOrdered = array();

    /**
     * Construtor da classe
     */
    public function init() {
        parent::init();
        $this->_title = translateAdmin('CMS');
        $this->_sections = array('ficheiros' => translateAdmin('Imagens'));
        $this->view->setViewsPath((dirname(__FILE__) . DIRECTORY_SEPARATOR . 'views'));
        $this->_uploadPath = PUBLIC_UPLOAD_PATH . DIRECTORY_SEPARATOR . 'cms';
        $this->_thumbnailsPath = DIRECTORY_SEPARATOR . '.thumbnails';
    }

    /**
     * Metodo chamado quando nenhuma action &eacute; fornecida
     */
    public function indexAction() {
        $this->browseAction();
    }
    /**
     * Este Metodo &eacute; executado quando a action fornecida n&atilde;o
     * &eacute; en&atilde;ontrada
     */
    public function __call($action, $arguments) {
        $this->browseAction();
    }

    /**
     * Este metodo valida e cria as pastas necessarias ao upload do ficheiro da imagem
     *
     * @return mixed
     */
    public function browseAction() {
        $type = 'images';
        $this->_uploadPath =  PUBLIC_UPLOAD_PATH . DIRECTORY_SEPARATOR . "cms";
        $this->_uploadBasePath =  "/uploads/cms";

        $path = urldecode($this->_request->path);
        $path = DIRECTORY_SEPARATOR . trim($path, '/');
        $this->_path = $path;

        $this->_initBaseUploadPath($this->_path);


        if (is_dir($this->_uploadPath)) {
            $this->_uploadPath .= ($path == '/') ? '' : $path;
            $this->_uploadRelativePath .= ($path == '/') ? '' : $path;
        } else {
            $this->_path = '/';
        }

        $this->_checkThumbnailsPath();

        // Criaecao de pasta
        Goweb::loadClass('Form_Pasta', dirname(__FILE__));
        $formPasta = new Form_Pasta('form_pasta', '/filemanager/browse/section/' . $type . '/path/' . urlencode($this->_path) );
        $formPasta->render();

        if ($this->_request->pasta != null && $this->_request->submit != null) {

            $dirName = $this->_clearString($this->_request->pasta);

            //if ($formPasta->validate($this->_request->pasta)) {
            if (file_exists($this->_uploadPath . '/' . $dirName)) {
                $formPasta->pasta->setErrorMessage(translateAdmin('J&aacute; existe uma pasta com o nome da <b>{{campo}}</b>.', $this->_request->pasta));
            } else {
                mkdir($this->_uploadPath . '/' . $dirName);
                chmod($this->_uploadPath . '/' . $dirName, 0777);
            }
            return $this->_redirect($this->view->serverName. goweb::link('/filemanager/browse/section/' . $type . '/path/' . urlencode($this->_path) ));
            //}
        }
        $this->view->form_pasta = $formPasta;

        // ---
        $method = '_' . $type . 'Browse';
        $this->{$method}();

    }

    /**
     * Remover ficheiros
     *
     */
    public function deletefilesAction() {
        $path = urldecode($this->_request->path);
        $path = DIRECTORY_SEPARATOR . trim($path, '/');
        $this->_path = $path;
        $type = 'images';

        $this->_uploadPath =  PUBLIC_UPLOAD_PATH . DIRECTORY_SEPARATOR . "cms";
        $this->_uploadBasePath =  "/uploads/cms";

        $this->_initBaseUploadPath($this->_path);

        if (is_dir($this->_uploadPath)) {
            $this->_uploadPath .= ($path == '/') ? '' : $path;
            $this->_uploadRelativePath .= ($path == '/') ? '' : $path;
       	} else {
       	    $this->_path = '/';
       	}



        $this->_checkThumbnailsPath();

        if ($this->_request->file) {
            $file = $this->_uploadPath . DIRECTORY_SEPARATOR . $this->_request->file;
            $thumbnail = $this->_uploadPath . $this->_thumbnailsPath . DIRECTORY_SEPARATOR .$this->_request->file;
            if (file_exists($file) && is_writable($file)) {
                unlink($file);
            }
            if (file_exists($thumbnail) && is_writable($thumbnail)) {
                unlink($thumbnail);
            }
        }
        // $this->_fileBrowse();

        $method = '_' . $type . 'Browse';
        $this->{$method}();
    }

    /**
     * Remove directorio
     *
     */
    public function deletefolderAction() {
        $path = urldecode($this->_request->path);
        $pastas = explode('/', trim($path, '/'));
        $pastas_temp = '';
        for ($i = 0; $i < count($pastas) - 1; $i++) {
            $pastas_temp .= '/' . $pastas[$i];
        }
        $pasta = $pastas[count($pastas) - 1];
        $path = $pastas_temp;
        $path = DIRECTORY_SEPARATOR . trim($path, '/');
        $this->_path = $path;
        $type = 'images';

        $this->_uploadPath =  PUBLIC_UPLOAD_PATH . DIRECTORY_SEPARATOR . "cms";
        $this->_uploadBasePath =  "/uploads/cms";

        $this->_initBaseUploadPath($this->_path);

        if (is_dir($this->_uploadPath)) {
            $this->_uploadPath .= ($path == '/') ? '' : $path;
            $this->_uploadRelativePath .= ($path == '/') ? '' : $path;
       	} else {
       	    $this->_path = '/';
       	}



        $this->_checkThumbnailsPath();

        if ($this->_request->path) {
            if (file_exists($this->_uploadPath . DIRECTORY_SEPARATOR . trim($pasta, '/')) && is_writable($this->_uploadPath . DIRECTORY_SEPARATOR . trim($pasta, '/'))){
                $this->_recursiveRemoveDirectory($this->_uploadPath . DIRECTORY_SEPARATOR . trim($pasta, '/'));
            }

        }

        $method = '_' . $type . 'Browse';
        $this->{$method}();
    }

    /**
     * Remove ficheiro
     *
     */
    public function deleteAction() {
        $path = urldecode($this->_request->path);
        $path = DIRECTORY_SEPARATOR . trim($path, '/');
        $this->_path = $path;
        $type = 'images';

        $this->_initBaseUploadPath($type);
        $this->_uploadPath .= DIRECTORY_SEPARATOR . $type;
        $this->_uploadRelativePath .= DIRECTORY_SEPARATOR . $type;

        if (is_dir($this->_uploadPath . $path)) {
            $this->_uploadPath .= ($path == '/') ? '' : $path;
            $this->_uploadRelativePath .= ($path == '/') ? '' : $path;
        } else {
            $this->_path = '/';
        }

        $this->_checkThumbnailsPath();

        if ($this->_request->file) {
            $file = $this->_uploadPath . DIRECTORY_SEPARATOR . $this->_request->file;

            $thumbnail = $this->_uploadPath . $this->_thumbnailsPath . DIRECTORY_SEPARATOR .$this->_request->file;
            if (file_exists($file) && is_writable($file)) {
                unlink($file);
            }
            if (file_exists($thumbnail) && is_writable($thumbnail)) {
                unlink($thumbnail);
            }

        }

        $this->_imagesBrowse();
    }

    /**
     * Visualiza imagem
     *
     */
    private function _imagesBrowse() {
        $type = 'image';
        $config = new Goweb_Config(Goweb_Config_Ini::load(APPLICATION_PATH . DIRECTORY_SEPARATOR . 'Cms' . DIRECTORY_SEPARATOR . 'config.ini', 'base'));
        Goweb::loadClass('Form_Files', dirname(__FILE__));
        $path = urldecode($this->_request->path);
        $form = new Form_Files('form_files', '/filemanager/browse/section/' . $type . '/path/' . urlencode($this->_path) );
        $form->render();
        if ($this->_request->isPost()) {
            if ($form->validate()) {
                if (is_writable($this->_uploadPath)) {
                    if (!file_exists($this->_uploadPath . $this->_thumbnailsPath)) {
                        try {
                            mkdir($this->_uploadPath . $this->_thumbnailsPath);
                            chmod($this->_uploadPath . $this->_thumbnailsPath, 0777);
                        } catch (Exception $e) {
                            throw new Goweb_Exception('N&atilde;o e poss&iacute;vel criar a directoria: "' . $this->_uploadPath . $this->_thumbnailsPath . '".');
                        }
                    }
                    $filename = $this->_clearString($form->ficheiro->value);
                    $ext = pathinfo($filename, PATHINFO_EXTENSION);
                    /**
                     * Extens�o em lowercase, por causa dos thumbnails
                     */
                    if (strcmp(strtolower($ext), $ext) !== 0){
                        $filename = substr($filename,0, -1 * strlen($ext)) . strtolower($ext);
                    }
                    $filename = date("YmdHis") . '_' . $filename;

                    try {
                        if (!$form->ficheiro->isReceived() && !$form->ficheiro->receive()) {
                            throw new Goweb_Exception("Ocorreu um erro a gravar o ficheiro");
                        }
                        rename($form->ficheiro->getFileName(), $this->_uploadPath . DIRECTORY_SEPARATOR . $filename);
                        chmod($this->_uploadPath . DIRECTORY_SEPARATOR . $filename, 0777);

                    } catch (Exception $e) {
                        throw new Goweb_Exception("Ocorreu um erro a gravar o ficheiro: " . $e->getMessage() . ' (linha '. $e->getLine() . ')');
                    }

                    Goweb::loadClass('Zend_Validate_File_IsImage');
                    $isImage = new Zend_Validate_File_IsImage();
                    $imageMimeTypes = $isImage->getMimeType(true);
                    if (in_array($this->_getMimeType($this->_uploadPath . DIRECTORY_SEPARATOR . $filename), $imageMimeTypes)){
                        $this->_createThumbnail($filename);
                    }

                } else {
                    throw new Goweb_Exception('N&atilde;o e poss&iacute;vel escrever na directoria: "' . $this->_uploadPath . '".');
                }
            }
        }

        $this->_readDir($this->_uploadPath);
        $this->view->dirs = $this->_dirs;
        $this->view->files = $this->_filesOrdered;
        $parentArr = explode('/', trim($this->_path, '/'));
        $parent = '';
        if (count($parentArr) == 1) {
            if ($parentArr[0] == '') {
                $parent = '';
            } else {
                $parent = '/';
            }
        } else {
            for ($i=0; $i<count($parentArr) - 1; $i++) {
                $parent .= '/' . $parentArr[$i];
            }
        }

        Goweb::loadClass('Form_Pasta', dirname(__FILE__));
        $formPasta = new Form_Pasta('form_pasta', '/filemanager/browse/section/' . $type . '/path/' . urlencode($this->_path) );
        $formPasta->render();

        $this->view->form_pasta = $formPasta;
        $this->view->path = $this->_path;
        $this->view->relative_path = $this->_uploadRelativePath;
        $this->view->base_path = $this->_uploadBasePath;
        $this->view->full_path = $this->_uploadPath;
        $this->view->thumbnails_path = $this->_thumbnailsPath;
        $this->view->parent = $parent;
        $this->view->title = translateAdmin('Gest&atilde;o');
        $this->view->form = $form;

        $this->view->output = $this->view->render('images.tpl');
        $this->view->action = translateAdmin('Ficheiros');

        $this->_helper->viewRenderer->setRender('base');
    }

    /**
     * Valida as permissoes de escrita
     *
     * @param String $dir
     */
    private function _initBaseUploadPath($dir) {
        $path = $this->_uploadPath . DIRECTORY_SEPARATOR . $dir;
        if (!is_dir($path)) {
            if (!is_dir($this->_uploadPath)) {
                try {
                    mkdir($this->_uploadPath);
                    chmod($this->_uploadPath, 0777);
                } catch (Goweb_Exception $e) {
                    throw new Goweb_Exception('A pasta "' . $this->_uploadPath . '" n&atilde;o tem permiss&otilde;es de escrita.');
                }
            }
            try {
                mkdir($path);
                chmod($path, 0777);
            } catch (Goweb_Exception $e) {
                throw new Goweb_Exception('A pasta "' . $path . '" n&atilde;o tem permiss&otilde;es de escrita.');
            }
        }
    }

    /**
     * Verifica as permissoes de escrita na pasta destinada aos Thumbnails
     *
     */
    private function _checkThumbnailsPath() {
        if (!file_exists($this->_uploadPath . $this->_thumbnailsPath)) {
            try {
                mkdir($this->_uploadPath . $this->_thumbnailsPath);
                chmod($this->_uploadPath . $this->_thumbnailsPath, 0777);
            } catch (Goweb_Exception $e) {
                throw new Goweb_Exception('A pasta "' . $this->_uploadPath . $this->_thumbnailsPath . '" n&atilde;o tem permiss&otilde;es de escrita.');
            }
        }
    }

    /**
     * Verifica o tamanho de um directorio
     *
     * @param String $path
     */
    protected function _readDir($path) {
        if (is_dir($path)) {
            if ($handler = opendir($path)) {
                while (($file = readdir($handler)) !== false) {
                    if ($file != '.' && $file != '..') {
                        $type = filetype($path . DIRECTORY_SEPARATOR . $file);
                        if ( $type == 'dir') {
                            $this->_dirs[] = $file;
                        } else {
                            $size = filesize($path . DIRECTORY_SEPARATOR . $file);
                            if ($size < 1024) {
                                $size .= ' bytes';
                            } elseif ($size < 1024 * 1024) {
                                $size = number_format(round($size / 1024, 0), 0, '.', '') . ' Kb';
                            } else {
                                $size = number_format($size / (1024 * 1024), 3, '.', '') . ' Mb';
                            }
                            $this->_files[] = array('name' => $file,
                                                    'size' => $size,
                                                    'type' => $type,
                            );
                        }
                    }
                }
                closedir($handler);
            }
        }

        if (count($this->_files) > 0) {
            foreach ($this->_files as $files) {
                $this->_filesOrdered[]['name'] = $files['name'];
            }
        }
        sort($this->_dirs);
        sort($this->_filesOrdered);
        rsort($this->_filesOrdered);
    }

    /**
     * remover directorio recursivamente
     *
     * @param String $path
     */
    private function _recursiveRemoveDirectory($path)
    {
        $dir = new RecursiveDirectoryIterator($path);

        //Remove all files
        foreach(new RecursiveIteratorIterator($dir) as $file)
        {
            unlink($file);
        }

        //Remove all subdirectories
        foreach($dir as $subDir)
        {
            //If a subdirectory can't be removed, it's because it has subdirectories, so recursiveRemoveDirectory is called again passing the subdirectory as path
            if(!@rmdir($subDir)) //@ suppress the warning message
            {
                recursiveRemoveDirectory($subDir);
            }
        }

        //Remove main directory
        rmdir($path);
    }

    protected function _getMimeType($file){
        $returnValue = false;
        if (class_exists('finfo', false) && defined('MAGIC')) {
            $mime = new finfo(FILEINFO_MIME);
            $returnValue = $mime->file($file);
            unset($mime);
        } elseif (function_exists('mime_content_type')) {
            $returnValue = mime_content_type($file);
        }
        return $returnValue;
    }

    protected function _createThumbnail($filename){
        $config = new Goweb_Config(Goweb_Config_Ini::load(APPLICATION_PATH . DIRECTORY_SEPARATOR . 'Cms' . DIRECTORY_SEPARATOR . 'config.ini', 'base'));
        $arrayAttributes = getimagesize($this->_uploadPath . DIRECTORY_SEPARATOR . $filename);
        $size = array('width' => $arrayAttributes[0],'height' => $arrayAttributes[1]);


        Goweb::loadClass('Goweb_Image_Resize');
        $imageResize = new Goweb_Image_Resize();

        if($arrayAttributes[0] > $config->images->original->max_width || $arrayAttributes[1] > $config->images->original->max_height)
        $imageResize->resizeMaintainRatio($this->_uploadPath . DIRECTORY_SEPARATOR . $filename, $this->_uploadPath . DIRECTORY_SEPARATOR . $filename,
        $config->images->original->max_width, $config->images->original->max_height, 72);

        // thumbnail
        $imageResize->resizeMaintainRatio($this->_uploadPath . DIRECTORY_SEPARATOR . $filename,
        $this->_uploadPath . $this->_thumbnailsPath . DIRECTORY_SEPARATOR . $filename,
        100, 100, 100);
        chmod($this->_uploadPath . $this->_thumbnailsPath . DIRECTORY_SEPARATOR . $filename, 0777);
    }

}