ElixirVault/www/system-brs-core/sys/sysTranslations/inc/sysTranslationsController.php

819 lines
27 KiB
PHP

<?php
namespace BRSystems\Core\Sys\sysTranslations\inc;
use BRSystems\Core\Library\cCore\cCore;
use BRSystems\Core\Library\cDefuseCrypto\cDefuseCrypto;
use BRSystems\Core\Library\cExcel\cExcel;
use BRSystems\Core\Library\cJSON\cJSON;
use BRSystems\Core\Library\cValidator\cValidator;
use BRSystems\Core\Sys\sysLanguages\inc\sysLanguagesModule;
use PHPExcel_Style_Alignment;
use PHPExcel_Style_Border;
use PHPExcel_Style_Fill;
/**
* sysTranslations Controller
*
* @category sysTranslations Controller
* @author Mareks Keišs <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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 <mareks.keiss@brsystems.lv>
* @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
);
}
}