* @since Version 2.0 */ class sysTranslationsController extends cCore { public $dir; public $name; public $module; static $_cfg = array( 'import' => array( 'upload_dir' => '/files/temp_import', 'file_type' => 'FILES', ) ); static $fileExtensions = array( /*'rar', 'zip', 'doc', 'docx', 'pdf',*/ 'xls', 'xlsx', /*'odt', 'ods', 'odp', 'ppt', 'pptx'*/ ); /** * Class constructor */ public function __construct($uriData, $dir, $name) { $this->dir = $dir; $this->name = $name; parent :: __construct($uriData); $this->module = new sysTranslationsModule(); $this->oView->setTemplateDir($this->dir . "/tmpl/"); if(!$this->oView->cacheUsed()){ $this->oView->setJs(getCurrentFolder($this->dir) . '/js/' . $this->name . '.js'); $this->oView->setCss(getCurrentFolder($this->dir) . '/css/' . $this->name . '.css'); } // Set JS module init title $this->oView->setAsJSON(cCore::JS_MOD, ucfirst($name)); } /** * Function to show main form in the module * * @category sysTranslations Controller * @author Mareks Keišs * @returns bool true */ public function run($initEditMode = false){ $this->oView->TABLE = true; $this->oView->setAsJSON('initEdit', $initEditMode); $this->oView->setAsJSON('baseUrl', $this->gL()); $this->oView->setAsJSON('gM', $this->getTranslations()); $this->oView->setAsJSON('vcfg', $this->getValCfg()); $this->oView->setAsJSON('upload', $this->getUploadConfig()); $this->oView->display(); } /** * Function to create cms table & return for direct & ajax input * * @author Mareks Keišs * @category sysTranslations Controller * @param int $page - page to display * @param string $filter_json - (optional) filter json string * @param bool $headers - flag whether to send header data or not * @return array of data * @version 1.1 */ public function createCmsTable($page = 1, $filter_json = '', $headers = false) { $pages = 0; $filter = array(); if($filter_json){ $filter = cJSON::decode($filter_json, true); } $this->oView->MODULE_TITLE = $this->gM("System translations"); if(!!$filter && is_array($filter)) $this->oView->DEFAULT_SEARCH_VALUES = prepForDisplayHtml($filter); //$this->oView->LIST_BTN = true; $this->oView->LIST_HEADER = reOrderTableFields($this->getTableFields(), $this->oUser->oCfg->getTableProperty($this->name)); $this->oView->LIST_DATA = $this->getModuleData($page, $filter, $pages); $this->oView->LIST_ACTIONS = $this->getTableActions(); $data = array( 'data' => $this->oView->genHelperView('cmsc/table/data-table'), 'pcount' => $pages, 'rlimit' => $this->cmsTableRecordsPerPage ); // Send data to client if($headers) $data['header'] = $this->oView->genHelperView('cmsc/table/data-table-search'); return $data; } /** * Function to get module data * * @author Mareks Keišs * @category sysTranslations Controller * @param int $page * @param array $filter * @param int $pages * @return array of data * @version 1.1 */ public function getModuleData($page = 1, $filter = array(), &$pages) { $where = 'AND 1'; $sort = "msg.id DESC"; $offset = (($page?$page:1)-1) * $this->cmsTableRecordsPerPage; $tFields = $this->getTableFields(); // Create sort by if(getP('sortBy')) $sort = $this->module->db->genOrderByQuery(getP('sortBy'), getP('sortWay'), $tFields); // Create where clause if(count($filter)) $where = $this->module->db->genSearchFieldQuery($filter, $tFields); $subWhere = ""; /* if(isset($filter['field_search'])){ $filter['field_search'] = $this->module->db->prepData($filter['field_search']); $subWhere = " AND ( msg.msg_message like '%". str_replace(' ', '_', $filter['field_search']) ."%' OR msgt.msg_translation like '%{$filter['field_search']}%' )"; unset($filter['field_search']); }*/ $data = $this->module->getModuleRecords($where . $subWhere, $sort, $offset, $this->cmsTableRecordsPerPage); $this->oView->ROWS = $rows = $this->module->db->getSelectedRecordsCount(); $pages = floor($rows / $this->cmsTableRecordsPerPage) + ($rows%$this->cmsTableRecordsPerPage?1:0); return $data; } /** * Function to disable / enable enum records marked in table * * @author Mareks Keišs * @category sysTranslations Controller * @param array $baseField - base field to handle * @param string $rows - passed user ids in JSON string * @return array of data */ public function disableRow($baseField, $rows) { if($baseField && $rows = cJSON::decode($rows, true)){ $baseField = substr($baseField, 2); $fields = $this->getTableFields(); if(isset($fields[$baseField]['db_field'])){ if($this->module->changeRecordsStatus($this->module->db->prepData($rows), $fields[$baseField]['db_field'])){ return true; } } } cJSON::sendError(); return false; } /** * Function to delete records marked in table * * @author Mareks Keišs * @category sysTranslations Controller * @param string $rows - passed user ids in JSON string * @return array of data */ public function delete($rows) { if($rows = cJSON::decode($rows, true)){ if($this->module->deleteRecords($this->module->db->prepData($rows))){ return true; }else{ cJSON::sendError(); } } return false; } /** * Function to delete all records * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function clearAll() { if($this->module->deleteAllRecords()){ return true; }else{ cJSON::sendError(); } return false; } /** * Function to get table record data for edit mode * * @author Mareks Keišs * @category sysTranslations Controller * @param int $id - record id * @return array of data */ public function editCmsTableRecord($id) { if($id){ $data = $this->module->getRecordDataById($id); $data['ttr'] = $this->module->getRecordTranslationsById($id); $this->oView->TT = $data; } $lng = new sysLanguagesModule(); $this->oView->lang = $lng->getLanguages(false, true); return array( 'show' => array('buttons_top' => false, 'buttons_bottom' => true), 'btn' => $this->getFormButtons(), 'html' => $this->oView->genTemplate('translationsEdit'), ); } /** * Function to save Record data * * @author Mareks Keišs * @category sysTranslations Controller * @param int $recordId - record id * @param string $fields - param JSON string * @return array of data */ public function saveRecordData($recordId, $fields) { if($fields){ $fields = $this->getSubmittedDataAsArray($fields); } // Start save process if($fields){ // Validate fields $valid = new cValidator($this); $errors = $valid->checkArray($fields, $this->getValCfg()); if($errors !== true){ cJSON::sendError(array('data' => $errors)); } $vNewTranslation = array(); if(isset($fields['base']['translation-base-msg'])){ $vNewTranslation = array( 'msg_message' => $fields['base']['translation-base-msg'] ); } $translations = array(); if(isset($fields['translations']) && count($fields['translations'])){ foreach($fields['translations'] as $k=>$v){ $translations[] = array( 'msg_id' => &$recordId, 'msg_lang_id' => substr($k, 1), 'msg_translation' => firstE($v), ); } } // Update / Insert record data $oldId = $recordId; if(!$recordId){ if(!($recordId = $this->module->saveRecordDataById($recordId, $vNewTranslation))) cJSON::sendError(); } $this->module->updateTranslations($recordId, $translations); cJSON::sendOk($oldId?"":array('newid' => $recordId)); } } /** * Function to create table headers + search * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data * @version 1.1 */ public function getTableFields() { if(!$this->oUser->chkPermission('SYS_CMS_TRANSLATIONS_SHOW_MANAGEMENT', false, false)){ return false; } $tFields = array( "checkbox" => array( 'sort' => false, 'title' => '', 'class' => 'w4 center rchk' ), "id" => array( 'sort' => true, 'search' => true, 'title' => $this->gM("ID"), 'class' => 'w8 center sortDesc sort', 'db_field' => 'msg.id', 'type' => 'input', ), "msg_message" => array( 'sort' => true, 'search' => true, 'title' => $this->gM("Message"), 'class' => 'w56', 'db_field' => 'msg.msg_message', 'type' => 'input', ), "buttons" => array( 'sort' => false, 'class' => 'w20', 'title' => $this->gM("Actions"), 'btnset' => array( 'ledit' => array( 'edit' => true, 'title' => $this->gM("Edit"), ), 'ldelete' => array( 'title' => $this->gM("Delete"), ) ) ) ); if(!$this->chkP('SYS_SHOW_TABLE_IDS')) unset($tFields['id']); return $tFields; } /** * Function to get js translations for view * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function getTranslations(){ return array( 'yes' => $this->gM('Yes'), 'no' => $this->gM('No'), 'delTitle' => $this->gM('Delete translations?'), 'delMessage' => $this->gM('Selected translations will be permanently deleted and cannot be recovered. Confirm delete?'), 'buttonYes' => $this->gM('Delete selected translations'), 'buttonCancel' => $this->gM('Cancel operation'), 'clearTitle' => $this->gM('Clear all translations?'), 'clearMessage' => $this->gM('All translations will be permanently deleted and cannot be recovered. Confirm delete?'), 'clearYes' => $this->gM('Delete all'), 'clearCancel' => $this->gM('Cancel'), ); } /** * Function to get table actions * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function getTableActions(){ $actions = array( 'inew' => array( 'lbl' => $this->gM("Add new"), 'icon' => 'ico-addnew', 'sepline' => true, ), /*'istatus' => array( 'lbl' => $this->gM("Change item status"), 'sepline' => true, ),*/ 'idelete' => array( 'lbl' => $this->gM("Delete selected"), 'icon' => 'nico-delete' ), 'icleartable' => array( 'lbl' => $this->gM("Delete whole translation table"), 'icon' => 'nico-delete-all' ), 'sepline', 'iExport' => array( 'lbl' => $this->gM("Export translation data"), 'icon' => 'nico-dl' ), 'iImport' => array( 'lbl' => $this->gM("Import translation data"), 'icon' => 'nico-upl' ), 'sepline', ); if(!$this->oUser->chkPermission('SYS_CMS_TRANSLATIONS_DELETE_ALL', false, false)){ unset($actions['icleartable']); } // Reformat drop down reformatDropDown($actions, false); return $actions; } /** * Function to get js validator cfg * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function getValCfg(){ $data = array(); $compWarn = $this->gM('Please fill in the field!'); // Create validation array $lang = $this->module->getSysLanguages(); foreach($lang as $v){ $data['translations-'.$v['id']] = array( cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 0, cValidator::P_TEST => array(cValidator::CHK_STR), 'comp-warning' => $compWarn ); } return $data; } /** * Function to get form buttons * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function getFormButtons(){ return array( 1 => array( 'id' => 'fsave', 'lbl' => $this->gM('Save') ), 2 => array( 'id' => 'fcancel', 'lbl' => $this->gM('Cancel') ) ); } /** * Function to save current or full file view * * @author Aivars Žukovskis * @category sysTranslations Controller * @return array of data */ public function saveExcelDoc() { $cry = new cDefuseCrypto(); $oMsg = array( 'beg' => $this->gM('Preparing data for export...'), 'exp' => $this->gM('Exporting table data rows %nr%/%nr_max% ...'), 'wri' => $this->gM('Writing excel file!'), 'end' => $this->gM('Export successfully finished without errors!'), 'failed' => $this->gM('Failed to export data, please contact administrator!'), 'noData' => $this->gM('No data found!'), ); // ------------------------------------------------------------------------- // Get export base data // ------------------------------------------------------------------------- $i = 1; // Create export folder $cpDir = __FILES__ . 'temp_export_msg/' . date('Y-m') . '/'; $cpName = "translation_msg"; // if not exists create new dir if(!file_exists($cpDir)) if(!mkdir($cpDir, 0777, true)) cJSON::sendOk(array('msg' => $oMsg['failed'])); // Create new filename while(file_exists("{$cpDir}{$cpName}_{$i}.xlsx")) $i++; $newFile = "{$cpDir}{$cpName}_{$i}.xlsx"; // Increase time & memory limit set_time_limit(60*60*3); ini_set('memory_limit', '2048M'); // Create new PHPExcel object $oExcel = new cExcel(); // Set document properties $oExcel->setPropertiesAdv("Export"); // Activate page by index 0 $oSheet = $oExcel->setActiveSheetIndex(0); // Rename worksheet $oSheet->setTitle('TRANSLATION_MSG'); // Hide grid lines $oSheet->setShowGridlines(false); $oSheet->setPrintGridlines(false); $offset = 0; $chunkSize = 300; // Gen query $lng = new sysLanguagesModule(); $langs = $lng->getLanguages(false, true); $sQuery = $this->constructExportSqlWithoutLimit($langs); $data = $this->module->getDataByQueryAndOffset($sQuery, $offset, $chunkSize); $ll = array(); foreach($langs as $v) $ll[] = $v['id']; // get field config $tFields = $this->getMsgDocViewTableFields($langs); unset($langs); // Create header $c = 0; $r = 1; $dCount = 0; foreach($tFields as $k=>$v){ $f2c = substr($k,0,2); if($f2c == 'p_'){ $oSheet->setCellValueByColumnAndRow($c, $r, $v['title']); $oSheet->mergeCells($oExcel->xY($c+1,$r) . ":" . $oExcel->xY($c+1, $r+1)); }else if($f2c == 'l_'){ $oSheet->setCellValueByColumnAndRow($c, $r+1, $v['title']); } $c++; $oSheet->getColumnDimension($oExcel->X($c))->setWidth($v['excel_w']); } $r = $r+2; $fKeys = array_keys($tFields); $i = 1; while(!!$data){ $data = prepForDisplayHtml($data); foreach($data as $k=>$v){ $c = -1; // Set base values foreach($fKeys as $k) if(array_key_exists(substr($k,2), $v)){ $oSheet->setCellValueByColumnAndRow(++$c, $r, $v[substr($k,2)]); }else{ $oSheet->setCellValueByColumnAndRow(++$c, $r, $i++); } ++$r; } // Select next data set $offset += $chunkSize; $data = $this->module->getDataByQueryAndOffset($sQuery, $offset, $chunkSize); } $r--; //----------------------------------------------------------------- // Format - borders, aligns, types, ect. //----------------------------------------------------------------- if($offset < 30000){ $body = array( 'borders' => array( 'allborders' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array('argb' => 'd3d3d3') ), ) ); $bottomBorders = array( 'borders' => array( 'horizontal' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array('argb' => 'e7e7e7') ) ) ); $oSheet->getStyle($cAddress = 'A2:' . $oExcel->xY(count($tFields), $r))->applyFromArray($body); $oSheet->getStyle($cAddress)->applyFromArray($bottomBorders); // Set font color // $oSheet->getStyle('A2:' . $oExcel->xY(count($tFields), $r))->getFont()->getColor()->applyFromArray(array("rgb" => "9d0004")); // Align whole table $oSheet->getStyle($oExcel->xY($dCount, 1) . ":" . $oExcel->xY($dCount+count($tFields), $r)) ->getAlignment() ->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT) ->setVertical(PHPExcel_Style_Alignment::VERTICAL_TOP) ->setWrapText(true); if($dCount==0) $oSheet->getStyle("A1:" . $oExcel->xY($dCount, $r))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); if($dCount>0) $oSheet->getStyle("A1:" . $oExcel->xY($dCount, $r))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT); } // Format header $oSheet->getRowDimension(1)->setRowHeight(30); $oSheet->getStyle($cAddress = "A1:" . $oExcel->xY(count($tFields), 2))->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER); $oSheet->getStyle("A1:" . $oExcel->xY(count($tFields), 2))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); $oSheet->getStyle("A1:" . $oExcel->xY(count($tFields), 2))->getFont()->setBold(true); $oSheet->getRowDimension(2)->setRowHeight(15); // Borders $header = array( 'borders' => array( 'allborders' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array('argb' => 'd3d3d3') ), 'vertical' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array('argb' => 'd3d3d3') ) ) ); $oSheet->setCellValueByColumnAndRow(2, 1, 'Message translations'); $oSheet->mergeCells("C1:" . $oExcel->xY(2+count($ll), 1)); // Format border style $cAddress = 'A1:' . $oExcel->xY(2+count($ll),2); $oSheet->getStyle($cAddress)->applyFromArray($header); // Fill BG $oSheet->getStyle($cAddress)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID); $oSheet->getStyle($cAddress)->getFill()->getStartColor()->setARGB('F7F7F7'); $oWriter = $oExcel->createWriter(getExtension($newFile)); $oWriter->save($newFile); // Free max memory unset($oWriter, $i, $offset, $header, $body, $bottomBorders); cJSON::sendOk(array('file' => $this->gL(false, 'action:dl/file:' . $cry->encrypt(basename($newFile))), 'msg' => $oMsg['end'])); exit; } /** * Function to get doc contract view table fields * * @category sysTranslations Controller * @author Aivars Žukovskis * @parama array $language - array with languages * @returns array */ public function getMsgDocViewTableFields($language){ $tFields = array( 'p_npk' => array( 'title' => 'Npk', 'excel_w' => 8, ), 'p_message' => array( 'title' => 'Message', 'excel_w' => 48, ), ); if(!!$language && is_array($language)){ foreach($language as $v){ if($v){ $tFields["l_{$v['id']}"] = array( 'sort' => false, 'title' => $v['lang_code'], 'excel_w' => 48, ); } } } return $tFields; } public function constructExportSqlWithoutLimit($languages){ $sSelect = ""; $sWhere = ""; if(is_array($languages) && !!$languages){ $i = 1; foreach($languages as $val){ $sSelect .= "ll{$i}.msg_translation as '{$val['id']}',"; $sWhere .= "LEFT JOIN site_cms_msg_translations ll{$i} ON msg.id = ll{$i}.msg_id AND ll{$i}.msg_lang_id = {$val['id']} "; $i++; } $sSelect = substr($sSelect, 0, -1); } $sSql = " SELECT DISTINCT msg.id, msg.msg_message as message, {$sSelect} FROM site_cms_msg msg {$sWhere} "; return $sSql; } /** * Function to download file * * @category sysTranslations Controller * @author Aivars Žukovskis * @returns bool */ public function downloadFile($file, $subDir = ''){ $cry = new cDefuseCrypto(); if($file = preg_replace('/^\/files\/|^\//', '', $subDir . $cry->decrypt($file))){ if(file_exists(__FILES__ . $file)){ $mimeTypes = array( 'jpg' => 'image/jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'bmp' => 'image/bmp', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'pdf' => 'application/pdf', 'xls' => 'application/excel', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'zip' => 'application/zip', ); header("Content-Disposition: attachment; filename=" . str_replace(' ', '_', basename($file))); header("Content-Type: " . $mimeTypes[getExtension($file)]); header('Cache-Control: max-age=0'); readfile(__FILES__ . $file); die(); } } return true; } /** * Function to upload files & get config for that * * @author Mareks Keišs * @category sysTranslations Controller * @return array of data */ public function getUploadConfig() { $encrypt = new cDefuseCrypto(); $data = array( "script" => "/js/fileupload/php/", "buttonText" => $this->gM('Click to add'), "fileExt" => implode('|', self::$fileExtensions), "scriptData" => array( 'dxcheck' => $encrypt->encrypt(session_id()), 'upload' => $encrypt->encrypt(__CLASS__ . "::getFileUploadConfig"), ), ); return $data; } public static function getFileUploadConfig() { return array( "fileExt" => implode('|', self::$fileExtensions), "sizeLimit" => 6291456, // 6MB 'cms' => 1, 'folder' => self::$_cfg['import']['upload_dir'], //*'preview_dir' => self::$_cfg['img']['preview_dir'], //'preview_size' => self::$_cfg['img']['preview_size'], //'slices' => self::$_cfg['img']['cut'], //'watermark' => self::$_cfg['img']['watermark'], 'separate' => 0, //'onUploadStatic'=> 'cmsProductAttrController::importDocDataFromFile', 'noFileReturn' => 0, 'getExtension' => 0 ); } }