<?php


/**
 *
 *
 * @category  vendors
 * @package   fileman
 *
 * @author    Yusein Yuseinov <yyuseinov@gmail.com>
 * @copyright 2006 - 2013 Experta OOD
 * @license   GPL 3
 *
 * @since     v 0.1
 */
class fileman_Log extends core_Manager
{
    /**
     * Заглавие на таблицата
     */
    public $title = 'Последни файлове';
    
    
    /**
     * Кой има право да чете?
     */
    public $canRead = 'user';
    
    
    /**
     * Кой има право да променя?
     */
    public $canEdit = 'no_one';
    
    
    /**
     * Кой има право да добавя?
     */
    public $canAdd = 'no_one';
    
    
    /**
     * Кой има право да го види?
     */
    public $canView = 'user';
    
    
    /**
     * Кой може да го разглежда?
     */
    public $canList = 'user';
    
    
    /**
     * Необходими роли за оттегляне на документа
     */
    public $canReject = 'no_one';
    
    
    /**
     * Кой има право да го изтрие?
     */
    public $canDelete = 'no_one';
    
    
    /**
     * Плъгини за зареждане
     */
    public $loadList = 'fileman_Wrapper, fileman_DialogWrapper, plg_Sorting';
    
    
    /**
     * Името на полито, по което плъгина GroupByDate ще групира редовете
     */
    public $groupByDateField = 'lastOn';
    
    
    /**
     * Броя на записите при странициране в диалоговия прозорец
     */
    const DIALOG_LIST_ITEMS_PER_PAGE = 5;
    
    
    /**
     * Броя на записите при странициране в диалоговия прозорец - в мобилен
     */
    const DIALOG_LIST_ITEMS_PER_PAGE_MOBILE = 50;
    
    
    public $listFields = 'fileId=Линк, action, lastOn';
    
    
    /**
     * Описание на модела
     */
    public function description()
    {
        $this->FLD('fileId', 'key(mvc=fileman_Files, select=fileHnd)', 'caption=Манипулатор,notNull');
        $this->FLD('fileName', 'varchar', 'caption=Файл');
        $this->FLD('fileSize', 'fileman_FileSize', 'caption=Размер');
        $this->FLD('action', 'enum(upload=Качване, preview=Разглеждане, rename=Преименуване)', 'caption=Действие');
        $this->FLD('userId', 'user', 'caption=Потребител');
        $this->FLD('lastOn', 'datetime(format=smartTime)', 'caption=Последно');
        
        $this->FLD('dataId', 'key(mvc=fileman_Data)', 'caption=Данни');
        
        $this->setDbUnique('dataId,userId');
        
        $this->setDbIndex('lastOn');
        $this->setDbIndex('userId,fileId');
    }
    
    
    /**
     * Обновява информацията за използването на файла
     *
     * @param mixed  $fileHnd - Запис от fileman_Files или манипулатор на файла
     * @param string $action  - Съответнотното действие: upload, preview
     * @param int    $userId  - id на потребитля
     */
    public static function updateLogInfo($fileHnd, $action, $userId = null)
    {
        if (Mode::is('FILEMAN_STOP_LOG_INFO')) {

            return false;
        }

        // Ако не е подадено id на потребител
        if (!$userId) {
            
            // Вземаме id' то на текущия потребител
            $userId = core_Users::getCurrent();
        }
        
        // Ако е подаден запис всмето манипулатор
        if (is_object($fileHnd)) {
            
            // Използваме го
            $fRec = $fileHnd;
        } else {
            
            // Ако е подаден манипулатор
            
            // Вземаме записа
            $fRec = fileman_Files::fetchByFh($fileHnd);
        }
        
        // Обновяваме времето на последно използване на данните
        fileman_Data::updateLastUse($fRec->dataId);
        
        // Ако системния потребител, връщаме
        if ($userId < 1) {
            
            return false;
        }
        
        // Ако няма манипулатор на файла
        if (!$fRec->fileHnd) {
            
            return false;
        }
        
        // Вземаме предишния запис
        $nRec = static::fetch(array("#dataId = '[#1#]' AND #userId=[#2#]", $fRec->dataId, $userId));
        
        // Ако този файл не е бил използван от съответния потребител
        if (!$nRec) {
            
            // Създаваме обект
            $nRec = new stdClass();
            
            // Добавяме id на потребителя
            $nRec->userId = $userId;
        }
        
        // Добавяме id на файла
        $nRec->fileId = $fRec->id;
        
        // Вземаме meta данните
        $meta = fileman::getMeta($fRec->fileHnd);
        
        // Добавяме размера
        $nRec->fileSize = $meta['size'];
        
        // Добавяме съответното действие
        $nRec->action = $action;
        
        // Добавяме текущото време
        $nRec->lastOn = dt::now();
        
        // Добавяме името на файла
        $nRec->fileName = $fRec->name;
        
        // Добавяме данните за файла
        $nRec->dataId = $fRec->dataId;
        
        // Упдейтваме записа
        static::save($nRec);
        
        // Връщаме записа
        return $nRec;
    }
    
    
    /**
     * Екшъна за показване на диалоговия прозорец за добавяне на файл
     */
    public function act_Dialog()
    {
        // Вземаме id' то на кофата
        $bucketId = Request::get('bucketId', 'int');
        
        // Вземаме callBack'а
        $callback = Request::get('callback', 'identifier');
        
        // Сетваме нужните променливи
        Mode::set('dialogOpened', true);
        Mode::set('callback', $callback);
        Mode::set('bucketId', $bucketId);
        
        // Вземаме шаблона
        $tpl = $this->getTpl();
        
        $tpl->push('fileman/js/lastUsed.js', 'JS');
        jquery_Jquery::run($tpl, 'lastUsedActions();');
        
        // Рендираме диалоговия прозорец
//        return $this->renderDialog($tpl);
        
        // Връщаме шаблона
        return $tpl;
    }
    
    
    /**
     * Връща шаблона за диалоговия прозорец
     *
     * @param Core_Et $tpl
     */
    public function renderDialog_($tpl)
    {
        return $tpl;
    }
    
    
    /**
     * Връща шаблона за добавяне на файл
     */
    public function getTpl()
    {
        // Вземаме шаблона за листовия изглед
        return $this->act_List();
    }
    
    
    /**
     * Извиква се преди подготовката на колоните ($data->listFields)
     *
     * @param core_Mvc $mvc
     * @param object   $res
     * @param object   $data
     */
    public static function on_BeforePrepareListFields($mvc, &$res, $data)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Нулираме, ако е имало нещо
            $data->listFields = array();
            
