"@f.strName s", 'viewFormat'=>'@f.strViewFormat');
*/
public $listFields = array();
/**
* Record set, that retrieved from DB
* @type link
*/
protected $recSet = null;
/**
* If use group scurity or not
* @type integer
*/
public $nSecOptions = 0;
/**
* Number of record
* @type integer
*/
protected $recNo = 1;
/**
* Id of row
* @type integer
*/
protected $rowId = 0; //fix it
/**
* Array of selected records for delete
* @type array
*/
protected $selectedRecs = array();
/**
* Number of record for delete
* @type integer
*/
protected $recordsDeleted = 0;
/**
* Original table name
* @var string
*/
public $origTName = ""; //fix it
/**
* Fields that used for search on panel, and should be open on every page load
* @type array
*/
public $panelSearchFields = array();
/**
* Array of key's fields
* @type array
*/
public $arrKeyFields = array();
public $audit = null;
/**
* Are there records on first page or not
* @type bool
*/
public $noRecordsFirstPage = false;
/**
* String ?? main table owner's Id
* @type string
*/
public $mainTableOwnerID = "";
/**
* Use print friendly or not
* @type bool
*/
public $printFriendly = false;
/**
* Create login page or not
* @type bool
*/
public $createLoginPage = false;
/**
* Searchpanel class builder
* @type object
*/
protected $searchPanel = null;
/**
* Fields for which span val should be added
* @type array
*/
protected $arrFieldSpanVal = array();
/**
* records weren't deleted due locking
* @type Array
*/
protected $lockDelRec;
public $firstTime = 0;
protected $gMapFields = array();
public $nLoginMethod; //fix it
/**
* Types of all fields in a list row
*/
protected $recordFieldTypes = array(); //fix it
/**
* class names for the fields that were chosen to hide mobile devices
* @type array
*/
protected $hiddenColumnClasses = array();
/**
* Is show add page like popUp or not
* @type boolean
* @intellisense
*/
protected $showAddInPopup = false;
/**
* Is show edit page like popUp or not
* @type boolean
* @intellisense
*/
protected $showEditInPopup = false;
/**
* Is show view page like popUp or not
* @type boolean
* @intellisense
*/
protected $showViewInPopup = false;
/**
* fieldClass function cache
* @type Array
*/
protected $fieldClasses = array();
public $sortBy;
protected $addedDetailsCountSubqueries = array();
protected $recordsRenderData = array();
protected $fieldsWithRawValues = array();
protected $queryCommand = null;
/**
* Constructor, set initial params
* @param array $params
*/
function __construct(&$params)
{
// call parent constructor
parent::__construct($params);
$this->listFields = array();
$allfields = $this->pSet->getPageFields();
foreach($allfields as $f)
{
if(!$this->pSet->appearOnPage($f))
continue;
$fieldTag = $this->pdfJsonMode() ? GoodFieldName($f)."_pdfvalue" : GoodFieldName($f)."_value";
$this->listFields[]= array(
"fName"=>$f,
"goodFieldName"=>GoodFieldName($f),
"valueFieldName" => $fieldTag,
"viewFormat"=>$this->pSet->getViewFormat($f),
"editFormat"=>$this->pSet->getEditFormat($f)
);
}
$this->showAddInPopup = $this->pSet->isShowAddInPopup();
$this->showEditInPopup = $this->pSet->isShowEditInPopup();
$this->showViewInPopup = $this->pSet->isShowViewInPopup();
$this->pSet->setPageType(PAGE_SEARCH);
// Before Process event
$this->beforeProcessEvent();
// Set language params, if have more than one language
$this->setLangParams();
if($this->searchClauseObj) //for asp & .net
$this->jsSettings['tableSettings'][$this->tName]['simpleSearchActive'] = $this->searchClauseObj->simpleSearchActive;
for($i = 0; $i < count($this->allDetailsTablesArr); $i ++)
{
// get perm for det tables
$this->permis[$this->allDetailsTablesArr[$i]['dDataSourceTable']]= $this->getPermissions($this->allDetailsTablesArr[$i]['dDataSourceTable']);
// field names of detail keys of passed detail table, when current is master
$this->detailKeysByD[$i] = $this->pSet->getDetailKeysByDetailTable($this->allDetailsTablesArr[$i]['dDataSourceTable']);
}
$this->genId();
// fill span val indicator for totals
$this->jsSettings['tableSettings'][$this->tName]['totalFields'] = array();
foreach ($this->totalsFields as $tField)
{
$totalFieldData = array('type'=> $tField['totalsType'], 'fName'=> $tField['fName'], 'format'=> $tField['viewFormat']);
if( FORMAT_NUMBER == $tField['viewFormat'] )
$totalFieldData["numberOfDigits"] = $this->pSet->isDecimalDigits( $tField['fName'] );
$this->jsSettings['tableSettings'][ $this->tName ]['totalFields'][] = $totalFieldData;
if ($tField['totalsType'] == 'COUNT')
{
$this->outputFieldValue($tField['fName'], 1);
}
else
{
$this->outputFieldValue($tField['fName'], 2);
}
}
//if scroll body of grid
$this->jsSettings['tableSettings'][$this->tName]['scrollGridBody'] = (( $this->listGridLayout == gltHORIZONTAL || $this->listGridLayout == gltFLEXIBLE )&& $this->isScrollGridBody);
$this->jsSettings['tableSettings'][$this->tName]['permissions'] = $this->permis[$this->tName];
if($this->pSet->getAdvancedSecurityType() == ADVSECURITY_EDIT_OWN)
$this->jsSettings['tableSettings'][$this->tName]['isEditOwn'] = $this->permis[$this->tName];
$this->settingsMap["tableSettings"]['inlineEdit'] = array("default"=>false,"jsName"=>"isInlineEdit", "option" => array("list", "inlineEdit") );
$this->settingsMap["tableSettings"]['inlineAdd'] = array("default"=>false,"jsName"=>"isInlineAdd", "option" => array("list", "inlineAdd"));
$this->settingsMap["tableSettings"]['copy'] = array("default"=>false,"jsName"=>"copy");
$this->settingsMap["tableSettings"]['view'] = array("default"=>false,"jsName"=>"view");
$this->jsSettings['tableSettings'][$this->tName]['listFields'] = array();
for($i=0;$ilistFields);$i++)
{
$this->jsSettings['tableSettings'][$this->tName]['listFields'][] = $this->listFields[$i]['fName'];
// call addGoogleMapData before call proccessRecordValue!!!
if ($this->listFields[$i]['viewFormat'] == FORMAT_MAP)
$this->gMapFields[] = $i;
}
$this->processClickAction();
$this->addPopupLayoutNamesToSettings();
$this->createOrderByObject();
// init setting for params in hash URL for ajax list
if ( $this->listAjax && $this->mode != LIST_DETAILS )
{
$this->pageData['urlParams'] = $this->getUrlParams();
}
// RunnerPage fillTableSettings doesn't work well with listGridLayout key
$this->jsSettings['tableSettings'][ $this->tName ]['listGridLayout'] = $this->listGridLayout;
}
protected function createOrderByObject() {
// read order by info from request
$this->orderClause = OrderClause::createFromPage( $this, true );
}
function processClickAction()
{
if( strtoupper($this->tName) == "ADMIN_MEMBERS" || strtoupper($this->tName) == "ADMIN_ADMEMBERS" )
return;
$clickActionJSON = $this->pSet->getClickActionJSONString();
if( $clickActionJSON != "" )
{
$clickAction = my_json_decode( $clickActionJSON );
foreach ( $clickAction["fields"] as $field => $fSetting )
{
if ( !$this->checkAllowClickAction($fSetting) )
$clickAction["fields"][$field]["action"] = "noaction";
}
if ( !$this->checkAllowClickAction($clickAction["row"]) )
$clickAction["row"]["action"] = "noaction";
$this->jsSettings['tableSettings'][$this->tName]["clickActions"] = $clickAction;
}
}
function checkAllowClickAction( $actionSet )
{
$isActionAllowed = true;
if ( $actionSet["action"] == "open" )
{
switch ($actionSet["openData"]["page"])
{
case 'add':
$isActionAllowed = $this->addAvailable();
break;
case 'edit':
$isActionAllowed = $this->editAvailable();
break;
case 'view':
$isActionAllowed = $this->viewAvailable();
break;
case 'print':
$isActionAllowed = $this->printAvailable();
break;
default:
$isActionAllowed = true;
break;
}
}
return $isActionAllowed;
}
/**
* add Order data for set in URL
*/
function addOrderUrlParam()
{
$urlParams = $this->orderClause->getOrderUrlParams();
if ( strlen($urlParams) > 0 )
{
if ( !isset($this->pageData["urlParams"]) )
$this->pageData["urlParams"] = array();
$this->pageData["urlParams"]["orderby"] = $urlParams;
}
}
/**
* Get list params for using in Url hash (ajax reload)
*/
function getUrlParams()
{
$params = array();
if ( @$_SESSION[$this->sessionPrefix."_qs"] )
{
$params["qs"] = rawurlencode($_SESSION[$this->sessionPrefix."_qs"]);
}
if ( @$_SESSION[$this->sessionPrefix."_q"] )
{
$params["q"] = rawurlencode($_SESSION[$this->sessionPrefix."_q"]);
}
if ( @$_SESSION[$this->sessionPrefix."_criteriaSearch"] && $_SESSION[$this->sessionPrefix."_criteriaSearch"] != "and" )
{
$params["criteria"] = $_SESSION[$this->sessionPrefix."_criteriaSearch"];
}
if ( @$_SESSION[$this->sessionPrefix."_filters"] )
{
$params["f"] = rawurlencode($_SESSION[$this->sessionPrefix."_filters"]);
}
if( !postvalue("qs") && !postvalue("q") && !isset( $_REQUEST["f"] ) && @$_SESSION[$this->sessionPrefix."_pagenumber"] && @$_SESSION[$this->sessionPrefix."_pagenumber"] > 1 )
{
$params["goto"] = $_SESSION[$this->sessionPrefix."_pagenumber"];
}
if( @$_SESSION[$this->sessionPrefix."_pagesize"] && $this->gPageSize != $_SESSION[$this->sessionPrefix."_pagesize"])
{
$params["pagesize"] = $_SESSION[$this->sessionPrefix."_pagesize"];
}
if( $this->masterTable )
{
$params["mastertable"] = $this->masterTable;
for($i = 1; $i <= count($this->masterKeysReq); $i++)
{
$params["masterkey".$i] = $this->masterKeysReq[$i];
}
}
if( @$_SESSION[$this->sessionPrefix."_masterpage"] )
{
$params["masterpage"] = $_SESSION[$this->sessionPrefix."_masterpage"];
}
if( $this->searchClauseObj )
{
if( $this->searchClauseObj->savedSearchIsRun )
$params["savedSearch"] = true;
}
$tabId = $this->getCurrentTabId();
if( strlen( $tabId ) )
$params["tab"] = rawurlencode( $tabId );
return $params;
}
/**
* Add array popupPagesLayoutNames data to the current table settings
* if it makes sense
*/
protected function addPopupLayoutNamesToSettings()
{
$layoutNames = $this->pSet->getPopupPagesLayoutNames();
if( count( $layoutNames ) )
$this->jsSettings['tableSettings'][$this->tName]['popupPagesLayoutNames'] = $this->pSet->getPopupPagesLayoutNames();
}
/**
* Add common html code for all modes on list page
*/
function addCommonHtml()
{
if ( !$this->isDashboardElement() && !$this->mobileTemplateMode() && !$this->pdfJsonMode() )
$this->body["begin"].= "
";
if($this->is508) {
$this->body["begin"].= "makeClassName("s508")."\">".##message 508_SKIP_DATA##."";
$this->body["begin"].= "makeClassName("s508")."\">".##message 508_SKIP_MENU##."";
$this->body["begin"].= "makeClassName("s508")."\">".##message 508_SKIP_SEARCH##."";
$this->body["begin"].= "makeClassName("s508")."\">".##message 508_HELP##."";
}
//prepare for dispaly master table info on details table
$this->displayMasterTableInfo();
}
/**
* Add common javascript files and code
*/
function addCommonJs()
{
parent::addCommonJs();
$this->addJsForGrid();
// add button events if exist
$this->addButtonHandlers();
##if @BUILDER.m_strRTEType==RTE_CK##
$addPSet = new ProjectSettings($this->tName, PAGE_ADD);
$editPSet = new ProjectSettings($this->tName, PAGE_EDIT);
for($i=0;$ilistFields);$i++)
{
if($this->pSet->appearOnInlineAdd($this->listFields[$i]['fName']) && $addPSet->isUseRTE($this->listFields[$i]['fName'])
|| $this->pSet->appearOnInlineEdit($this->listFields[$i]['fName']) && $editPSet->isUseRTE($this->listFields[$i]['fName']))
{
$this->AddJSFile("plugins/ckeditor/ckeditor.js");
break;
}
}
##endif##
if( $this->allDetailsTablesArr )
{
$this->AddCSSFile("include/jquery-ui/smoothness/jquery-ui.min.css");
$this->AddCSSFile("include/jquery-ui/smoothness/jquery-ui.theme.min.css");
}
}
/**
* Add javascript code for grid
*/
function addJsForGrid()
{
if( $this->isResizeColumns )
$this->prepareForResizeColumns();
if( $this->reorderFieldsFeatureEnabled() && $this->isBootstrap() )
{
$this->AddJSFile( 'include/jquery.dragtable.js' );
}
$this->jsSettings['tableSettings'][$this->tName]['showRows'] = ($this->numRowsFromSQL ? true : false);
$this->initGmaps();
}
/**
* If use resizable columns
* Prepare for resize main table
*/
function prepareForResizeColumns()
{
if( $this->isBootstrap() )
{
$this->AddJSFile( 'include/colresizable.js' );
return;
}
if( $this->mode != LIST_AJAX )
{
if( $this->debugJSMode === true )
$this->AddJSFile("include/runnerJS/RunnerResizeGrid.js");
}
}
/**
* Process master key value from request params
* For DPInline mode and use this mode on edit or add page
*/
function processMasterKeyValue()
{
parent::processMasterKeyValue();
// reset search and page number
$_SESSION[$this->sessionPrefix."_search"] = 0;
if($this->firstTime)
$_SESSION[$this->sessionPrefix."_pagenumber"] = 1;
}
/**
* Add event before process list
*/
function beforeProcessEvent()
{
if($this->eventExists("BeforeProcessList"))
$this->eventsObject->BeforeProcessList( $this );
}
/**
* Set session variables
*/
function setSessionVariables()
{
parent::setSessionVariables();
if( $this->searchClauseObj )
{
if( $this->searchClauseObj->isSearchFunctionalityActivated() )
{
// if search used serialize clause object
$_SESSION[$this->sessionPrefix.'_advsearch'] = serialize($this->searchClauseObj);
}
else
{
// Unset session for search if search not used
unset($_SESSION[$this->sessionPrefix.'_advsearch']);
}
// Unset session for filters if filters not activated
if(!$this->searchClauseObj->filtersActivated)
unset($_SESSION[$this->sessionPrefix.'_filters']);
}
else
{
unset($_SESSION[$this->sessionPrefix.'_advsearch']);
unset($_SESSION[$this->sessionPrefix.'_filters']);
}
//set session goto
if(@$_REQUEST["goto"])
$_SESSION[$this->sessionPrefix."_pagenumber"]= @$_REQUEST["goto"];
// page number
$this->myPage =(integer) $_SESSION[$this->sessionPrefix."_pagenumber"];
if(! $this->myPage)
$this->myPage = 1;
//set page size
if(!$this->pageSize)
$this->pageSize = $this->gPageSize;
if( $this->pdfJsonMode() ) {
$this->pageSize = -1;
}
}
protected function assignColumnHeaderClasses()
{
for($i = 0; $i < count($this->listFields); $i ++)
{
$field = $this->listFields[$i]['fName'];
$goodName = GoodFieldname($field);
// add class for field header as field value
$fieldClassStr = $this->fieldClass($field);
// add class for mobile columns hiding
if( isset( $this->hiddenColumnClasses[$goodName] ) )
$fieldClassStr .= " ".$this->hiddenColumnClasses[$goodName ];
$this->xt->assign(GoodFieldName($field)."_class", $fieldClassStr);
$this->xt->assign(GoodFieldName($field)."_align", $this->fieldAlign($field));
}
}
/**
* @return Boolean
*/
public function isReoderByHeaderClickingEnabled()
{
return true;
}
/**
* Delete selected records
*/
function deleteRecords()
{
global $globalEvents;
if( @$_REQUEST["a"] != "delete" )
return;
$message_class = "alert-warning";
$this->deleteMessage = "";
if(@$_REQUEST["mdelete"])
{
foreach(@$_REQUEST["mdelete"] as $ind)
{
$selectedKeys = array();
for($i = 0; $i < count($this->arrKeyFields); $i ++)
{
$selectedKeys[ $this->arrKeyFields[$i] ] = refine($_REQUEST["mdelete".($i + 1)][mdeleteIndex($ind)]);
}
$this->selectedRecs[] = $selectedKeys;
}
}
elseif(postvalue( "selection" ))
{
foreach( postvalue( "selection" ) as $keyblock)
{
$arr = explode("&", refine($keyblock));
if(count($arr) < count($this->arrKeyFields))
continue;
$selectedKeys = array();
for($i = 0; $i < count($this->arrKeyFields); $i ++)
{
$selectedKeys[ $this->arrKeyFields[$i] ]= urldecode(@$arr[$i]);
}
$this->selectedRecs[] = $selectedKeys;
}
}
$this->recordsDeleted = 0;
$this->lockDelRec = array();
foreach($this->selectedRecs as $keys)
{
$where = KeyWhere($keys, $this->tName);
$mandatoryWhere = array();
$mandatoryWhere[]= $where;
// delete only owned records
if($this->nSecOptions != ADVSECURITY_ALL && $this->nLoginMethod == SECURITY_TABLE && $this->createLoginPage)
{
$where = whereAdd($where, $this->SecuritySQL("Delete" ) );
$mandatoryWhere[] = $this->SecuritySQL("Delete" );
}
$sqlParts = $this->gQuery->getSqlComponents();
$selectSQL = SQLQuery::buildSQL( $sqlParts, $mandatoryWhere );
$strSQL = "delete from ".$this->connection->addTableWrappers( $this->origTName )." where ".$where;
$retval = true;
$deletedqResult = $this->connection->query( SQLQuery::buildSQL($sqlParts, $mandatoryWhere ) );
$deleted_values = $this->cipherer->DecryptFetchedArray( $deletedqResult->fetchAssoc() );
if($globalEvents->exists("IsRecordEditable", $this->tName))
{
if(!$globalEvents->IsRecordEditable($deleted_values, true, $this->tName))
continue;
}
if($this->eventExists("BeforeDelete"))
{
RunnerContext::pushRecordContext( $deleted_values, $this );
$tdeleteMessage = $this->deleteMessage;
$retval = $this->eventsObject->BeforeDelete($where, $deleted_values, $tdeleteMessage, $this);
$this->deleteMessage = $tdeleteMessage;
RunnerContext::pop();
}
$lockRecord = false;
if($this->lockingObj)
{
$lockWhere = array();
foreach($keys as $keysvalue)
{
$lockWhere[] = rawurlencode($keysvalue);
}
if( $this->lockingObj->isLocked( $this->origTName, implode("&", $lockWhere), "1" ) )
{
$lockRecord = true;
$this->lockDelRec[] = $keys;
}
if( $this->mode == LIST_SIMPLE )
$_SESSION[$this->sessionPrefix."_lockDelRec"] = $this->lockDelRec;
}
if(!$lockRecord && @$_REQUEST["a"] == "delete" && $retval)
{
$this->recordsDeleted ++;
// delete associated uploaded files if any
DeleteUploadedFiles($this->pSet, $deleted_values);
LogInfo($strSQL);
$this->connection->exec( $strSQL );
if($this->audit && $deleted_values)
{
$fieldsList = $this->pSet->getFieldsList();
$i=0;
foreach($deleted_values as $key=>$value)
{
if( IsBinaryType( $this->pSet->getFieldType($fieldsList[$i]) ) )
$deleted_audit_values[ $fieldsList[$i] ] = $value;
else
$deleted_audit_values[ $key ] = $value;
$i++;
}
$this->audit->LogDelete($this->tName, $deleted_audit_values, $keys);
}
##if @BUILDER.m_bDynamicPermissions && @BUILDER.nLoginMethod==SECURITY_TABLE##
if( $this->tName == ADMIN_USERS )
{
// delete _ugmembers corr. rec.
global $cman;
$grConnection = $cman->getForUserGroups();
$sql = "delete from ". $grConnection->addTableWrappers( "##@BUILDER.strUGMembers s##" )
." where ". $grConnection->comparisonSQL(
$grConnection->addFieldWrappers( "##@BUILDER.members_username s##" ),
$grConnection->prepareString( $deleted_values[ GetUserNameField() ] ),
$this->pSet->isCaseInsensitiveUsername()
);
$grConnection->exec( $sql );
}
##endif##
if($this->eventExists("AfterDelete"))
{
RunnerContext::pushRecordContext( $deleted_values, $this );
$tdeleteMessage = $this->deleteMessage;
$this->eventsObject->AfterDelete($where, $deleted_values,$tdeleteMessage, $this);
$this->deleteMessage = $tdeleteMessage;
RunnerContext::pop();
$message_class = "alert-info";
}
}
if (strlen($this->deleteMessage))
{
$this->xt->assignbyref("message", $this->deleteMessage);
$this->xt->assignbyref( "message_class", $message_class );
$this->xt->assign("message_block",true);
}
}
if( count($this->selectedRecs) && $this->eventExists("AfterMassDelete") )
$this->eventsObject->AfterMassDelete($this->recordsDeleted, $this);
}
/**
* PRG rule, to avoid POSTDATA resend
*/
function rulePRG()
{
if( $this->stopPRG )
return false;
if(no_output_done() && count($this->selectedRecs) && !strlen($this->deleteMessage))
{
$getParams = "a=return";
if ( postvalue("page") )
$getParams .= "&page=" . postvalue("page");
// redirect, add a=return param for saving SESSION
HeaderRedirect($this->shortTableName, $this->getPageType(), $getParams);
// turned on output buffering, so we need to stop script
exit();
}
}
/**
* Add code from program before show list
*/
function BeforeShowList()
{
if($this->eventExists("BeforeShowList"))
{
$templatefile = $this->templatefile;
$this->eventsObject->BeforeShowList($this->xt, $templatefile, $this);
$this->templatefile = $templatefile;
}
}
/**
* Common assign for diferent mode on list page
* Branch classes add to this method its individualy code
*/
function commonAssign()
{
parent::commonAssign();
$this->xt->assign("id", $this->id);
$this->xt->assignbyref("body", $this->body);
$this->xt->assign("newrecord_controls_block", $this->inlineAddAvailable() || $this->addAvailable() );
if( ( $this->isDispGrid() || $this->listAjax ) && (
$this->printAvailable()
|| $this->exportAvailable()
|| $this->deleteAvailable()
|| $this->updateSelectedAvailable()
|| $this->inlineEditAvailable()
|| $this->inlineAddAvailable()
|| $this->showAddInPopup && $this->addAvailable()
)
)
{
$this->xt->assign("record_controls_block", true);
}
if( $this->numRowsFromSQL == 0 )
$this->hideElement("recordcontrol");
// add link
if( $this->addAvailable() )
{
$this->xt->assign("add_link", true);
$add_attrs = 'id="addButton'.$this->id.'"';
if( !$this->isPD() )
{
$add_attrs .= ' href="'.GetTableLink($this->shortTableName, "add") . '"';
}
$this->xt->assign("addlink_attrs", $add_attrs);
if ( $this->dashTName )
{
$this->xt->assign("addlink_getparams", "?fromDashboard=" . $this->dashTName);
}
}
// inline add link
$this->inlineAddLinksAttrs();
if($this->isShowMenu() || $this->isAdminTable())
$this->xt->assign("quickjump_attrs", 'class="'.$this->makeClassName("quickjump").'"');
foreach ($this->googleMapCfg['mainMapIds'] as $mapId)
{
$this->xt->assign_event($mapId, $this, 'createMapDiv', array('mapId'=>$mapId, 'width'=>$this->googleMapCfg['mapsData'][$mapId]['width'], 'height'=>$this->googleMapCfg['mapsData'][$mapId]['height']));
}
$this->assignSortByDropdown();
//add assign for grid block
$this->addAssignForGrid();
$this->xt->assign("grid_block", true);
//select all link and attr
$this->selectAllLinkAttrs();
//edit selected link and attr
$this->editSelectedLinkAttrs();
//update selected link and attr
$this->updateSelectedLinkAttrs();
//save all link, attr, span
$this->saveAllLinkAttrs();
//cansel all link, attr, span
$this->cancelAllLinkAttrs();
$this->assignDetailsTablesBadgeColors();
$this->hideItemType("details_preview");
$this->hideItemType("grid_inline_save");
$this->hideItemType("grid_inline_cancel");
}
/**
* Common assign for grid block in diferent mode on list page
*/
function addAssignForGrid()
{
if( !$this->isDispGrid() )
return;
if($this->is508)
{
if( $this->isBootstrap() && $this->listGridLayout == gltVERTICAL )
$this->xt->assign_section("grid_header", "Table data
", "");
else
$this->xt->assign_section("grid_header", "Table data", "");
}
$this->xt->assign("endrecordblock_attrs", "colid=\"endrecord\"");
for($i = 0; $i < count($this->listFields); $i ++)
{
$this->xt->assign(GoodFieldName($this->listFields[$i]['fName'])."_fieldheadercolumn", true);
$this->xt->assign(GoodFieldName($this->listFields[$i]['fName'])."_fieldcolumn", true);
$this->xt->assign(GoodFieldName($this->listFields[$i]['fName'])."_fieldfootercolumn", true);
}
$colsonpage = $this->recsPerRowList;
$record_header = array("data" => array());
$record_footer = array("data" => array());
if ($colsonpage > $this->recordsOnPage && $this->recordsOnPage && $this->listGridLayout != gltVERTICAL){
$colsonpage = $this->recordsOnPage;
}
if( $this->isPD() ) {
$colsonpage = 1;
}
for($i = 0; $i < $colsonpage; $i ++)
{
$rheader = array();
$rfooter = array();
if($i < $colsonpage - 1)
{
$rheader["endrecordheader_block"] = true;
$rfooter["endrecordfooter_block"] = true;
}
$record_header["data"][] = $rheader;
$record_footer["data"][] = $rfooter;
}
$this->xt->assignbyref("record_header", $record_header);
$this->xt->assignbyref("record_footer", $record_footer);
$this->xt->assign("grid_header", true);
$this->xt->assign("grid_footer", true);
// hiding header, if no rows
if(!$this->numRowsFromSQL){
$this->xt->assign("gridHeader_class", " ".$this->makeClassName("hiddenelem"));
$this->xt->assign("gridFooter_class", "r-grid-footer ".$this->makeClassName("hiddenelem"));
}
// moved from search panel
$gridTableStyle = "";
$gridTableStyle = 'style="';
$gridTableStyle .= $this->recordsOnPage>0 ? '"' : 'width: 50%;"';
$this->xt->assign('gridTable_attrs', $gridTableStyle);
//checkbox column
$this->checkboxColumnAttrs();
if( $this->editAvailable() )
{
$this->xt->assign("edit_column", true);
$this->xt->assign("edit_headercolumn", true);
$this->xt->assign("edit_footercolumn", true);
}
if( $this->inlineEditAvailable() )
{
$this->xt->assign("inlineedit_column", true);
$this->xt->assign("inlineedit_headercolumn", true);
$this->xt->assign("inlineedit_footercolumn", true);
}
if( $this->inlineEditAvailable() || $this->inlineAddAvailable() )
{
$this->xt->assign("inline_cancel", true);
$this->xt->assign("inline_save", true);
}
//copy link
if( $this->copyAvailable() )
$this->xt->assign("copy_column", true);
//view column
if( $this->displayViewLink() )
$this->xt->assign("view_column", true);
//for list icons instead of list links
$this->assignListIconsColumn();
if( $this->detailsInGridAvailable() )
{
$this->xt->assign(GoodFieldName($this->tName)."_dtable_column", true);
$this->xt->assign("dtables_link", true);
}
//delete link and attr
$this->deleteSelectedLink();
}
function createMapDiv(&$params)
{
if( $this->isPD() )
$div = '';
else
$div = '';
echo $div;
}
/**
* Show import link
* Add import link attributes
*/
function importLinksAttrs()
{
$this->xt->assign("import_link", $this->permis[$this->tName]['import']);
$this->xt->assign("importlink_attrs", "id=\"import_".$this->id."\" name=\"import_".$this->id."\"");
}
/**
* Show inline add link
* Add inline add attributes
*/
function getInlineAddLinksAttrs()
{
return "name=\"inlineAdd_".$this->id."\" href='".
GetTableLink( $this->shortTableName, "add", $this->getStateUrlParams() )."' id=\"inlineAdd".$this->id."\"";
}
function getAddLinksAttrs()
{
return "href='".GetTableLink($this->shortTableName, "add")."' id=\"addButton".$this->id."\"";
}
function inlineAddLinksAttrs()
{
if( !$this->inlineAddAvailable() )
return;
//inline add link and attr
$this->xt->assign("inlineadd_link", true );
$this->xt->assign("inlineaddlink_attrs", $this->getInlineAddLinksAttrs() );
}
/**
* Assign selectAll link and attrs
*/
function selectAllLinkAttrs()
{
$this->xt->assign("selectall_link", $this->deleteAvailable() || $this->permis[$this->tName]['export']|| $this->permis[$this->tName]['edit']);
$this->xt->assign("selectalllink_span", $this->buttonShowHideStyle());
$this->xt->assign("selectalllink_attrs",
"name=\"select_all".$this->id."\"
id=\"select_all".$this->id."\"
href=\"#\"");
}
/**
* Assign checkbox column, header and header attrs
*/
function checkboxColumnAttrs()
{
$showColumn = $this->deleteAvailable() || $this->exportAvailable() || $this->inlineEditAvailable() || $this->printAvailable() || $this->updateSelectedAvailable();
$this->xt->assign("checkbox_column", $showColumn);
$this->xt->assign("checkbox_header", true);
$this->xt->assign("checkboxheader_attrs", "id=\"chooseAll_".$this->id."\" class=\"chooseAll".$this->id."\"");
}
/**
* Get common attrs for Print and Export links
*/
function getPrintExportLinkAttrs($page)
{
if(!$page)
return '';
return "name=\"".$page."_selected".$this->id."\"
id=\"".$page."_selected".$this->id."\"
href = '".GetTableLink($this->shortTableName, $page)."'";
}
/**
* Show or hide current button
*/
function buttonShowHideStyle($link="")
{
if($link == 'saveall' || $link == 'cancelall')
return ' style="display:none;" ';
return $this->numRowsFromSQL > 0 ? '' : ' style="display:none;" ';
}
/**
* Assign editSelected link and attrs
*/
function editSelectedLinkAttrs()
{
if( !$this->inlineEditAvailable() )
return;
$this->xt->assign("editselected_link", true );
$this->xt->assign("editselectedlink_span", $this->buttonShowHideStyle());
$this->xt->assign("editselectedlink_attrs","
href='".GetTableLink($this->shortTableName, "edit")."'
name=\"edit_selected".$this->id."\"
id=\"edit_selected".$this->id."\"");
}
function updateSelectedLinkAttrs()
{
if( !$this->updateSelectedAvailable() )
return;
$this->xt->assign("updateselected_link", true );
$this->xt->assign("updateselectedlink_attrs", $this->getUpdateSelectedAttrs() . $this->buttonShowHideStyle() );
}
protected function getUpdateSelectedAttrs()
{
<<<<<<< .working
return "href='".GetTableLink($this->shortTableName, "edit")."' name=\"update_selected".$this->id."\" id=\"update_selected".$this->id."\"";
||||||| .merge-left.r34343
return "href='".GetTableLink($this->shortTableName, "edit")."' name=\"update_selected".$this->id."\" id=\"update_selected".$this->id."\"";
=======
if( $this->isPD() )
return " name=\"update_selected".$this->id."\" id=\"update_selected".$this->id."\"";
return "href='".GetTableLink($this->shortTableName, "edit")."' name=\"update_selected".$this->id."\" id=\"update_selected".$this->id."\"";
>>>>>>> .merge-right.r34358
}
/**
* Assign saveAll link and attrs
*/
function saveAllLinkAttrs()
{
$this->xt->assign("saveall_link",$this->permis[$this->tName]['edit'] || $this->permis[$this->tName]['add']);
$this->xt->assign("savealllink_span",$this->buttonShowHideStyle('saveall'));
$this->xt->assign("savealllink_attrs","name=\"saveall_edited".$this->id."\" id=\"saveall_edited".$this->id."\"");
}
/**
* Assign cancelAll link and attrs
*/
function cancelAllLinkAttrs()
{
$this->xt->assign("cancelall_link",$this->permis[$this->tName]['edit'] || $this->permis[$this->tName]['add']);
$this->xt->assign("cancelalllink_span",$this->buttonShowHideStyle('cancelall'));
$this->xt->assign("cancelalllink_attrs","name=\"revertall_edited".$this->id."\" id=\"revertall_edited".$this->id."\"");
}
/**
* Assign delete selected link
*/
function deleteSelectedLink()
{
if( !$this->deleteAvailable() )
return;
$this->xt->assign("deleteselected_link", true );
$this->xt->assign("deleteselectedlink_span", $this->buttonShowHideStyle());
$this->xt->assign("deleteselectedlink_attrs", $this->getDeleteLinksAttrs());
}
function getDeleteLinksAttrs()
{
return "id=\"delete_selected".$this->id."\" name=\"delete_selected".$this->id."\" ";
}
function getEditLinksAttrs()
{
return "id=\"edit_selected".$this->id."\" name=\"edit_selected".$this->id."\" ";
}
function getFormInputsHTML()
{
return '';
}
function getFormTargetHTML()
{
return '';
}
/**
* Seeks recs, depending on page number etc.
* @param string $strSQL
*/
protected function seekPageInRecSet( $strSQL )
{
$listarray = false;
if( $this->eventExists("ListQuery") )
{
$orderData = $this->orderClause->getListQueryData();
$listarray = $this->eventsObject->ListQuery( $this->searchClauseObj, $orderData["fieldsForSort"], $orderData["howToSortData"],
$this->masterTable, $this->masterKeysReq, null, $this->pageSize, $this->myPage, $this );
}
if( $listarray !== false )
$this->recSet = $listarray;
else
$this->recSet = $this->connection->queryPage( $strSQL, $this->myPage, $this->pageSize, $this->maxPages > 1 );
}
protected function getSubsetSQLComponents() {
$sql = parent::getSubsetSQLComponents();
if( $this->connection->dbType == nDATABASE_DB2 )
$sql["sqlParts"]["head"] .= ", ROW_NUMBER() over () as DB2_ROW_NUMBER ";
// security
$sql["mandatoryWhere"][] = $this->SecuritySQL("Search" );
// no records on first page
if( $this->mode != LIST_DETAILS && $this->noRecordsFirstPage && !$this->isSearchFunctionalityActivated() )
$sql["mandatoryWhere"][] = "1=0";
// add details subqueries
$detailsSubqueries = $this->getMasterDetailSubQuery();
if( $detailsSubqueries )
$sql["sqlParts"]["head"] .= ", " . implode( ", ", $detailsSubqueries );
return $sql;
}
public function getOrderByClause()
{
// use builtin orderClause object
return $this->orderClause->getOrderByExpression();
}
/**
* Builds SQL query, for retrieve data from DB
*/
function buildSQL()
{
$sql = $this->getSubsetSQLComponents();
// build SQL
$strSQL = SQLQuery::buildSQL( $sql["sqlParts"], $sql["mandatoryWhere"], $sql["mandatoryHaving"], $sql["optionalWhere"], $sql["optionalHaving"] );
$countSQL = $strSQL;
$strOrderBy = $this->getOrderByClause();
$strSQL.= " ".trim( $strOrderBy );
// do Before SQL Query event
$strSQLbak = $strSQL;
$sqlModifiedInEvent = false;
$whereModifiedInEvent = false;
$orderbyModifiedInEvent = false;
if( $this->eventsObject->exists("BeforeQueryList") )
{
$tstrWhereClause = SQLQuery::combineCases( array(
SQLQuery::combineCases( $sql["mandatoryWhere"], "and" ),
SQLQuery::combineCases( $sql["optionalWhere"], "or" )
), "and" );
$strWhereBak = $tstrWhereClause;
$tstrOrderBy = $strOrderBy;
$this->eventsObject->BeforeQueryList($strSQL, $tstrWhereClause, $tstrOrderBy, $this);
$whereModifiedInEvent = ( $tstrWhereClause != $strWhereBak );
$orderbyModifiedInEvent = ( $tstrOrderBy != $strOrderBy );
$sqlModifiedInEvent = ( $strSQL != $strSQLbak );
$strOrderBy = $tstrOrderBy;
// Rebuild SQL if needed
if( $sqlModifiedInEvent )
{
// changed $strSQL - old style
$this->numRowsFromSQL = GetRowCount($strSQL, $this->connection);
}
else if( $whereModifiedInEvent )
{
$strSQL = SQLQuery::buildSQL($sql["sqlParts"], array( $tstrWhereClause ), $sql["mandatoryHaving"] );
$countSQL = $strSQL;
$strSQL.= " ".trim( $strOrderBy );
}
else if( $orderbyModifiedInEvent )
{
$strSQL = SQLQuery::buildSQL($sql["sqlParts"], $sql["mandatoryWhere"], $sql["mandatoryHaving"], $sql["optionalWhere"], $sql["optionalHaving"] );
$countSQL = $strSQL;
$strSQL.= " ".trim( $strOrderBy );
}
}
// custom GetRowCount event:
$rowcount = false;
if($this->eventExists("ListGetRowCount"))
{
$rowcount = $this->eventsObject->ListGetRowCount($this->searchClauseObj, $this->masterTable, $this->masterKeysReq, null, $this);
if( $rowcount !== false )
$this->numRowsFromSQL = $rowcount;
}
// normal mode row count
if( $rowcount === false && !$sqlModifiedInEvent )
{
$this->numRowsFromSQL = $this->connection->getFetchedRowsNumber( $countSQL );
}
$this->numRowsFromSQL = $this->limitRowCount( $this->numRowsFromSQL );
// check if we need to count details number using a sub-query when numRowsFromSQL prop is calculated
if( $this->useDetailsCountBySubquery() )
{
// rebuild SQL query to add a details counting sub-query #12991
// when numRowsFromSQL isn't set the sub-query doesn't go to SQLComponents subset
$sql = $this->getSubsetSQLComponents();
$strSQL = SQLQuery::buildSQL( $sql["sqlParts"], $sql["mandatoryWhere"], $sql["mandatoryHaving"], $sql["optionalWhere"], $sql["optionalHaving"] );
$strSQL.= " ".trim( $this->getOrderByClause() );
}
LogInfo($strSQL);
$this->querySQL = $strSQL;
}
/**
* Returns array of subqueries for counting details records
* These queries should be added to the select-list of the main SQL query
* @return Array
*/
protected function getMasterDetailSubQuery()
{
if( $this->numRowsFromSQL == 0 )
return array();
$ret = array();
for($i = 0; $i < count($this->allDetailsTablesArr); $i++)
{
$detailData = $this->allDetailsTablesArr[$i];
$dataSourceTName = $detailData['dDataSourceTable'];
if( !$this->pSet->detailsShowCount( $dataSourceTName ) && !$this->pSet->detailsHideEmpty( $dataSourceTName ) )
continue;
if( !$this->isDetailTableSubquerySupported( $dataSourceTName, $i ) )
continue;
$detailsSettings = $this->pSet->getTable($dataSourceTName);
$detailsQuery = $detailsSettings->getSQLQuery();
$detailsSqlWhere = $detailsQuery->WhereToSql();
$masterWhere = "";
foreach($this->masterKeysByD[$i] as $idx => $val)
{
if($masterWhere)
$masterWhere.= " and ";
$masterWhere.= $this->cipherer->GetFieldName( $this->connection->addTableWrappers("subQuery_cnt")."."
.$this->connection->addFieldWrappers($this->detailKeysByD[$i][$idx]), $this->masterKeysByD[$i][$idx] )
."=".$this->cipherer->GetFieldName( $this->connection->addTableWrappers($this->origTName)."."
.$this->connection->addFieldWrappers($this->masterKeysByD[$i][$idx]), $this->masterKeysByD[$i][$idx] );
}
// add a key field to the select list
$subQ = "";
foreach($this->detailKeysByD[$i] as $k)
{
if( strlen($subQ) )
$subQ.= ",";
$subQ.= RunnerPage::_getFieldSQL($k, $this->connection, $detailsSettings);
}
$subQ = "SELECT ".$subQ." ".$detailsQuery->FromToSql();
// add security where clause for sub query
$securityClause = SecuritySQL("Search", $dataSourceTName);
if( strlen($securityClause) )
$subQ.= " WHERE ".whereAdd($detailsSqlWhere, $securityClause);
elseif( strlen($detailsSqlWhere) )
$subQ.= " WHERE ".whereAdd("", $detailsSqlWhere);
$subQ.= " ".$detailsQuery->GroupByHavingToSql();
$countsql = "SELECT count(*) FROM (".$subQ.") ".$this->connection->addTableWrappers("subQuery_cnt")." WHERE ".$masterWhere;
$ret[] = "(".$countsql.") as ".$this->connection->addFieldWrappers( $dataSourceTName."_cnt" );
$this->addedDetailsCountSubqueries[ $dataSourceTName ] = true;
}
return $ret;
}
/**
* Check if its possible to add to the main table query a subquery that contes the number of details. #9875
* @param String dDataSourceTable The detail datasource table name
* @param Number dTableIndex The detail table index in the allDetailsTablesArr prop
* @return Boolean
*/
protected function isDetailTableSubquerySupported( $dDataSourceTName, $dTableIndex )
{
global $cman, $bSubqueriesSupported;
return $bSubqueriesSupported
&& $this->connection->checkDBSubqueriesSupport()
&& $cman->checkTablesSubqueriesSupport( $this->tName, $dDataSourceTName )
&& $this->checkfDMLinkFieldsOfTheSameType( $dDataSourceTName, $dTableIndex )
&& !$this->gQuery->HasJoinInFromClause();
}
/**
* Check if to add a details counting sub-query to the page's sql-query
* @return Boolean
*/
protected function useDetailsCountBySubquery()
{
// mind ASP conversion before modifying this code!!!
$manyPages = false;
if( $this->numRowsFromSQL > 0 )
$manyPages = ($this->pageSize / $this->numRowsFromSQL < 0.1);
return count($this->allDetailsTablesArr) > 0 &&
( max($this->pageSize, $this->numRowsFromSQL) <= 20
|| $manyPages )
&& !$this->eventExists("BeforeQueryList")
&& !$this->eventExists("ListGetRowCount");
}
/**
* #12351
* Check if a sub-query counting a number of details is added to the page's SQL-query
* @param String table The detail datasource table name
* @return Boolean
*/
protected function isDetailTableSubqueryApplied( $table )
{
return $this->addedDetailsCountSubqueries[ $table ];
}
/**
* Check if detail and master tables' link fields have the same type.
* They must be of the same type (for not mySQL databases)
* to add a subquery counting the number of detais for each record.
*
* @param String dDataSourceTable The detail datasource table name
* @param Number dTableIndex The detail table index in the allDetailsTablesArr prop
* @return Boolean
*/
protected function checkfDMLinkFieldsOfTheSameType( $dDataSourceTName, $dTableIndex )
{
if( $this->allDetailsTablesArr[ $dTableIndex ]['dDataSourceTable'] != $dDataSourceTName )
return false;
if( $this->connection->dbType == nDATABASE_MySQL )
return true;
foreach($this->masterKeysByD[ $dTableIndex ] as $idx => $val)
{
// get field types
$masterLinkFieldType = $this->pSet->getFieldType( $this->masterKeysByD[ $dTableIndex ][ $idx ] );
$detailLinkFieldType = $this->pSet->getFieldType( $this->detailKeysByD[ $dTableIndex ][ $idx ] );
// if different data types we can't use subQ
if( $masterLinkFieldType != $detailLinkFieldType )
return false;
}
return true;
}
/**
* @return Boolean
*/
protected function isInlineAreaToSet()
{
return $this->inlineAddAvailable() || $this->addAvailable() && $this->showAddInPopup;
}
/**
* Fills info in array about grid.
* For new add row
* @param array $rowInfoArr array with total info, that assignes grid
*/
function prepareInlineAddArea(&$rowInfoArr)
{
$rowInfoArr["data"]= array();
if( !$this->isInlineAreaToSet() )
return;
$editlink = "";
$copylink = "";
// add inline add row
$row = array();
$row["rowattrs"] = "data-pageid=\"" . $this->id . "\"";
$row["rowclass"] = "gridRowAdd ".$this->makeClassName("hiddenelem");
$row["rsclass"] = "gridRowSepAdd ".$this->makeClassName("hiddenelem");
if($this->listGridLayout == gltVERTICAL)
$row["rowattrs"] .= "vertical=\"1\"";
$record = array();
$record["recId"] = "add";
$record["edit_link"]= true;
$record["inlineedit_link"]= true;
$record["view_link"]= true;
$record["copy_link"]= true;
$record["checkbox"]= true;
$record["editlink_attrs"]= "id=\"editLink_add".$this->id."\" data-gridlink";
$record["copylink_attrs"]= "id=\"copyLink_add".$this->id."\" name=\"copyLink_add".$this->id."\" data-gridlink";
$record["viewlink_attrs"]= "id=\"viewLink_add".$this->id."\" name=\"viewLink_add".$this->id."\" data-gridlink";
$record["checkbox_attrs"]= "id=\"check_add".$this->id."\" name=\"selection[]\"";
// add container for inline add controls
if( $this->inlineEditAvailable() )
{
$record["inlineeditlink_attrs"]= "id=\"iEditLink_add".$this->id."\" ";
}
$record["inlinesavelink_attrs"]= "id=\"saveLink_add".$this->id."\" href=#";
$record["inlinerevertlink_attrs"]= "id=\"revertLink_add".$this->id."\" href=#";
$record["ieditbuttonsholder_attrs"]= "id=\"ieditbuttonsholder".$this->id."\" ";
if( $this->detailsInGridAvailable() )
$record["dtables_link"] = true;
$hideDPLink = false;
for($i = 0; $i < count($this->allDetailsTablesArr); $i ++)
{
//detail tables
$dDataSourceTable = $this->allDetailsTablesArr[$i]['dDataSourceTable'];
$dShortTable = $this->allDetailsTablesArr[$i]['dShortTable'];
$record[$dShortTable."_dtable_link"]=($this->permis[$dDataSourceTable]['add'] || $this->permis[$dDataSourceTable]['search']);
if( $this->pSet->detailsShowCount( $dDataSourceTable ) )
{
$record[ $dShortTable."_childnumber_attr" ] = " id='cntDet_".$dShortTable."_'";
if( $this->getLayoutVersion() < PD_BS_LAYOUT )
$record[ $dShortTable."_link_attrs" ] = " href=\"#\" id=\"details_add".$this->id."_".$dShortTable."\" ";
$record[ $dShortTable."_childcount" ] = true;
}
if ( $this->getLayoutVersion() >= PD_BS_LAYOUT )
{
$indXTtag = $dShortTable."_link_attrs";
$indIdAttr = "details_add".$this->id."_".$dShortTable;
}
else
{
$indXTtag = $dShortTable."_dtablelink_attrs";
$indIdAttr = $dShortTable."_preview".$this->id;
}
$htmlAttributes = array();
$record[$indXTtag] = "";
$htmlAttributes["href"] = GetTableLink($dShortTable, "list")."?";
$htmlAttributes["id"] = $indIdAttr;
$htmlAttributes["style"] = "display:none;";
if( $this->pSet->detailsPreview( $dDataSourceTable ) == DP_INLINE )
{
$htmlAttributes["caption"] = GetTableCaption(GoodFieldName($dDataSourceTable));
$htmlAttributes["data-pagetype"] = $this->allDetailsTablesArr[$i]['dType'];
}
foreach ($htmlAttributes as $attr => $value)
{
$record[$indXTtag] .= $attr . "=\"" . $value . "\" ";
}
if( $this->pSet->detailsHideEmpty( $dDataSourceTable ) && !$hideDPLink )
$hideDPLink = true;
}
$record["dtables_link_attrs"] = " href=\"#\" id=\"details_add".$this->id."\" ";
if( $hideDPLink )
{
if ( $this->getLayoutVersion() >= PD_BS_LAYOUT )
$record["dtables_link_attrs"] .= " data-hidden";
else
$record["dtables_link_attrs"] .= " class=\"".$this->makeClassName("hiddenelem")."\"";
}
$this->addSpansForGridCells('add', $record);
for($i = 0; $i < count($this->listFields); $i ++)
{
$field = $this->listFields[$i]['fName'];
$gFieldName = GoodFieldName( $field );
// code deleted due to #12459
$record[ $gFieldName."_class" ] .= $this->fieldClass( $field );
$this->addHiddenColumnClasses($record, $field);
}
if($this->colsOnPage > 1)
$record["endrecord_block"]= true;
$record["grid_recordheader"]= true;
$record["grid_vrecord"]= true;
$row["grid_record"]= array("data" => array());
//set the $row["grid_record"] value
$this->setRowsGridRecord($row, $record);
for($i = 1; $i < $this->colsOnPage; $i ++)
{
$rec = array();
if($i < $this->colsOnPage - 1)
$rec["endrecord_block"]= true;
if($row["grid_record"]["data"])
{
$row["grid_record"]["data"][]= $rec;
}
}
$row["grid_rowspace"]= true;
$row["grid_recordspace"]= array("data" => array());
for($i = 0; $i < $this->colsOnPage * 2 - 1; $i ++)
$row["grid_recordspace"]["data"][]= true;
$rowInfoArr["data"][]= $row;
}
/**
* Incapsulates beforeProccessRow event
*
* @return array
*/
function beforeProccessRow()
{
if($this->eventExists("ListFetchArray"))
$data = $this->eventsObject->ListFetchArray($this->recSet, $this);
else
$data = $this->cipherer->DecryptFetchedArray( $this->recSet->fetchAssoc() );
while($data)
{
if($this->eventExists("BeforeProcessRowList"))
{
RunnerContext::pushRecordContext( $data, $this );
$result = $this->eventsObject->BeforeProcessRowList($data, $this);
RunnerContext::pop();
if(!$result )
{
if($this->eventExists("ListFetchArray"))
$data = $this->eventsObject->ListFetchArray($this->recSet, $this);
else
$data = $this->cipherer->DecryptFetchedArray( $this->recSet->fetchAssoc() );
continue;
}
}
return $data;
}
}
/**
* If use list icons instead list of links
* Then continue count width for td, which contains icons
* And depends of this width assign or not list icons column
*
* @param {integer} $editPermis - edit permissions
* @param {integer} $addPermis - add permissions
* @param {integer} $searchPermis - search permissions
*/
function assignListIconsColumn()
{
if( $this->inlineEditAvailable() || $this->inlineAddAvailable() || $this->displayViewLink() || $this->editAvailable() )
{
$this->xt->assign("listIcons_column", true);
}
}
/**
* Fills list grid. This method use many other methods
*/
function fillGridData()
{
global $globalEvents;
$totals=array();
// fill $rowinfo array
$rowinfo = array();
$this->prepareInlineAddArea($rowinfo);
$this->setDetailsBadgeStyles();
// add grid data
$data = $this->beforeProccessRow();
$prewData = false;
$lockRecIds = array();
$tKeys = $this->pSet->getTableKeys();
$this->controlsMap['gridRows'] = array();
for($i = 0; $i < count($this->listFields); $i ++)
{
$this->recordFieldTypes[ $this->listFields[$i]['fName'] ] = $this->pSet->getFieldType( $this->listFields[$i]["fName"] );
}
// calc current page size by records limit for last
$currentPageSize = $this->pageSize;
if ( $this->pSet->getRecordsLimit() && $this->maxPages == $this->myPage )
{
$currentPageSize = $this->pSet->getRecordsLimit() - ( ($this->myPage-1) * $this->pageSize);
}
$_notEmptyFieldColumns = array();
while($data && ($this->recNo <= $currentPageSize || $currentPageSize == -1 ) )
{
$row = array();
RunnerContext::pushRecordContext( $data, $this );
$row["grid_record"]= array();
$row["grid_record"]["data"]= array();
$this->rowId ++;
for($col = 1; $data && ($this->recNo <= $currentPageSize || $currentPageSize == -1) && $col <= $this->colsOnPage; $col ++)
{
$this->countTotals($totals, $data);
$record = array();
$this->genId();
$row["rowattrs"] = " id=\"gridRow".$this->recId."\"";
$record["recId"] = $this->recId;
$gridRowInd = count($this->controlsMap['gridRows']);
$this->controlsMap['gridRows'][$gridRowInd] = array();
$currentRow = &$this->controlsMap['gridRows'][$gridRowInd];
$currentRow['id'] = $this->recId;
$currentRow['rowInd'] = $gridRowInd;
//Add the connection with containing row. It's important for vertical layout's multiple records per row mode
$currentRow['contextRowId'] = $this->recId + $this->colsOnPage - $col;
$isEditable = Security::userCan('E', $this->tName, $data[$this->mainTableOwnerID] )
|| Security::userCan('D', $this->tName, $data[$this->mainTableOwnerID] );
if($globalEvents->exists("IsRecordEditable", $this->tName))
$isEditable = $globalEvents->IsRecordEditable($data, $isEditable, $this->tName);
$currentRow['isEditOwnRow'] = $isEditable;
$currentRow['gridLayout'] = $this->listGridLayout;
$currentRow['keyFields'] = array();
$currentRow['keys'] = array();
for($i = 0; $i < count($tKeys); $i ++) {
$currentRow['keyFields'][$i] = $tKeys[$i];
$currentRow['keys'][$i] = $data[$tKeys[$i]];
}
$record["edit_link"] = $isEditable;
$record["inlineedit_link"] = $isEditable;
$record["view_link"] = $this->permis[$this->tName]['search'];
$record["copy_link"] = $this->permis[$this->tName]['add'];
//get record id for locking record
if($this->lockingObj)
{
if($this->mode == LIST_SIMPLE && !count($this->lockDelRec) && isset($_SESSION[$this->sessionPrefix."_lockDelRec"]))
{
$this->lockDelRec = $_SESSION[$this->sessionPrefix."_lockDelRec"];
unset($_SESSION[$this->sessionPrefix."_lockDelRec"]);
}
for($i=0;$ilockDelRec);$i++)
{
$lockDelRec = true;
foreach($this->lockDelRec[$i] as $key => $val)
{
if($data[$key]!=$val)
{
$lockDelRec = false;
break;
}
}
if($lockDelRec)
{
$lockRecIds[] = $this->recId;
break;
}
}
}
// detail tables
$this->proccessDetailGridInfo($record, $data, $gridRowInd);
// key fields
$keyblock = "";
$editlink = "";
$copylink = "";
$keylink = "";
$keys = array(); //to open view pages in popup clicking on markers
for($i = 0; $i < count($tKeys); $i ++) {
if($i != 0) {
$keyblock.= "&";
$editlink.= "&";
$copylink.= "&";
}
$keyValue = rawurlencode($data[$tKeys[$i]]);
$keyValueHtml = runner_htmlspecialchars( $keyValue );
$keyblock.= $keyValue;
$editlink.= "editid".($i + 1)."=".$keyValueHtml;
$copylink.= "copyid".($i + 1)."=".$keyValueHtml;
$keylink.= "&key".($i + 1)."=".$keyValueHtml;
$keys[$i] = $data[$tKeys[$i]];
}
$this->recIds[] = $this->recId;
$record["recordattrs"] = "data-record-id=\"".$this->recId."\"";
$record["editlink_attrs"] = "id=\"editLink".$this->recId."\" name=\"editLink".$this->recId."\" data-gridlink";
$record["copylink_attrs"] = "id=\"copyLink".$this->recId."\" name=\"copyLink".$this->recId."\" data-gridlink";
$record["viewlink_attrs"] = "id=\"viewLink".$this->recId."\" name=\"viewLink".$this->recId."\" data-gridlink";
if( !$this->isPD() )
{
$record["editlink_attrs"] .= " href='".GetTableLink($this->shortTableName, "edit", $editlink)."'";
$record["copylink_attrs"] .= " href='".GetTableLink($this->shortTableName, "add", $copylink)."'";
$record["viewlink_attrs"] .= " href='".GetTableLink($this->shortTableName, "view", $editlink)."'";
}
else
{
$state = $this->getStateUrlParams();
$record["editlink"] = $editlink . '&' . $state;
$record["copylink"] = $copylink . '&' . $state;
}
$record["inlineeditlink_attrs"]= "id=\"iEditLink".$this->recId
."\" name=\"iEditLink".$this->recId."\" href='".GetTableLink($this->shortTableName, "edit", $editlink)."' data-gridlink";
$record["inlinesavelink_attrs"]= "id=\"saveLink".$this->recId."\" href=#";
$record["inlinerevertlink_attrs"]= "id=\"revertLink".$this->recId."\" href=#";
$record["ieditbuttonsholder_attrs"]= "id=\"ieditbuttonsholder".$this->recId."\" ";
if( $this->mobileTemplateMode() )
{
if( $this->displayViewLink() )
$record["recordattrs"] .= " data-viewlink='".GetTableLink($this->shortTableName, "view", $editlink)."'";
if( $this->editAvailable() && $isEditable )
$record["recordattrs"] .= " data-editlink='".GetTableLink($this->shortTableName, "edit", $editlink)."'";
}
$this->fillCheckAttr($record, $data, $keyblock);
if( $this->detailsInGridAvailable() )
$record["dtables_link"] = true;
if( $this->hasBigMap() )
$this->addBigGoogleMapMarkers($data, $keys, $editlink);
$fieldsToHideIfEmpty = $this->pSet->getFieldsToHideIfEmpty();
for($i = 0; $i < count($this->listFields); $i ++)
{
// call addGoogleMapData before call proccessRecordValue!!!
if( $this->checkFieldHasMapData($i) )
$this->addGoogleMapData( $this->listFields[$i]['fName'], $data, $keys, $editlink );
$record[$this->listFields[$i]['valueFieldName']] = $this->proccessRecordValue($data, $keylink, $this->listFields[$i]);
if( in_array( $this->listFields[$i]['fName'], $fieldsToHideIfEmpty ) )
{
if( $this->listGridLayout != gltHORIZONTAL && $record[ $this->listFields[$i]['valueFieldName'] ] == "" )
{
$this->hideField( $this->listFields[$i]['fName'], $this->recId );
}
else if ( $this->listGridLayout == gltHORIZONTAL && $record[ $this->listFields[$i]['valueFieldName'] ] != "" )
{
$_notEmptyFieldColumns[ $this->listFields[$i]['fName'] ] = true;
}
}
}
$this->addSpansForGridCells('edit', $record, $data);
if($this->eventExists("BeforeMoveNextList"))
{
RunnerContext::pushRecordContext( $data, $this );
$this->eventsObject->BeforeMoveNextList($data, $row, $record, $record["recId"], $this);
RunnerContext::pop();
}
$this->spreadRowStyles($data, $row, $record);
$this->setRowCssRules($record);
for($i = 0; $i < count($this->listFields); $i ++)
{
$field = $this->listFields[$i]['fName'];
$this->setRowClassNames($record, $field);
$this->addHiddenColumnClasses($record, $field);
}
if($col < $this->colsOnPage)
$record["endrecord_block"]= true;
$record["grid_recordheader"]= true;
$record["grid_vrecord"]= true;
//set the $row["grid_record"] value
$this->setRowsGridRecord($row, $record);
// hide group fields
if ( $prewData )
{
$grFields = $this->pSet->getGroupFields();
foreach ( $grFields as $grF )
{
if ( $data[$grF] != $prewData[$grF] )
break;
foreach ( $this->pSet->getFieldItems( $grF ) as $fItemId)
$this->hideItem($fItemId, $this->recId);
}
}
$prewData = $data;
RunnerContext::pop();
$data = $this->beforeProccessRow();
$this->recNo ++;
}
if($col <= $this->colsOnPage)
{
for($gInd = 0; $gInd < $col - 1; $gInd++)
{
$this->controlsMap['gridRows'][$gridRowInd - $gInd]['contextRowId'] = $this->recId;
}
}
if( !$this->isPD() ) {
// old stuff
while($col <= $this->colsOnPage)
{
$record = array();
if($col < $this->colsOnPage)
$record["endrecord_block"]= true;
if($row["grid_record"]["data"])
{
$row["grid_record"]["data"][]= $record;
}
$col ++;
}
// assign row spacings for vertical layout
$row["grid_rowspace"]= true;
$row["grid_recordspace"]= array("data" => array());
for($i = 0; $i < $this->colsOnPage * 2 - 1; $i ++)
$row["grid_recordspace"]["data"][]= true;
}
$rowinfo["data"][]= $row;
if( $this->isPD() ) {
$this->recordsRenderData[ $record["recId"] ] = &$rowinfo["data"][ count( $rowinfo["data"] ) - 1 ];
}
}
if($this->lockingObj)
$this->jsSettings['tableSettings'][$this->tName]['lockRecIds'] = $lockRecIds;
if(count($rowinfo["data"]))
{
$rowinfo["data"][count($rowinfo["data"]) - 1]["grid_rowspace"]= false;
if($this->listGridLayout == gltVERTICAL && $this->is508)
{
if( $this->isBootstrap() )
$rowinfo["begin"] = "Table data
";
else
$rowinfo["begin"] = "Table data";
}
$this->xt->assignbyref("grid_row", $rowinfo);
}
$this->buildTotals($totals);
if( $this->listGridLayout == gltHORIZONTAL )
{
foreach( $this->pSet->getFieldsToHideIfEmpty() as $f )
{
if( !$_notEmptyFieldColumns[ $f ] )
$this->hideField( $f );
}
}
}
/**
* @return Boolean
*/
protected function hasBigMap()
{
return $this->googleMapCfg['isUseMainMaps'];
}
/**
* @param Number fIndex
* @return Boolean
*/
protected function checkFieldHasMapData( $fIndex )
{
return in_array($fIndex, $this->gMapFields);
}
/**
* Add hidden column classes
* If it need for current field
*
* @param &Array $record
* @param string $field field name
*/
protected function addHiddenColumnClasses(&$record, $field)
{
$gFieldName = GoodFieldName( $field );
if( isset( $this->hiddenColumnClasses[$gFieldName] ) )
{
$record[ $gFieldName."_class" ] .= " " . $this->hiddenColumnClasses[$gFieldName];
if( $this->listGridLayout != gltHORIZONTAL )
$record[ $gFieldName."_label_class" ] = $this->hiddenColumnClasses[$gFieldName];
}
}
/**
* Get the field's class name to align the field's value
* basing on its edti and view formats
*
* @param string $f field name
*
* @return string
*/
function fieldClass($f)
{
if( !isset($this->fieldClasses[$f]) )
$this->fieldClasses[$f] = $this->calcFieldClass( $f );
return $this->fieldClasses[$f];
}
function calcFieldClass($f)
{
if( $this->pSet->getEditFormat($f) == FORMAT_LOOKUP_WIZARD )
return '';
$format = $this->pSet->getViewFormat($f);
if( $format == FORMAT_FILE )
return ' rnr-field-file';
if( $this->listGridLayout == gltVERTICAL || $this->listGridLayout == gltCOLUMNS )
return '';
if( $format == FORMAT_AUDIO )
return ' rnr-field-audio';
if( $format == FORMAT_CHECKBOX )
return ' rnr-field-checkbox';
if( $format == FORMAT_NUMBER || IsNumberType( $this->pSet->getFieldType($f) ) )
return ' r-field-number';
return 'r-field-text';
}
/**
* Set the custom css hover rules for the current record
* corresponding css rules to the "row_css_rules" string property
*
* @param string $rowHoverCssRule
* @param string $fieldName OPTIONAL
* @return string
*/
protected function setRowHoverCssRule($rowHoverCssRule, $fieldName = "")
{
if( $this->listGridLayout != gltHORIZONTAL && $this->listGridLayout != gltFLEXIBLE )
return;
if( $fieldName )
{
$className = 'rnr-style'.$this->recId.'-'.$fieldName;
$this->row_css_rules .= ' tr:hover > td.'. $className .'.'. $className .'{'. $this->getCustomCSSRule( $rowHoverCssRule ) ."}\n";
return $className;
}
else
{
$this->row_css_rules = ' tr[id="gridRow'. $this->recId .'"]:hover > td:not(.rnr-cs){'. $this->getCustomCSSRule( $rowHoverCssRule ) ."}\n". $this->row_css_rules;
return '';
}
}
/**
* Build and shows totals info on page
*
* @param array $totals info abount totals
*/
function buildTotals(&$totals)
{
if(count($this->totalsFields))
{
// process totals
$this->xt->assign("totals_row", true);
$totals_records = array("data" => array());
for($j = 0; $j < $this->colsOnPage; $j++)
{
$record = array();
if($j == 0)
{
for($i = 0; $i < count($this->totalsFields); $i ++)
{
$goodName = GoodFieldName( $this->totalsFields[$i]['fName'] );
// show totals
$total = GetTotals( $this->totalsFields[$i]['fName'],
$totals[$this->totalsFields[$i]['fName']],
$this->totalsFields[$i]['totalsType'],
$this->totalsFields[$i]['numRows'],
$this->totalsFields[$i]['viewFormat'],
PAGE_LIST,
$this->pSet,
false,
$this );
if( !$this->pdfJsonMode() ) {
$total = "id."_" . $goodName . "\">".$total."";
}
$this->xt->assign( $goodName ."_total", $total);
$this->xt->assign( $goodName . "_showtotal", true);
}
}
if($j < $this->colsOnPage - 1){
$record["endrecordtotals_block"]= true;
}
$totals_records["data"][]= $record;
}
$this->xt->assignbyref("totals_record", $totals_records);
if(!$this->rowsFound)
$this->xt->assign("totals_attr", "style='display:none;'");
}
}
/**
* @param string $field
* @param int $state 0 value not need, 1 need for count, 2 need real value
*/
function outputFieldValue($field, $state)
{
$this->arrFieldSpanVal[$field] = $state;
}
/**
* Add span val for lookup fields, and average|total|count totals
*/
function addSpanVal($fName, &$data)
{
if( !$this->printRawValue( $fName ) )
return;
$fieldValue = $data[$fName ];
return "val=\"".runner_htmlspecialchars( $fieldValue )."\" ";
}
/**
* Proccess grid cells, also add spans if need them
*
* @param String type
* @param Array &record
* @param Array data (optional)
*/
function addSpansForGridCells($type, &$record, $data = null)
{
if( $this->pdfJsonMode() ) {
return;
}
for($i=0; $ilistFields); $i++)
{
$span = "recId : $this->id)."_".$this->listFields[$i]['goodFieldName']."\" ";
if($type == 'edit')
{
$span.= $this->addSpanVal($this->listFields[$i]['fName'], $data).">";
$span.= $record[$this->listFields[$i]['valueFieldName']];
}
else
$span.= ">";
$span.="";
$record[$this->listFields[$i]['valueFieldName']]= $span;
}
}
/**
* Proccess record values
*
* @param array $record
* @param array $data
* @param string $keylink
*/
function proccessRecordValue(&$data, &$keylink, $listFieldInfo)
{
$dbVal = $this->showDBValue($listFieldInfo['fName'], $data, $keylink);
return $this->addCenterLink($dbVal, $listFieldInfo['fName']);;
}
/**
* Checks if need to display grid
*/
function isDispGrid()
{
// can show data
if( $this->permis[$this->tName]['search'] && $this->rowsFound )
return true;
// can add data to grid
if ( $this->inlineAddAvailable() || $this->addAvailable() && $this->showAddInPopup )
return true;
return false;
}
/**
* Build checkbox markup
*/
function fillCheckAttr(&$record, $data, $keyblock)
{
if( $this->exportAvailable() || $this->printAvailable() || $this->deleteAvailable() || $this->inlineEditAvailable() || $this->updateSelectedAvailable() )
{
$record["checkbox"]= true;
/*
$keyValues = array();
$keyFields = $this->pSet->getTableKeys();
foreach( $keyFields as $idx => $k ) {
$keyValues[ $idx ] = $data[ $k ];
}
*/
$record["checkbox_attrs"]= "name=\"selection[]\" ".
"value=\"".runner_htmlspecialchars($keyblock)."\" ".
"id=\"check".$this->id."_".$this->recId."\" ";
//"data-keys=\"".runner_htmlspecialchars(my_json_encode( $keyValues ))."\"";
}
}
/**
* Main function, call to build page
* Do not change methods call oreder!!
*/
function prepareForBuildPage()
{
if( $this->mode == LIST_DASHDETAILS
|| $this->mode == LIST_DETAILS && ( $this->masterPageType == PAGE_LIST || $this->masterPageType == PAGE_REPORT ))
$this->updateDetailsTabTitles();
// prepare maps
loadMaps( $this->pSet );
// build column hiding CSS
$this->buildMobileCssRules();
//Sorting fields
$this->buildOrderParams();
// delete record
$this->deleteRecords();
// PRG rule, to avoid POSTDATA resend
$this->rulePRG();
// we need to decide which tab to display first
$this->processGridTabs();
// call SQL events, calculate record count
$this->calculateRecordCount();
//$this->buildSQL();
// build pagination block
$this->buildPagination();
$this->recSet = $this->dataSource->getList( $this->queryCommand );
// seek page must be executed after build pagination
// ***Datasource must nandle this
//$this->seekPageInRecSet($this->querySQL);
$this->setGoogleMapsParams($this->listFields);
$this->setGridUserParams();
$this->assignColumnHeaderClasses();
// fill grid data
$this->fillGridData();
if( $this->mode != LIST_MASTER )
$this->buildSearchPanel();
// add common js code
$this->addCommonJs();
// add common html code
$this->addCommonHtml();
// Set common assign
$this->commonAssign();
// Add cells' custom css
$this->addCustomCss();
}
/**
* Sorting fields
*/
function buildOrderParams()
{
$this->assignColumnHeaders();
if( !$this->isPageSortable() )
return;
$this->addOrderUrlParam();
}
function assignColumnHeaders()
{
// show headers
foreach( $this->listFields as $f)
{
$this->xt->assign( GoodFieldname( $f['fName'] ) . "_fieldheader", true );
}
if ( !$this->isReoderByHeaderClickingEnabled() ) {
return;
}
// add icons and find already sorted fields
$orderFields =& $this->orderClause->getOrderFields();
// add sorting links and icons
foreach( $orderFields as $of )
{
if( $of['hidden'] ) {
continue;
}
// add icon
if( $this->isPD() )
{
$this->xt->assign( "arrow_icon_" . GoodFieldname( $of['column'] ),
"" );
}
else
{
$this->xt->assign_section( GoodFieldname( $of['column'] )."_fieldheader",
"", "" );
}
}
foreach( $this->listFields as $f )
{
$gf = GoodFieldName( $f['fName'] );
$dir = "a";
// build multisort parameter
// update direction if the field is already sorted
$multisort = array();
foreach( $orderFields as $of )
{
if( $of['hidden'] )
continue;
if( $of['column'] == $f['fName'] )
{
$dir = $of["dir"] == "ASC" ? "d" : "a";
}
else
{
$multisort[] = ($of["dir"] == "ASC" ? "a" : "d") . GoodFieldName($of['column']);
}
}
// assign sorting links
$attrs = array();
$attrs[] = 'data-href="' . GetTableLink($this->shortTableName, "list", "orderby=" . $dir.$gf ) . '"';
$attrs[] = 'data-order="' . $dir . $gf . '"';
$attrs[] = 'id="order_'.$gf.'_'.$this->id.'"';
$attrs[] = 'name="order_'.$gf.'_'.$this->id.'"';
$attrs[] = 'data-multisort="' . implode( ';', $multisort ) . '"';
$attrs[] = 'class="rnr-orderlink"';
$this->xt->assign( $gf."_orderlinkattrs", implode( " ", $attrs ) );
}
}
/**
* @param String fName
* @param Boolean desc
* @param Boolean showLabelOnly
* @return String
*/
protected function orderFieldLabelString( $fName, $desc, $showLabelOnly )
{
$fName = GetFieldLabel( GoodFieldName( $this->tName ), GoodFieldName( $fName ) );
if( $showLabelOnly )
return $fName;
return $fName." ". ($desc ? ##message SORT_HIGH_TO_LOW## : ##message SORT_LOW_TO_HIGH##);
}
/**
*
*/
protected function assignSortByDropdown()
{
if( !$this->pSet->hasSortByDropdown() )
return;
// no data
if( !$this->rowsFound )
{
if( $this->listAjax )
{
$this->xt->assign("reorder_records", true);
$this->hideElement("reorder_records");
}
else
$this->hideItem("sort_dropdown");
return;
}
$sortSettings = $this->orderClause->getSortBySettings();
$sortByIdx = $this->orderClause->getSortByControlIdx();
$options = array();
if( $sortByIdx == -1 )
$options[] = "";
foreach( $sortSettings as $idx => $sData )
{
$label = $sData["label"];
if( !$label )
{
$labelParts = array();
foreach( $sData["fields"] as $fData )
{
$labelParts[] = $this->orderFieldLabelString( $fData["field"], $fData["desc"], $fData["labelOnly"] );
}
$label = implode( "; ", $labelParts );
}
$selected = $sortByIdx == $idx ? " selected" : "";
$options[] = '';
}
if( count( $options ) )
$markup = '";
$this->xt->assign("reorder_records", true);
$this->xt->assign("sortByDropdown", $markup);
}
/**
* show page at the end of its proccess, depending on mode
*/
function showPage()
{
$this->BeforeShowList();
$this->display($this->templatefile);
}
/**
* Static function for create list page
* Read params from setting
* Create object of class in accordance with mode displaying page
* @param String strTableName
* @param Array options
*/
static function & createListPage($strTableName, $options)
{
global $isGroupSecurity;
$gSettings = new ProjectSettings($strTableName, $options['pageType'], $options['pageName']);
$gQuery = $gSettings->getSQLQuery();
$params = $options;
$params['tName'] = $strTableName;
$params['origTName'] = $gSettings->getOriginalTableName();
$params['gPageSize'] = $gSettings->getInitialPageSize();
$params['nSecOptions'] = $gSettings->getAdvancedSecurityType();
$params['nLoginMethod'] = GetGlobalData("nLoginMethod",0);
$params['recsPerRowList'] = $gSettings->getRecordsPerRowList();
$params['mainTableOwnerID'] = $gSettings->getTableOwnerIdField();
$params['exportTo'] = $gSettings->hasExportPage();
$params['printFriendly'] = $gSettings->hasPrintPage();
$params['deleteRecs'] = $gSettings->hasDelete();
$params["isGroupSecurity"] = $isGroupSecurity;
$params['arrKeyFields'] = $gSettings->getTableKeys();
$params["panelSearchFields"] = $gSettings->getPanelSearchFields();
$params['listGridLayout'] = $gSettings->getListGridLayout();
$params['createLoginPage'] = GetGlobalData("createLoginPage",false);
$params['noRecordsFirstPage'] = $gSettings->noRecordsOnFirstPage();
$params['totalsFields'] = $gSettings->getTotalsFields();
$params['listAjax'] = $gSettings->ajaxBasedListPage();
$params['arrRecsPerPage'] = $gSettings->getRecordsPerPageArray();
$params['isScrollGridBody'] = $gSettings->getScrollGridBody();
$params['viewPDF'] = $gSettings->isViewPagePDF() || $gSettings->isPrinterPagePDF();
$params['audit'] = GetAuditObject($strTableName);
// choose class by mode
if ($params["mode"]==LIST_SIMPLE )
$pageObject = new ListPage_Simple($params);
else if($params["mode"]==LIST_MASTER)
$pageObject = new ListPage_Master($params);
else if($params["mode"]==LIST_AJAX)
$pageObject = new ListPage_Ajax($params);
else if($params["mode"]==LIST_LOOKUP)
$pageObject = new ListPage_Lookup($params);
else if($params["mode"]==LIST_DETAILS && $params["masterPageType"] == PAGE_LIST)
$pageObject = new ListPage_DPList($params);
else if($params["mode"]==LIST_DETAILS || $params["mode"]==LIST_PDFJSON)
$pageObject = new ListPage_DPInline($params);
else if($params["mode"]==LIST_POPUPDETAILS )
$pageObject = new ListPage_DPPopup($params);
else if( $params["mode"]==LIST_DASHDETAILS )
$pageObject = new ListPage_DPDash($params);
else if($params["mode"] == RIGHTS_PAGE)
{
##if @BUILDER.nLoginMethod==LOGIN_AD##
$pageObject = new RightsPage_AD($params);
##else##
$pageObject = new RightsPage($params);
##endif##
}
else if($params["mode"]==MEMBERS_PAGE)
{
##if @BUILDER.nLoginMethod==LOGIN_AD##
$pageObject = new MembersPage_AD($params);
##else##
$pageObject = new MembersPage($params);
##endif##
}
else if($params["mode"] == LIST_DASHBOARD)
$pageObject = new ListPage_Dashboard($params);
else if( $params["mode"] == MAP_DASHBOARD )
$pageObject = new MapPage_Dashboard($params);
$pageObject->init();
return $pageObject;
}
/**
* If the page's layout is horizontal and the number of records per row equals 1
* It assigns all $record's content to 'grid_row' (to show all rows added to a grid row in 'Visual Editor')
* otherwise It assigns the content to 'grid_record' directly.
*/
protected function setRowsGridRecord(&$row, $record)
{
if( !$this->isPD() )
{
// old stuff
if($this->listGridLayout == gltVERTICAL || $this->recsPerRowList != 1)
{
$row["grid_record"]["data"][]= $record;
return;
}
}
foreach($record as $index=>$value)
{
$row[$index] = $value;
}
$row["grid_record"] = true;
}
/**
* Build CSS rules to hide particular columnns on specific screen sizes
*/
protected function buildMobileCssRules()
{
if( $this->pSet->isAllowShowHideFields() )
return;
$cssBlocks = array();
$columnsToHide = $this->getColumnsToHide();
$devices = array( SMARTPHONE_PORTRAIT, DESKTOP );
// build CSS code
foreach( $this->listFields as $f )
{
$gFieldName = GoodFieldName( $f['fName'] );
$fieldMentioned = false;
$field = $f['fName'];
foreach( $devices as $d )
{
if( in_array($gFieldName, $columnsToHide[ $d ]) )
{
$this->hiddenColumnClasses[$gFieldName] = "column".GoodFieldName( $field );
$cssBlocks[$d] .= "." . $this->hiddenColumnClasses[$gFieldName] . ":not([data-forced-visible-column]) { display: none !important;; }\n";
$fieldMentioned = true;
}
}
}
$this->mobile_css_rules = "";
foreach( $devices as $d )
{
if($cssBlocks[$d])
{
$this->mobile_css_rules .= ProjectSettings::getDeviceMediaClause($d)."\n{\n".$cssBlocks[$d]."\n}\n";
}
}
}
/**
* Get indices of the not list page's blob fields
* @return Array
*/
public function getNotListBlobFieldsIndices()
{
$allFields = $this->pSet->getFieldsList();
$blobIndices = $this->pSet->getBinaryFieldsIndices();
$indices = array();
foreach($blobIndices as $idx)
{
if( !$this->pSet->appearOnListPage( $allFields[ $idx - 1 ] ) )
$indices[] = $idx;
}
return $indices;
}
public static function readListModeFromRequest()
{
$postedMode = postvalue("mode");
if($postedMode == "ajax")
return LIST_AJAX;
else if($postedMode == "lookup")
return LIST_LOOKUP;
else if($postedMode == "listdetails")
return LIST_DETAILS;
else if( $postedMode == "listdetailspopup" )
return LIST_POPUPDETAILS;
else if($postedMode == "dashdetails")
return LIST_DASHDETAILS;
else if($postedMode == "dashlist")
return LIST_DASHBOARD;
else if($postedMode == "dashmap")
return MAP_DASHBOARD;
return LIST_SIMPLE;
}
protected static function readMainTableSettingsFromRequest( $table )
{
$mainTableShortName = GetTableURL( postvalue("table") );
##if @BUILDER.bCreateLoginPage && @BUILDER.m_nLoginMethod == SECURITY_TABLE & @BUILDER.strLoginDataSource.len##
if( postvalue("pageType") == "register" )
$mainTableShortName = GetTableURL( "##@BUILDER.strLoginDataSource s##" );
##endif##
return getLookupMainTableSettings($table, $mainTableShortName, postvalue("field"));
}
protected static function checkLookupPermissions( $table )
{
$lookupMainSettings = ListPage::readMainTableSettingsFromRequest( $table );
if( !$lookupMainSettings )
return false;
$mainTable = $lookupMainSettings->getTableName();
// page called for List page with search lookup and the user has permissions on the main table
if( CheckTablePermissions($mainTable, "S") || CheckTablePermissions($mainTable, "E") || CheckTablePermissions($mainTable, "A"))
return true;
// otherwise check if the page is called from the register page
##if @BUILDER.bCreateLoginPage && @BUILDER.m_nLoginMethod == SECURITY_TABLE & @BUILDER.strLoginDataSource.len##
if( $mainTable == "##@BUILDER.strLoginDataSource s##" )
{
if( $lookupMainSettings->appearOnPage( postvalue("field") ) !== FALSE )
return true;
}
##endif##
return false;
}
public static function processListPageSecurity( $table )
{
// user has necessary permissions
if( Security::checkPagePermissions( $table, "S" ) )
return true;
$mode = ListPage::readListModeFromRequest();
// check special permissions like lookup mode
if( $mode == LIST_LOOKUP && ListPage::checkLookupPermissions( $table ) )
return true;
// page can not be displayed. Redirect or return error
// return error if the page is requested by AJAX
if( $mode != LIST_SIMPLE )
{
Security::sendPermissionError();
return false;
}
// The user is logged in but lacks necessary permissions
// redirect to List page or Menu.
if( isLogged() && !isLoggedAsGuest() )
{
HeaderRedirect("menu");
return false;
}
// Not logged in
// redirect to Login
// Current URL is already saved in session
redirectToLogin();
return false;
}
/**
* Hide the field on the page
* @param String fieldName
*/
function hideField($fieldName, $recordId = "")
{
if( $this->isPD() ) {
return parent::hideField( $fieldName, $recordId );
}
$this->xt->assign(GoodFieldName($fieldName) ."_fieldheadercolumn", false);
$this->xt->assign(GoodFieldName($fieldName) . "_fieldcolumn", false);
$this->xt->assign(GoodFieldName($fieldName) . "_fieldfootercolumn", false);
}
/**
* Show the field on the page
* @param String fieldName
*/
function showField($fieldName)
{
if( $this->isPD() ) {
return parent::showField( $fieldName );
}
$this->xt->assign(GoodFieldName($fieldName) ."_fieldheadercolumn", true);
$this->xt->assign(GoodFieldName($fieldName) . "_fieldcolumn", true);
$this->xt->assign(GoodFieldName($fieldName) . "_fieldfootercolumn", true);
}
public function isPageSortable()
{
return true;
}
/**
* save user setting
* @param String table
* @return Boolean
*/
public static function processSaveParams( $table )
{
if( postvalue("saveParam") )
{
$paramType = intval( postvalue("saveParam") );
$paramData = my_json_decode(postvalue("data"));
include_once getabspath("classes/paramsLogger.##@ext##");
if( postvalue("onDashboard") )
$paramsLogger = new paramsLogger( postvalue("dashElementId"), $paramType );
else
$paramsLogger = new paramsLogger( $table, $paramType );
if( $paramType == SHFIELDS_PARAMS_TYPE )
{
$macroDeviceClass = RunnerPage::deviceClassToMacro( postvalue("deviceClass") );
$ps = new ProjectSettings($table);
if( !$ps->columnsByDeviceEnabled() )
$macroDeviceClass = 0;
$paramsLogger->saveShowHideData( $macroDeviceClass, $paramData );
}
else
$paramsLogger->save( $paramData );
return true;
}
return false;
}
protected function setGridUserParams()
{
}
protected function displayViewLink() {
return $this->viewAvailable();
}
function gridTabsAvailable() {
if( $this->mode == LIST_DETAILS && $this->masterPageType == PAGE_ADD )
return false;
return true;
}
protected function hasMainDashMapElem()
{
return false;
}
function displayTabsInPage()
{
return $this->simpleMode() || ( $this->mode == LIST_DETAILS && ($this->masterPageType == PAGE_VIEW || $this->masterPageType == PAGE_EDIT));
}
function element2Item( $name ) {
if( $name == "message" ) {
return array( "grid_message" );
} if( $name == "grid" ) {
return array( "grid" );
}
return parent::element2Item( $name );
}
function &findRecordAssigns( $recordId ) {
return $this->recordsRenderData[ $recordId ];
}
/**
* Add raw values to the grid or not
* @return Boolean
*/
function printRawValue( $field )
{
if( !isset( $this->fieldsWithRawValues[ $field ] )) {
$type = $this->pSet->getFieldType($field);
if( IsBinaryType($type) ) {
$this->fieldsWithRawValues[ $field ] = false;
} else {
$this->fieldsWithRawValues[ $field ] = $this->addRawFieldValues
|| @$this->arrFieldSpanVal[ $field ] == 2
|| @$this->arrFieldSpanVal[ $field ] == 1
|| $this->pSet->hasAjaxSnippet()
|| $this->pSet->hasButtonsAdded();
}
}
return $this->fieldsWithRawValues[ $field ];
}
public function getSubsetDataCommand() {
$dc = parent::getSubsetDataCommand();
// no records on first page
if( $this->mode != LIST_DETAILS && $this->noRecordsFirstPage && !$this->isSearchFunctionalityActivated() )
$dc->filter = DataCondition::_False();
$dc->reccount = $this->pageSize;
$dc->startRecord = $this->pageSize * ($this->myPage - 1);
/*
$detailsSubqueries = $this->getMasterDetailSubQuery();
if( $detailsSubqueries )
$sql["sqlParts"]["head"] .= ", " . implode( ", ", $detailsSubqueries );
*/
return $dc;
}
/**
* calcualte record count, call BeforeQuery events
* update SQL queries if the user wants so
*/
function calculateRecordCount()
{
$this->queryCommand = $this->getSubsetDataCommand();
$this->callBeforeQueryEvent( $this->queryCommand );
$this->numRowsFromSQL = $this->dataSource->getCount( $this->queryCommand );
}
/**
* Call event and modify dc if needed
*/
function callBeforeQueryEvent( $dc ) {
if( !$this->eventsObject->exists("BeforeQueryList") ) {
return;
}
$prep = $this->dataSource->prepareSQL( $dc );
$where = $prep["where"];
$order = $prep["order"];
$sql = $prep["sql"];
$this->eventsObject->BeforeQueryList($sql, $where, $order, $this);
if( $sql != $prep["sql"] )
$this->dataSource->overrideSQL( $dc, $sql );
else {
if( $where != $prep["where"] )
$this->dataSource->overrideWhere( $dc, $where );
if( $order != $prep["order"] )
$this->dataSource->overrideOrder( $dc, $order );
}
}
}
?>