kenken999/php
0
1<?php2class EditPage extends RunnerPage3{4 protected $cachedRecord = null;5 6 public $oldKeys = array();7 public $newKeys = array();8 protected $keysChanged = false;9 10 public $jsKeys = array();11 12 public $keyFields = array();13 14 public $readEditValues = false;15 16 public $action = "";17 18 public $lockingAction = "";19 public $lockingSid = null;20 public $lockingKeys = null;21 public $lockingStart = null;22 23 protected $lockingMessageAttr = "data-locked";24 protected $lockingMessageText = "";25 26 protected $lockingMessageBlock = "";27 28 public $messageType = MESSAGE_ERROR;29 30 protected $auditObj = null;31 32 protected $oldRecordData = null;33 protected $newRecordData = array();34 35 protected $updatedSuccessfully = false;36 37 /**38 * It's set up in inline edit mode only39 */40 public $screenWidth = 0;41 42 /**43 * It's set up in inline edit mode only44 */45 public $screenHeight = 0;46 47 /**48 * It's set up in inline edit mode only49 */50 public $orientation = '';51 52 53 /**54 * @type Number55 */56 protected $afterEditAction = null;57 58 /**59 * @type Array60 */61 protected $prevKeys = null;62 /**63 * @type Array64 */65 protected $nextKeys = null;66 67 protected $recordValuesToEdit = null;68 69 public $forSpreadsheetGrid = false;70 public $hostPageName = "";71 72 73 protected $sqlValues = array();74 75 public $listPage = "";76 77 /**78 * @constructor79 */80 function __construct(&$params)81 {82 parent::__construct($params);83 84 $this->setKeysForJs();85 86 $this->auditObj = GetAuditObject($this->tName);87 88 $this->editFields = $this->getPageFields();89 90 $this->headerForms = array( "top" );91 $this->footerForms = array( "below-grid" );92 if ( $this->isMultistepped() )93 $this->bodyForms = array( "above-grid", "steps" );94 else95 $this->bodyForms = array( "above-grid", "grid" );96 97 $this->addPageSettings();98 }99 100 /**101 * Add js page settings102 */103 protected function addPageSettings()104 {105 if( $_SESSION[ $this->sessionPrefix . "_recordUpdated" ] )106 {107 $this->setProxyValue( $this->shortTableName."_recordUpdated", true );108 unset( $_SESSION[ $this->sessionPrefix . "_recordUpdated" ] );109 }110 else111 $this->setProxyValue( $this->shortTableName."_recordUpdated", false );112 113 if( !$this->isPopupMode() && !$this->isSimpleMode() )114 return;115 116 $afterEditAction = $this->getAfterEditAction();117 $this->jsSettings["tableSettings"][ $this->tName ]["afterEditAction"] = $afterEditAction;118 119 if ( $afterEditAction == AE_TO_DETAIL_LIST )120 $this->jsSettings["tableSettings"][ $this->tName ]["afterEditActionDetTable"] = GetTableURL( $this->pSet->getAEDetailTable() );121 122 if ( $this->mode == EDIT_POPUP )123 {124 if ( $afterEditAction == AE_TO_NEXT_EDIT )125 $this->jsSettings["tableSettings"][ $this->tName ]["nextKeys"] = $this->getNextKeys();126 127 if ( $afterEditAction == AE_TO_PREV_EDIT )128 $this->jsSettings["tableSettings"][ $this->tName ]["prevKeys"] = $this->getPrevKeys();129 }130 131 if( $this->listPage && $afterEditAction == AE_TO_LIST ) {132 $this->pageData["listPage"] = $this->listPage;133 }134 }135 136 /**137 * Get the correct after edit action138 * basing on the table settings139 * @return Number140 */141 protected function getAfterEditAction()142 {143 if( isset( $this->afterEditAction ) && !is_null( $this->afterEditAction ) )144 return $this->afterEditAction;145 146 $action = $this->pSet->getAfterEditAction();147 148 if( $this->isPopupMode() && $this->pSet->checkClosePopupAfterEdit()149 || $action == AE_TO_VIEW && !$this->viewAvailable()150 || $action == AE_TO_NEXT_EDIT && !$this->getNextKeys() 151 || $action == AE_TO_PREV_EDIT && !$this->getPrevKeys() )152 {153 $action = AE_TO_LIST;154 }155 156 if( $action == AE_TO_DETAIL_LIST )157 {158 $dTName = $this->pSet->getAEDetailTable();159 $dPset = new ProjectSettings( $dTName );160 $dPermissions = $this->getPermissions( $dTName );161 162 if( !$dTName || $action == AE_TO_DETAIL_LIST && (!$dPset->hasListPage() || !$dPermissions["search"]) )163 $action = AE_TO_LIST;164 }165 166 $this->afterEditAction = $action;167 return $this->afterEditAction;168 }169 170 /**171 * Assign session prefix172 */173 protected function assignSessionPrefix()174 {175 if( $this->mode == EDIT_DASHBOARD || ( $this->isPopupMode() || $this->mode == EDIT_INLINE ) && $this->dashTName )176 {177 $this->sessionPrefix = $this->dashTName."_".$this->tName;178 return;179 }180 181 parent::assignSessionPrefix();182 }183 184 /**185 * Set session variables186 */187 public function setSessionVariables()188 {189 $masterTable = $this->masterTable;190 parent::setSessionVariables();191 // don't use mastertable stored in session192 $this->masterTable = $masterTable;193 194 $_SESSION[ $this->sessionPrefix.'_advsearch' ] = serialize($this->searchClauseObj);195 }196 197 /**198 * Get the page's fields list199 * @return Array200 */201 protected function getPageFields()202 {203 if( $this->mode == EDIT_INLINE )204 return $this->pSet->getInlineEditFields();205 206 return $this->pSet->getEditFields();207 }208 209 /**210 * Set keys values211 * @param Array keys212 */213 public function setKeys($keys)214 {215 $this->cachedRecord = null;216 $this->recordValuesToEdit = null;217 $this->keys = $keys;218 $this->setKeysForJs();219 }220 221 public function setKeysForJs()222 {223 $i = 0;224 foreach($this->keys as $field => $value)225 {226 $this->jsKeys[ $i++ ] = $value;227 }228 }229 230 /**231 * Tell whether the page was called to update locking state only232 */233 public function isLockingRequest() {234 return $this->lockingObj && $this->lockingAction != "";235 }236 237 /**238 * Perform locking action the page was called for239 */240 public function doLockingAction()241 {242 $arrkeys = explode("&", urldecode( $this->lockingKeys ));243 244 foreach(array_keys($arrkeys) as $ind)245 $arrkeys[$ind] = urldecode($arrkeys[$ind]);246 247 if($this->lockingAction == "unlock")248 {249 $this->lockingObj->UnlockRecord($this->tName, $arrkeys, $this->lockingSid);250 }251 else if($this->lockingAction == "lockadmin" && $this->lockingAdmin() )252 {253 $this->lockingObj->UnlockAdmin($this->tName, $arrkeys, $this->lockingStart == "yes");254 if($this->lockingStart == "no")255 echo "unlock";256 else if($this->lockingStart == "yes")257 echo "lock";258 }259 else if($this->lockingAction == "confirm")260 {261 $lockMessage = "";262 if( !$this->lockingObj->ConfirmLock($this->tName, $arrkeys, $lockMessage) )263 echo $lockMessage;264 }265 }266 267 /**268 * Set template file if it empty269 */270 public function setTemplateFile()271 {272 if($this->mode == EDIT_INLINE)273 $this->templatefile = GetTemplateName($this->shortTableName, "inline_edit");274 parent::setTemplateFile();275 }276 277 public function init()278 {279 if( $this->eventsObject->exists("BeforeProcessEdit") )280 $this->eventsObject->BeforeProcessEdit( $this );281 282 parent::init();283 }284 285 public function process()286 {287 if( $this->action == "edited" )288 {289 $this->processDataInput();290 291 $this->readEditValues = !$this->updatedSuccessfully;292 293 if( $this->mode == EDIT_INLINE || $this->isPopupMode() )294 {295 $this->reportInlineSaveStatus();296 return;297 }298 299 if( $this->updatedSuccessfully )300 {301 if( $this->afterEditActionRedirect() )302 return;303 }304 }305 306 if( $this->captchaExists() )307 {308 $this->displayCaptcha();309 }310 311 $this->prgReadMessage();312 313 // get the record to edit314 if( !$this->readRecord() )315 return;316 317 if( !$this->IsRecordEditable( false ) )318 return $this->SecurityRedirect();319 320 if( !$this->lockRecord() )321 return;322 323 324 $this->doCommonAssignments();325 $this->prepareBreadcrumbs();326 $this->prepareCollapseButton();327 $this->prepareButtons();328 $this->prepareSteps();329 $this->prepareEditControls();330 $this->prepareReadonlyFields();331 332 $this->prepareJsSettings();333 334 $this->prepareDetailsTables();335 336 if( $this->mode != EDIT_INLINE )337 $this->addButtonHandlers();338 339 $this->addCommonJs();340 341 $this->displayEditPage();342 }343 344 /**345 * Add common javascript files and code346 */347 function addCommonJs()348 {349 parent::addCommonJs();350 }351 352 /**353 * Add table settings354 */355 protected function prepareJsSettings()356 {357 $this->pageData['detailsMasterKeys'] = $this->getDetailTablesMasterKeys( $this->getCurrentRecordInternal() );358 359 $this->jsSettings['tableSettings'][ $this->tName ]["keys"] = $this->jsKeys;360 $this->jsSettings['tableSettings'][ $this->tName ]['keyFields'] = $this->pSet->getTableKeys();361 362 if( $this->lockingObj ) {363 // $keys, $savedKeys could not be set properly if editid params were not passed, so use $this->keys instead364 $escapedKeys = array();365 foreach( $this->keys as $k ) {366 $escapedKeys[] = rawurlencode( $k );367 }368 $this->jsSettings['tableSettings'][ $this->tName ]["sKeys"] = implode("&", $escapedKeys );369 $this->jsSettings['tableSettings'][ $this->tName ]["confirmTime"] = $this->lockingObj->ConfirmTime;370 }371 }372 373 374 /**375 * Assign basic page's xt variables376 */377 protected function doCommonAssignments()378 {379 380 if ( $this->mode === EDIT_SIMPLE )381 {382 $this->headerCommonAssign();383 }384 else385 {386 $this->xt->assign("menu_chiddenattr", "data-hidden" );387 }388 389 $this->setLangParams();390 391 // display message392 $this->xt->assign("message_block", true);393 if( $this->isMessageSet() )394 {395 $this->xt->assign("message", $this->message );396 $this->xt->assign("message_class", $this->messageType == MESSAGE_ERROR ? "alert alert-danger" : "alert alert-success" );397 }398 else399 {400 $this->hideElement("message");401 }402 403 // labels404 $this->assignFieldBlocksAndLabels();405 406 // body["end"] - this assignment is very important407 if($this->isSimpleMode() )408 {409 $this->assignBody();410 // assign body end411 $this->xt->assign("flybody", true);412 }413 414 $data = $this->getCurrentRecordInternal();415 $this->xt->assign( "editlink", implode( '&', array( $this->getEditLink( $data ), $this->getStateUrlParams() ) ) );416 }417 418 /**419 * Display the edit page420 */421 protected function displayEditPage()422 {423 // beforeshow event424 $templateFile = $this->templatefile;425 if( $this->eventsObject->exists("BeforeShowEdit") )426 $this->eventsObject->BeforeShowEdit($this->xt, $templateFile, $this->getCurrentrecordInternal(), $this);427 428 if( $this->mode != EDIT_INLINE )429 $this->displayMasterTableInfo();430 // invoked after displayMasterTableInfo to add master viewcontrols maps431 $this->fillSetCntrlMaps();432 433 if( $this->isSimpleMode() )434 {435 $this->display($templateFile);436 return;437 }438 439 if( $this->isPopupMode() || $this->mode == EDIT_DASHBOARD )440 {441 $this->xt->assign("footer", false);442 $this->xt->assign("header", false);443 $this->xt->assign("body", $this->body);444 $this->displayAJAX($templateFile, $this->flyId + 1);445 exit();446 }447 448 if( $this->mode == EDIT_INLINE )449 {450 $returnJSON = array();451 452 $this->xt->load_template( $templateFile );453 454 $returnJSON["htmlControls"] = array();455 foreach($this->editFields as $f) {456 // build controls457 $returnJSON["htmlControls"][ $f ] = $this->xt->fetchVar( GoodFieldName($f)."_editcontrol" );458 }459 460 global $pagesData;461 $returnJSON["pagesData"] = $pagesData;462 $returnJSON["settings"] = $this->jsSettings;463 $returnJSON["controlsMap"] = $this->controlsHTMLMap;464 $returnJSON["viewControlsMap"] = $this->viewControlsHTMLMap;465 466 $returnJSON["additionalJS"] = $this->grabAllJsFiles();467 $returnJSON["additionalCSS"] = $this->grabAllCSSFiles();468 echo printJSON( $returnJSON );469 exit();470 }471 }472 473 /**474 * @param templatefile string475 * @return string476 */477 protected function getBodyMarkup( $templatefile )478 {479 $this->xt->assign("locking", "");480 return $this->lockingMessageBlock . $this->fetchForms( $this->bodyForms );481 }482 483 /**484 * Get extra JSON params to display the page on AJAX-like request485 * @return Array486 */487 protected function getExtraAjaxPageParams()488 {489 return $this->getSaveStatusJSON();490 }491 492 /**493 * Set details preview on the edit master page494 */495 protected function prepareDetailsTables()496 {497 if( !$this->isShowDetailTables /*|| $this->mode == EDIT_DASHBOARD*/ || $this->mode == EDIT_INLINE )498 return;499 500 $dpParams = $this->getDetailsParams( $this->id );501 $this->jsSettings['tableSettings'][ $this->tName ]['dpParams'] = array('tableNames' => $dpParams['strTableNames'], 'ids' => $dpParams['ids']);502 503 if( !$dpParams['ids'] )504 return;505 506 if( $this->mode == EDIT_DASHBOARD )507 $dpTablesParams = array();508 509 $this->xt->assign("detail_tables", true);510 511 $this->flyId = $dpParams['ids'][ count($dpParams['ids']) - 1 ] + 1;512 for($d = 0; $d < count($dpParams['ids']); $d++)513 {514 if( $this->mode != EDIT_DASHBOARD )515 {516 $this->setDetailPreview( $dpParams['type'][ $d ], $dpParams['strTableNames'][ $d ], $dpParams['ids'][ $d ], $this->getCurrentRecordInternal() );517 $this->displayDetailsButtons( $dpParams['type'][ $d ], $dpParams['strTableNames'][ $d ], $dpParams['ids'][ $d ] );518 }519 else520 {521 $this->xt->assign("details_". $dpParams['shorTNames'][ $d ], true);522 $dpTablesParams[] = array(523 "tName" => $dpParams['strTableNames'][ $d ],524 "id" => $dpParams['ids'][ $d ],525 "pType" => $dpParams['type'][ $d ]526 );527 $this->xt->assign("displayDetailTable_" . $dpParams['shorTNames'][ $d ],528 "<div id='dp_".goodFieldName( $this->tName )."_".$this->pageType."_". $dpParams['ids'][ $d ]."'></div>");529 }530 }531 532 if( $this->mode == EDIT_DASHBOARD )533 $this->controlsMap["dpTablesParams"] = $dpTablesParams;534 }535 536 /**537 *538 */539 protected function displayDetailsButtons( $dpType, $dpTableName, $dpId )540 {541 if ( !CheckTablePermissions($dpTableName, "S") )542 return;543 544 if ( $dpType == PAGE_CHART || $dpType == PAGE_REPORT )545 return;546 547 $listPageObject = $this->getDetailsPageObject( $dpTableName, $dpId );548 $listPageObject->assignButtonsOnMasterEdit( $this->xt );549 }550 551 /**552 * Assign buttons xt variables553 */554 protected function prepareButtons()555 {556 if( $this->mode == EDIT_INLINE )557 return;558 559 $this->prepareNextPrevButtons();560 561 if( $this->isPopupMode() )562 {563 $this->xt->assign("close_button", true);564 $this->xt->assign("closebutton_attrs", "id=\"closeButton".$this->id."\"");565 }566 567 $this->xt->assign("save_button", true);568 569 if ( $this->mode !== EDIT_SELECTED_SIMPLE && $this->mode !== EDIT_SELECTED_POPUP ) {570 $this->xt->assign("save_edit", true);571 } else {572 $this->xt->assign("save_update", true);573 }574 575 $addStyle = "";576 if ( $this->isMultistepped() )577 {578 $addStyle = " style=\"display: none;\"";579 }580 581 $this->xt->assign("savebutton_attrs", "id=\"saveButton".$this->id."\"" . $addStyle );582 583 $this->xt->assign("resetbutton_attrs", 'id="resetButton'.$this->id.'"');584 $this->xt->assign("reset_button", true);585 586 if( $this->mode == EDIT_DASHBOARD )587 return;588 589 if( $this->isSimpleMode() )590 {591 if( isset( $_SESSION["successfulEdit"] ) )592 $this->xt->assign("message_back_button", true);593 // back to list/menu buttons594 if( $this->pSet->hasListPage() ) {595 $this->xt->assign("back_button", true);596 $this->xt->assign("backbutton_attrs", "id=\"backButton".$this->id."\"");597 $this->xt->assign("mbackbutton_attrs", "id=\"extraBackButton".$this->id."\"");598 }599 else if( $this->isShowMenu() )600 {601 $this->xt->assign("back_button", true);602 $this->xt->assign("backbutton_attrs", "id=\"backToMenuButton".$this->id."\"");603 }604 }605 606 if( $this->viewAvailable() )607 {608 $this->xt->assign("view_page_button", true);609 $this->xt->assign("view_page_button_attrs", "id=\"viewPageButton".$this->id."\"");610 if( $_SESSION["successfulEdit"] ) {611 $this->xt->assign("message_view_page_button", true);612 }613 }614 615 unset( $_SESSION["successfulEdit"] );616 }617 618 protected function prepareNextPrevButtons()619 {620 if( !$this->pSet->useMoveNext() ) {621 $this->hideItemType("prev");622 $this->hideItemType("next");623 return;624 }625 626 $nextPrev = $this->getNextPrevRecordKeys( $this->getCurrentRecordInternal() );627 628 //show Prev/Next buttons629 $this->assignPrevNextButtons( !!$nextPrev["next"], !!$nextPrev["prev"], $this->mode == EDIT_DASHBOARD && ($this->hasTableDashGridElement() || $this->hasDashMapElement()) ); // TODO: haMajorDashElem630 631 $this->jsSettings["tableSettings"][ $this->tName] ["prevKeys"] = $nextPrev["prev"];632 $this->jsSettings["tableSettings"][ $this->tName ]["nextKeys"] = $nextPrev["next"];633 }634 635 protected function readRecord()636 {637 if( $this->getCurrentRecordInternal() )638 return true;639 if($this->isSimpleMode() )640 {641 HeaderRedirect($this->pSet->getShortTableName(), "list", "a=return&".$this->getStateUrlParams());642 exit();643 }644 // nothing to edit.645 // TODO: add some report or message646 exit();647 return false;648 }649 650 /**651 * Format and prepare readonly field values652 */653 protected function prepareReadonlyFields()654 {655 $fields = $this->pSet->getFieldsList();656 $data = $this->getFieldControlValues();657 658 // prepare field values659 // keys660 $keyParams = array();661 foreach( $this->pSet->getTableKeys() as $i => $k )662 {663 $keyParams[] = "key" . ($i + 1) . "=" . runner_htmlspecialchars( rawurlencode( $this->keys[ $k ] ) );664 }665 $keylink = "&" . implode("&", $keyParams);666 667 foreach( $fields as $f )668 {669 if( $this->getEditFormat( $f ) == EDIT_FORMAT_READONLY &&670 ( $this->pSet->appearOnEditPage( $f ) || $this->pSet->appearOnInlineEdit( $f ) ) )671 $this->readOnlyFields[ $f ] = $this->showDBValue( $f , $data, $keylink );672 }673 }674 675 /**676 * Locks record for editing.677 * Returns false if the page can not continue processing. True otherwise.678 */679 protected function lockRecord() {680 if( !$this->lockingObj )681 return true;682 683 // locked OK684 if( $this->lockingObj->LockRecord( $this->tName, $this->keys) ) {685 $this->lockingMessageBlock = '<div class="rnr-locking" style="display:none" '.$this->lockingMessageAttr. '>' 686 .$this->lockingMessageText. '</div>';687 688 $this->xt->assign( "locking", $this->lockingMessageBlock );689 return true;690 }691 692 // NOT locked693 if( $this->mode == EDIT_INLINE ) {694 // inline mode695 $returnJSON = array();696 $returnJSON['success'] = false;697 if( $this->lockingAdmin() )698 $returnJSON['message'] = $this->lockingObj->GetLockInfo( $this->tName, $this->keys, false, $this->id );699 else700 $returnJSON['message'] = $this->lockingObj->LockUser;701 702 echo printJSON( $returnJSON );703 exit();704 }705 706 // other modes707 $this->lockingMessageText = $this->lockingObj->LockUser;708 // send flag to client709 $this->pageData["lockedByOther"] = true;710 711 if( $this->lockingAdmin() ) {712 $ribbonMessage = $this->lockingObj->GetLockInfo( $this->tName, $this->keys, true, $this->id );713 if( $ribbonMessage != "" )714 $this->lockingMessageText = $ribbonMessage;715 }716 717 $this->lockingMessageBlock = '<div class="rnr-locking" style="display:none">' .$this->lockingMessageText. '</div>';718 $this->xt->assign( "locking", $this->lockingMessageBlock );719 720 return true;721 }722 723 /**724 * Print JSON containing a saved record data on ajax-like request725 */726 protected function reportInlineSaveStatus()727 {728 echo printJSON( $this->getSaveStatusJSON() );729 exit();730 }731 732 /**733 * Get an array containing the record save status734 * @return Array735 */736 protected function getSaveStatusJSON()737 {738 $returnJSON = array();739 740 if( $this->action != "edited" || $this->isSimpleMode() )741 return $returnJSON;742 743 $returnJSON['success'] = $this->updatedSuccessfully;744 $returnJSON['message'] = $this->message;745 $returnJSON['lockMessage'] = $this->lockingMessageText;746 747 if( !$this->isCaptchaOk )748 $returnJSON['wrongCaptchaFieldName'] = $this->getCaptchaFieldName();749 750 if( !$this->updatedSuccessfully )751 return $returnJSON;752 753 // successful update. Return new keys and field values754 $data = $this->getCurrentRecordInternal();755 if( !$data )756 $data = $this->newRecordData;757 758 // details tables keys759 $returnJSON['detKeys'] = array();760 foreach( $this->pSet->getDetailTablesArr() as $dt )761 {762 $dkeys = array();763 foreach( $dt["masterKeys"] as $idx => $mk )764 {765 $dkeys[ "masterkey".($idx + 1) ] = $data[ $mk ];766 }767 $returnJSON['detKeys'][ $dt['dDataSourceTable'] ] = $dkeys;768 }769 770 // prepare field values771 // keys772 $keyParams = array();773 foreach( $this->pSet->getTableKeys() as $i => $k )774 {775 $keyParams[] = "key" . ($i + 1) . "=" . runner_htmlspecialchars( rawurlencode( $this->keys[ $k ] ) );776 }777 $keylink = "&" . implode("&", $keyParams);778 779 // values780 $values = array();781 $rawValues = array();782 $controlValues = array();783 784 $listPSet = new ProjectSettings( $this->tName, PAGE_LIST, $this->hostPageName, $this->pageTable );785 // override viewControls so that field values are built for the host List page and not for the Edit786 $this->viewControls = new ViewControlsContainer( $listPSet, PAGE_LIST, $this );787 788 foreach( $this->pSet->getFieldsList() as $f )789 {790 $value = $this->showDBValue( $f, $data, $keylink );791 $values[ $f ] = $value;792 if( IsBinaryType( $this->pSet->getFieldType( $f ) ) )793 $rawValues[ $f ] = "";794 else {795 $rawValues[ $f ] = runner_substr($data[ $f ], 0, 100);796 $controlValues[ $f ] = $data[ $f ];797 }798 }799 800 $returnJSON['keys'] = $this->jsKeys;801 $returnJSON['masterKeys'] = $this->getDetailTablesMasterKeys($data);802 $returnJSON['keyFields'] = $this->pSet->getTableKeys();803 $returnJSON['oldKeys'] = array();804 // add old keys805 $i = 0;806 foreach($this->oldKeys as $field => $value)807 {808 $returnJSON['oldKeys'][ $i++ ] = $value;809 }810 811 $returnJSON['controlValues'] = $controlValues; 812 813 $returnJSON['vals'] = $values;814 $returnJSON['fields'] = $this->pSet->getFieldsList();815 $returnJSON['rawVals'] = $rawValues;816 $returnJSON['hrefs'] = $this->buildDetailGridLinks( $returnJSON['detKeys'] );817 818 // the record might become non-editable after updating819 if( !$this->IsRecordEditable( false ) )820 $returnJSON['nonEditable'] = true;821 822 $dmapIconsData = $this->getDashMapsIconsData( $data );823 if( !!$dmapIconsData )824 $returnJSON['mapIconsData'] = $dmapIconsData;825 826 $fieldsIconsData = $this->getFieldMapIconsData( $data );827 if( !!$fieldsIconsData )828 $returnJSON['fieldsMapIconsData'] = $fieldsIconsData;829 830 $returnJSON['editFields'] = $this->editFields;831 if( $this->forSpreadsheetGrid ) {832 $returnJSON['editFields'] = $listPSet->getInlineEditFields();833 }834 835 return $returnJSON;836 }837 838 /**839 * It redirects to a new page840 * according to the edit page settings841 * @return Boolean842 */843 protected function afterEditActionRedirect()844 {845 if( !$this->isSimpleMode() )846 return false;847 848 $stateParams = $this->getStateUrlParams();849 850 switch( $this->getAfterEditAction() )851 {852 case AE_TO_EDIT:853 return $this->prgRedirect();854 855 case AE_TO_LIST:856 if( $this->pSet->hasListPage() ) {857 HeaderRedirect($this->shortTableName, PAGE_LIST, "a=return&" 858 .( $this->listPage ? "page=".$this->listPage."&" : "" ). $stateParams );859 } else {860 HeaderRedirect("menu");861 }862 return true;863 864 case AE_TO_VIEW:865 HeaderRedirect( $this->shortTableName, PAGE_VIEW, implode( '&', array( $this->getKeyParams(), $stateParams ) ) );866 return true;867 868 case AE_TO_PREV_EDIT:869 $_SESSION["message_edit"] = $this->message . "";870 $prevKeys = $this->getPrevKeys();871 872 HeaderRedirect( $this->shortTableName, PAGE_EDIT, implode( '&', array( $this->getKeyParams( $prevKeys ), $stateParams ) ) );873 return true;874 875 case AE_TO_NEXT_EDIT:876 $_SESSION["message_edit"] = $this->message . "";877 $nextKeys = $this->getNextKeys();878 879 HeaderRedirect( $this->shortTableName, PAGE_EDIT, implode( '&', array( $this->getKeyParams( $nextKeys ), $stateParams ) ) );880 return true;881 882 case AE_TO_DETAIL_LIST:883 $dTName = $this->pSet->getAEDetailTable();884 HeaderRedirect( GetTableURL( $dTName ), PAGE_LIST, implode("&", $this->getNewRecordMasterKeys( $dTName ) ). "&mastertable=" .$this->tName );885 return true;886 887 default:888 return false;889 }890 }891 892 893 function getNewRecordMasterKeys( $dTName )894 {895 $data = $this->getCurrentRecordInternal();896 897 $mKeys = array();898 foreach($this->pSet->getMasterKeysByDetailTable( $dTName ) as $i => $mk)899 {900 $mKeys[] = "masterkey". ($i + 1) . "=" .$data[ $mk ];901 }902 return $mKeys;903 }904 905 906 /**907 * Get the previous record keys908 * @return Array909 */910 protected function getPrevKeys()911 {912 if( isset($this->prevKeys) && !is_null($this->prevKeys))913 return $this->prevKeys;914 915 $keys = $this->getNextPrevRecordKeys( $this->getCurrentRecordInternal(), PREV_RECORD );916 $this->prevKeys = $keys['prev'];917 return $this->prevKeys;918 }919 920 /**921 * Get the next record keys922 * @return Array923 */924 protected function getNextKeys()925 {926 if( isset($this->nextKeys) && !is_null($this->nextKeys) )927 return $this->nextKeys;928 929 $keys = $this->getNextPrevRecordKeys( $this->getCurrentRecordInternal(), NEXT_RECORD );930 $this->nextKeys = $keys['next'];931 return $this->nextKeys;932 }933 934 935 /**936 * POST-REDIRECT-GET937 * Redirect after saving the data to avoid saving again on refresh.938 */939 protected function prgRedirect()940 {941 if( $this->stopPRG )942 return false;943 if( !$this->updatedSuccessfully || !$this->isSimpleMode() || !no_output_done() )944 return false;945 946 $_SESSION["message_edit"] = $this->message . "";947 $_SESSION["message_edit_type"] = $this->messageType;948 949 $getParams = implode( '&', array( $this->getKeyParams(), $this->getStateUrlParams() ) );950 if ( $this->pageName )951 {952 $getParams .= "&page=".$this->pageName;953 }954 HeaderRedirect( $this->pSet->getShortTableName(), $this->getPageType(), $getParams );955 exit();956 return true;957 }958 959 /**960 * POST-REDIRECT-GET961 * Read the saved message on the GET step.962 */963 protected function prgReadMessage()964 {965 if( !$this->isSimpleMode() || !isset($_SESSION["message_edit"]) )966 return;967 968 $this->setMessage( $_SESSION["message_edit"] );969 $this->messageType = $_SESSION["message_edit_type"];970 971 unset($_SESSION["message_edit"]);972 }973 974 /**975 * @return Array976 */977 public function getCurrentRecord()978 {979 $data = $this->getCurrentRecordInternal();980 $newData = array();981 982 foreach($data as $fName => $val)983 {984 $editFormat = $this->getEditFormat($fName);985 if( $editFormat == EDIT_FORMAT_DATABASE_FILE || $editFormat==EDIT_FORMAT_DATABASE_IMAGE )986 {987 if( $data[ $fName ] )988 $newData[ $fName ] = true;989 else990 $newData[ $fName ] = false;991 }992 }993 994 foreach($newData as $fName => $val) // .net compatibility issue995 {996 $data[ $fName ] = $val;997 }998 999 return $data;1000 }1001 1002 /**1003 * @param Boolean useOldKeys1004 * @return String1005 */1006 public function getKeysWhereClause( $useOldKeys )1007 {1008 $dc = new DsCommand;1009 $dc->keys = $useOldKeys 1010 ? $this->oldKeys1011 : $this->keys;1012 $dc->filter = $this->getSecurityCondition();1013 $sql = $this->dataSource->prepareSQL($dc );1014 return $sql["where"];1015 }1016 1017 /**1018 * Read current values from the database1019 * @return Array The current record data1020 */1021 public function getCurrentRecordInternal()1022 {1023 if( !is_null($this->cachedRecord) )1024 return $this->cachedRecord;1025 1026 $dc = $this->getSingleRecordCommand();1027 1028 if( $this->eventsObject->exists("BeforeQueryEdit") )1029 {1030 $prep = $this->dataSource->prepareSQL( $dc );1031 $where = $prep["where"];1032 $sql = $prep["sql"];1033 1034 $this->eventsObject->BeforeQueryEdit($sql, $where, $this);1035 1036 if( $sql != $prep["sql"] ) {1037 $this->dataSource->overrideSQL( $dc, $sql );1038 } else if( $where != $prep["where"] ) {1039 $this->dataSource->overrideWhere( $dc, $where );1040 }1041 }1042 1043 $fetchedArray = $this->dataSource->getSingle( $dc )->fetchAssoc();1044 $this->cachedRecord = $this->cipherer->DecryptFetchedArray( $fetchedArray );1045 1046 if( !$this->checkKeysSet() )1047 {1048 $this->keys = $this->getKeysFromData( $this->cachedRecord );1049 $this->setKeysForJs();1050 }1051 1052 if( !$this->cachedRecord && $this->mode == EDIT_SIMPLE )1053 return $this->cachedRecord;1054 1055 foreach($this->getPageFields() as $fName)1056 {1057 if( @$_POST["a"]!= "edited" && $this->pSet->getAutoUpdateValue($fName) !== "" )1058 $this->cachedRecord[ $fName ] = $this->pSet->getAutoUpdateValue($fName);1059 }1060 1061 if($this->readEditValues)1062 {1063 foreach($this->getPageFields() as $fName)1064 {1065 $editFormat = $this->getEditFormat($fName);1066 if( !ProjectSettings::uploadEditType( $editFormat ) && $editFormat!== EDIT_FORMAT_READONLY )1067 $this->cachedRecord[ $fName ] = $this->newRecordData[ $fName ];1068 }1069 }1070 1071 1072 return $this->cachedRecord;1073 }1074 1075 /**1076 * Check if the keys values were set through GET/POST 'editid' params1077 * or by using the setKeys method directly1078 * @return Boolean1079 */1080 protected function checkKeysSet()1081 {1082 foreach($this->keys as $kValue)1083 {1084 if( strlen($kValue) )1085 return true;1086 }1087 return false;1088 }1089 1090 /**1091 * @return Array - field values to be shown in edit controls1092 */1093 protected function getFieldControlValues()1094 {1095 $data = $this->getFieldControlsData();1096 if( $this->readEditValues ) {1097 foreach( $this->editFields as $f ) {1098 if( !isset( $this->newRecordData[ $f ] ) )1099 continue;1100 1101 $editFormat = $this->getEditFormat( $f );1102 if( !ProjectSettings::uploadEditType( $editFormat ) && $editFormat != EDIT_FORMAT_READONLY ) {1103 1104 $data[ $f ] = $this->newRecordData[ $f ];1105 }1106 }1107 }1108 return $data;1109 }1110 1111 public function getEditFormat( $field, $pSet = null ) {1112 $isDetKeyField = in_array( $field, $this->detailKeysByM );1113 if( $isDetKeyField ) {1114 return EDIT_FORMAT_READONLY;1115 }1116 return parent::getEditFormat( $field, $pSet );1117 }1118 1119 1120 protected function prepareEditControl( $fName, &$data ) {1121 $firstElementId = $this->getControl( $fName, $this->id )->getFirstElementId();1122 if( $firstElementId )1123 $this->xt->assign( "labelfor_" . GoodFieldName( $fName ), $firstElementId );1124 1125 $parameters = $this->getEditContolParams( $fName, $this->id, $data );1126 $this->xt->assign_function( GoodFieldName( $fName )."_editcontrol", "xt_buildeditcontrol", $parameters );1127 1128 $controls = $this->getContolMapData( $fName, $this->id, $data, $this->editFields );1129 if ( in_array( $fName, $this->errorFields ) )1130 $controls["controls"]["isInvalid"] = true;1131 1132 $this->fillControlsMap( $controls );1133 1134 $this->fillControlFlags( $fName );1135 1136 // fill special settings for timepicker1137 if( $this->getEditFormat($fName) == 'Time' )1138 $this->fillTimePickSettings( $fName, $data[ $fName ] );1139 1140 if( $this->pSet->getViewFormat($fName) == FORMAT_MAP )1141 $this->googleMapCfg['isUseGoogleMap'] = true;1142 }1143 1144 /**1145 * Prepare edit controls1146 */1147 public function prepareEditControls() {1148 if( $this->mode == EDIT_INLINE ) {1149 $this->editFields = $this->removeHiddenColumnsFromInlineFields(1150 $this->editFields,1151 $this->screenWidth,1152 $this->screenHeight,1153 $this->orientation1154 );1155 }1156 1157 // prepare values1158 $data = $this->getFieldControlValues();1159 1160 foreach( $this->editFields as $fName ) {1161 $this->prepareEditControl( $fName, $data );1162 }1163 }1164 1165 1166 public static function readEditModeFromRequest()1167 {1168 if(postvalue("editType") == "inline")1169 return EDIT_INLINE;1170 elseif(postvalue("editType") == EDIT_POPUP)1171 return EDIT_POPUP;1172 elseif(postvalue("mode") == "dashrecord")1173 return EDIT_DASHBOARD;1174 else1175 return EDIT_SIMPLE;1176 }1177 1178 public static function processEditPageSecurity( $table )1179 {1180 // user has necessary permissions1181 if( Security::checkPagePermissions( $table, "E" ) )1182 return true;1183 1184 // display entered data. Give the user chance to relogin. Do nothing for now.1185 if( postvalue("a") == "edited" )1186 return true;1187 1188 // page can not be displayed. Redirect or return error1189 1190 $pageMode = EditPage::readEditModeFromRequest();1191 1192 // return error if the page is requested by AJAX1193 if( $pageMode != EDIT_SIMPLE )1194 {1195 $messageLink = "";1196 if( !isLogged() || Security::isGuest() )1197 $messageLink = " <a href='#' id='loginButtonContinue'>". "Login" . "</a>";1198 Security::sendPermissionError( $messageLink );1199 return false;1200 }