            // Задаваме, кои полета да се показва
            $data->listFields['FileIcon'] = '-';
            $data->listFields['Name'] = 'Име';
            
            // Да не се извикат останалите
            return false;
        }
        
        // Ако сме в листовия изглед
        // Добавяме плъгина
        $mvc->load('plg_GroupByDate');
    }
    
    
    /**
     * Изпълнява се след подготовката на формата за филтриране
     *
     * @param core_Mvc $mvc
     * @param object   $data
     */
    public function on_AfterPrepareListFilter($mvc, $data)
    {
        $query = $data->query;
        
        // Ако е задеден потребител
        if (($userId = core_Users::getCurrent()) && ($userId > 0)) {
            
            // Вземаме записите само за избрания потребител
            $query->where("#userId = '{$userId}'");
        }
        
        // По - новите да са по - напред
        $query->orderBy('#lastOn', 'DESC');
        
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Ако има кофа
            if ($bucketId = Mode::get('bucketId')) {
                
                // Вземаме записите за кофата
                $bucketRec = fileman_Buckets::fetch($bucketId);

                // Вземаме максималния размер за файл в кофата
                $query->where("#fileSize < '{$bucketRec->maxSize}'");
                
                // Ако има позволени разширения в кофата
                if ($extensions = $bucketRec->extensions) {
                    
                    // Вземаме масива с позволените разширения в кофата
                    $extArr = fileman_Buckets::getAllowedExtensionArr($extensions);
                    
                    // Ако има масив
                    if ($extArr) {
                        
                        // Флаг, който указва, че за първи път сме в цикъла
                        $first = true;
                        
                        // Обхождаме масива
                        foreach ((array) $extArr as $ext) {
                            
                            // Добавяме условие, да се вземат всички файлове, които завършавт с посоченото разширение
                            $query->where(array("LOWER(#fileName) LIKE '%.[#1#]'", $ext), !$first);
                            
                            // Ако сме за първи път
                            if ($first) {
                                
                                // Сваляме флага
                                $first = false;
                            }
                        }
                    }
                }
            }
        }
            
        // Вземаме формата за филтриране
        $form = $data->listFilter;
        
        // Добавяме променливата, която се взема от URL' то
        // Необходимо е, защото не се предава при филтриране
        $form->FNC('Protected', 'varchar', 'input=hidden, silent');
        
        // В хоризонтален вид
        $form->view = 'horizontal';
        
        // Добавяме бутон за филтриране
        $form->toolbar->addSbBtn('Филтрирай', 'default', 'id=filter', 'ef_icon = img/16/funnel.png');
        
        $form->FNC('search', 'varchar', 'caption=Търсене,input,silent,recently,refreshForm');
        
        // Показваме полетата
        $form->showFields = 'search, Protected';
        
        // Инпутваме стойностите
        $form->input('search, Protected', 'silent');
        
        // Ако има текст за търсене
        if ($search = trim($form->rec->search)) {
            $data->query->EXT('searchKeywords', 'fileman_Data', 'externalKey=dataId');
            plg_Search::applySearch($search, $data->query, 'searchKeywords');
        } else {
            // Ако няма търсене, скриваме html и eml файловете
            foreach (array('html', 'eml') as $ext) {
                $query->where(array("LOWER(#fileName) NOT LIKE '%.[#1#]'", $ext));
            }
        }
    }
    
    
    /**
     * Изпълнява се преди подготвяне на страниците
     *
     * @param core_Mvc $mvc
     * @param object   $res
     * @param object   $data
     */
    public function on_BeforePrepareListPager($mvc, &$res, $data)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Задаваме броя на елементите в страница
            if (Mode::is('screenMode', 'narrow')) {
                $mvc->listItemsPerPage = static::DIALOG_LIST_ITEMS_PER_PAGE_MOBILE;
            } else {
                $mvc->listItemsPerPage = static::DIALOG_LIST_ITEMS_PER_PAGE;
            }
        }
    }
    
    
    /**
     * След преобразуване на записа в четим за хора вид.
     *
     * @param core_Mvc $mvc
     * @param object   $data
     */
    public static function on_AfterPrepareListRows($mvc, $res, &$data)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            $callback = Mode::get('callback');
            
            // Обхождаме записите
            foreach ((array) $data->recs as $key => $rec) {
                // Името на файла
                $fileName = $rec->fileName;
                
                // Манипулатора на файла
                $fh = fileman_Files::fetchField($data->recs[$key]->fileId, 'fileHnd');
                
                // Вербалното име на файла
                $fileNameVerb = static::getVerbal($rec, 'fileName');
                
                // Съкращаваме дължината на името
                $fileNameVerb = str::limitLen($fileNameVerb, 30);
                
                $id = 'last_' . $rec->id;
                
                // Атрибутите на линковете
                $attr = array('onclick' => "if(window.opener.{$callback}('{$fh}','{$fileName}') != true) self.close(); else self.focus();", 'class' => 'file-log-link hyphen');

                // Името на файла да е линк с посочените атрибути
                $fileNameLink = ht::createLink($fileNameVerb, '#', null, $attr);
                
                // Взеамаме иконата с линка за съответния файл
                $img = static::getIcon($fh);
                
                // Добавяме иконата
                $data->rows[$key]->FileIcon = ht::createLink($img, '#', null, $attr);
                
                // Вземаме иконата с линка към сингъла на файла
                $nameStr = $fileNameLink . "<br /><span class='fileman-log-action-date'>" . fileman::getVerbal($rec->fileId, 'createdBy') . ' ' . fileman::getVerbal($rec->fileId, 'createdOn') . '</span>';
                
                // Вземаме иконата с линка към сингъл на файла
                $nameLink = ht::createLinkRef($nameStr, array('fileman_Files', 'single', $fh), null, array('target' => '_blank', 'title' => 'Към изгледа на файла'));
                
                // Добавяме името на файла
                $data->rows[$key]->Name = $nameLink;
                
                // Добавяме id в атрибутите на файла
                $data->rows[$key]->ROW_ATTR['id'] = $id;
                $data->rows[$key]->ROW_ATTR['class'] = 'filemanLastLog';
            }
            
            // Да не се извикат останалите
            return false;
        }
        
        // Обхождаме масива
        foreach ((array) ($data->recs) as $id => $rec) {
                
                // Вземаме линка към сингъла на файла
            $data->rows[$id]->fileId = fileman_Files::getLinkById($rec->fileId);
        }
    }
    
    
    /**
     * Връща иконата за подадения файл
     *
     * @param string $fh   - Манупулатор на файла
     * @param int    $size - Размер на файла
     */
    public static function getIcon($fh, $size = 48)
    {
        // Вземаме записа за файла
        $fRec = fileman_Files::fetchByFh($fh);
        
        // Вземаме името на файла
        $fileName = $fRec->name;
        
        // Вземаме разширението на файла
        $ext = mb_strtolower(fileman_Files::getExt($fileName));
        
        // Ако може да се генерира thumbnail
        if (thumb_Img::isAllowedForThumb($fh)) {
            $imgInst = new thumb_Img($fh, $size, $size, 'fileman');
            
            // Вземаме файла
            $img = $imgInst->createImg();
        } else {
            
            //Иконата на файла, в зависимост от разширението на файла
            $icon = "fileman/icons/{$size}/{$ext}.png";
            
            //Ако не можем да намерим икона за съответното разширение
            if (!is_file(getFullPath($icon))) {
                
                // Използваме иконата по подразбиране
                $icon = "fileman/icons/{$size}/default.png";
            }
            
            // Вземаме изображението
            $img = ht::createElement('img', array('src' => sbf($icon, '', true), 'width' => $size, 'height' => $size));
        }
        
        return $img;
    }
    
    
    /**
     * Извиква се преди подготовката на титлата в списъчния изглед
     *
     * @param core_Mvc $mvc
     * @param core_Et  $tpl
     * @param object   $data
     */
    public static function on_BeforeRenderListTitle($mvc, &$tpl, $data)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Да не се слага заглавието
            
            // Да не се извикат останалите
            return false;
        }
    }
    
    
    /**
     * След рендиране на шаблона
     *
     * @param core_Mvc $mvc
     * @param core_Et  $tpl
     * @param object   $data
     */
    public static function on_AfterRenderListLayout($mvc, $tpl, $data)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Заменяме плейсхолдера за страницира с празен стринг
            $tpl->replace('', 'ListPagerBottom');
        }
    }
    
    
    /**
     * Извиква се преди рендирането на 'опаковката' на мениджъра
     *
     * @param core_Mvc $mvc
     * @param string   $res
     * @param core_Et  $tpl
     * @param object   $data
     */
    public function on_BeforeRenderWrapping($mvc, &$res, &$tpl, $data = null)
    {
        // Ако е отворен в диалоговия прозорец
        if (Mode::get('dialogOpened')) {
            
            // Рендираме опаковката от друго място
            $res = $mvc->renderDialog($tpl);
            
            // Да не се извикат останалите и да не се рендира "опаковката"
            return false;
        }
    }
    
    
    /**
     * Извиква се след SetUp-а на таблицата за модела
     *
     * За съвместимост със стари бази
     *
     * @todo Може да се премахне
     */
    public static function on_AfterSetupMvc($mvc, &$res)
    {
        // Вземаме всички записи, които няма dataId
        $query = $mvc->getQuery();
        $query->where('#dataId IS NULL');
        
        // Обхождаме резултатите
        while ($rec = $query->fetch()) {
            
            // Флаг, дали да се премахне
            $delete = false;
            
            // Ако има fileId вземаме dataId
            if (($rec->fileId) && ($dataId = fileman_Files::fetchField($rec->fileId, 'dataId'))) {
                
                // Ако няма такъв запис в този модел за съответния потребител
                if (!static::fetch("#dataId = {$dataId} AND #userId = {$rec->userId}")) {
                    
                    // Добавяме dataId
                    $rec->dataId = $dataId;
                    static::save($rec);
                    
                    // Увеличаваме брояча
                    $cnt++;
                } else {
                    
                    // Да се изтрие ако записа няма да е уникален
                    $delete = true;
                }
            } else {
                
                // Да се изтрие, ако няма да има такива данни
                $delete = true;
            }
            
            // Ако флага е вдигнат
            if ($delete) {
                
                // Изтриваме
                static::delete($rec->id);
            }
        }
        
        // Ако има добавени записи
        if ($cnt) {
            
            // Показваме броя им
            $res .= "<li>Добавени {$cnt} 'dataId'";
        }
    }
}
