Advertisement
Guest User

Untitled

a guest
Mar 1st, 2015
8,994
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 377.98 KB | None | 0 0
  1. <?php
  2. // *****************************************************************************
  3. // Copyright 2003-2005 by A J Marston <http://www.tonymarston.net>
  4. // Copyright 2006-2014 by Radicore Software Limited <http://www.radicore.org>
  5. // *****************************************************************************
  6.  
  7. class Default_Table
  8. {
  9. // member variables
  10. var $access_count; // count of accesses since instantiation
  11. var $allow_empty_where = false; // switch to allow an empty $where string in STD.LIST2.INC
  12. var $allow_db_function = array(); // allow a field's value in a database insert/update to contain a function name
  13. var $allow_scrolling = false; // used inside ADD2 pattern to allow scrolling between selected rows
  14. var $alt_language_table; // table holding alternative language text
  15. var $alt_language_cols; // columns holding alternative language text
  16. var $audit_logging; // yes/no switch
  17.  
  18. var $checkPrimaryKey = false; // yes/no switch
  19. var $child_relations = array(); // child relationship specifications (optional)
  20. var $css_files = array(); // optional CSS file names
  21. var $csv; // object for CSV processing
  22. var $custom_processing_object; // name of object containing code for custom processing
  23. var $custom_replaces_standard = false; // if set to TRUE in a custom method then the standard method must not be run
  24.  
  25. var $dbms_engine = ''; // database engine (mysql, postgresql, oracle, etc)
  26. var $dbname; // database name as recorded in the Data Dictionary
  27. var $dbname_server; // database name after being switched in the CONFIG.INC file
  28. var $dbname_old; // refer to _switch_database() method
  29. var $dbprefix = ''; // prefix (for shared servers)
  30. var $dirname; // directory name of current script
  31. var $dirname_dict; // directory name where '*.dict.inc' script is located (optional)
  32.  
  33. var $download_filename; // file to be downloaded
  34. var $download_mode; // 'inline' or null
  35.  
  36. var $delete_count; // count of records deleted
  37. var $insert_count; // count of records inserted
  38. var $update_count; // count of records updated
  39. var $unchange_count; // count of records unchanged
  40.  
  41. var $errors = array(); // array of errors
  42. var $expanded; // list of tree nodes which have been expanded
  43. var $fieldarray = array(); // array of row/field data
  44. var $fieldspec = array(); // field specifications (see class constructor)
  45. var $fields_not_for_trimming = array(); // array of field names which are not to be trimmed
  46. var $field_access; // see setFieldAccess()
  47. var $ignore_empty_fields = false; // YES/NO switch (see getInitialData() method)
  48. var $initial_values; // from MNU_INITIAL_VALUES_USER/ROLE
  49. var $initiated_from_controller = false; // source of object instantiation
  50. var $inner_table; // used in an outer-link-inner relationship
  51. var $instruction; // instruction to be passed to previous script
  52. var $is_link_table = false; // used in method _sqlAssembleWhere (many-link-many relationship)
  53. var $javascript = array(); // optional JavaScript code
  54. var $lastpage; // last available page number in current query
  55. var $link_item; // used in _sqlAssembleWhere() in many-to-many relationships
  56. var $lookup_data = array(); // array of lookup data (for dropdowns, radio groups)
  57. var $lookup_css = array(); // optional css classes for $lookup_data
  58. var $messages = array(); // array of messages
  59. var $nameof_end_date; // alias for 'end_date'
  60. var $nameof_start_date; // alias for 'start_date'
  61. var $noedit_array; // array of fields which cannot be updated
  62. var $no_controller_msg = false; // prevent page controller from creating a message concerning this object
  63. var $no_convert_timezone = false; // turn off all timezone conversions
  64. var $no_csv_header = false; // turns off creation of header row in CSV output file
  65. var $no_display_count = false; // yes/no switch to display count after multiple inserts or updates
  66. var $no_duplicate_error = false; // if TRUE do not create an error when inserting a duplicate
  67. var $no_foreign_data = false; // if TRUE do not call getForeignData() method
  68. var $no_submit_on_error = false; // if TRUE drop any SUBMIT buttons after a validation error
  69. var $numrows; // number of rows retrieved
  70. var $outer_table; // used in an outer-link-inner relationship
  71. var $pageno; // requested page number
  72. var $parent_relations = array(); // parent relationship specifications (optional)
  73.  
  74. var $parent_object; // reference to parent object (if there is one in current task)
  75. var $child_object; // reference to child object (if there is one in current task)
  76.  
  77. var $pdf; // object for PDF processing
  78. var $pdf_filename; //
  79. var $pdf_destination; // I=Inline (browser), D=Download (browser), F=Filename (on server), S=String
  80.  
  81. var $picker_subdir; // subdirectory for the File Picker
  82. var $picker_filetypes = array(); // array of file types
  83.  
  84. var $primary_key = array(); // column(s) which form the primary key
  85. var $report_structure; // report structure
  86. var $resize_array; // used in file uploads
  87. var $retry_on_duplicate_key; // field name to be incremented when insert fails
  88. var $reuse_previous_select = false; // reuse previous SELECT in _dml_ReadBeforeUpdate()
  89. var $rows_per_page = 0; // page size for multi-row forms
  90. var $row_locks; // FALSE, SH=shared, EX=exclusive
  91. var $row_locks_supp; // supplemental lock type
  92. var $scrollarray; // array for internal scrolling
  93. var $scrollindex; // index to current item in scrollarray
  94. var $select_string; // identifies which entries have been selected
  95. var $skip_getdata = false; // YES/NO switch
  96. var $skip_validation = false; // YES/NO switch
  97. var $tablename; // table name (internal)
  98. var $transaction_level; // transaction level
  99. var $unbuffered_query = false; // used in getData_serial()
  100. var $unique_keys = array(); // unique key specifications (optional)
  101. var $update_on_duplicate_key=false; // switch to 'update' if insert fails
  102.  
  103. var $upload_subdir; // subdirectory for file upoads
  104. var $upload_filetypes = array(); // file types for uploading
  105. var $upload_maxfilesize; // max file size for uploading
  106.  
  107. var $wf_case_id; // workflow case id
  108. var $wf_context; // workitem context
  109. var $wf_workitem_id; // workflow workitem id
  110. var $wf_user_id; // update workitem with this value, not $_SESSION['logon_user_id']
  111.  
  112. var $xsl_params = array(); // optional parameters to be passed to XSL transformation
  113.  
  114. var $zone; // set by page controller - main/outer/middle/inner
  115.  
  116. // the following are used to construct SQL queries
  117. var $default_orderby = null; // default for table, may be overridden by $sql_orderby
  118. var $default_orderby_task = null; // default for task, may be overridden by $sql_orderby
  119. var $sql_from;
  120. var $sql_groupby;
  121. var $sql_having;
  122. var $sql_no_foreign_db = false; // if TRUE _sqlProcessJoin() method will skip tables in other databases
  123. var $sql_orderby; // sort field
  124. var $prev_sql_orderby; // previous sort field
  125. var $sql_orderby_seq; // 'asc' or 'desc'
  126. var $sql_orderby_table; // tablename qualifier for optional sort criteria
  127. var $sql_search; // optional search criteria from a search screen (modifiable)
  128. var $sql_search_orig; // original search criteria (unmodified)
  129. var $sql_search_table; // tablename qualifier for optional search criteria
  130. var $sql_select; // fields to be selected
  131. var $sql_selection; // selection passed down from previous task
  132. var $sql_union; // optional UNION clause
  133. var $sql_where; // additional selection criteria
  134. var $where; // passed from parent form
  135.  
  136. // ****************************************************************************
  137. // class constructor
  138. // ****************************************************************************
  139. function Default_Table ()
  140. {
  141. // save directory name of current script
  142. //$this->dirname = dirname(__file__);
  143.  
  144. $this->dbms_engine = ''; // to be supplied by getFieldSpec_original()
  145. $this->dbprefix = ''; // to be supplied by getFieldSpec_original()
  146. $this->tablename = 'default';
  147. $this->dbname = 'default';
  148.  
  149. // call this method to get original field specifications
  150. // (note that they may be modified at runtime)
  151. $this->fieldspec = $this->getFieldSpec_original();
  152.  
  153. } // Default_Table
  154.  
  155. // ****************************************************************************
  156. function array2string ($array)
  157. // return an array of values (for a SET/ARRAY/VARRAY datatype) as a string.
  158. // NOTE: the format of the string is dependent upon the DBMS.
  159. {
  160. $DML =& $this->_getDBMSengine($this->dbname);
  161.  
  162. if (is_string($array)) {
  163. return $array;
  164. } // if
  165.  
  166. $string = $DML->array2string($array);
  167.  
  168. return $string;
  169.  
  170. } // array2string
  171.  
  172. // ****************************************************************************
  173. function cascadeDelete ($where, $parent_table=null)
  174. // Parent record is being deleted, so remove associated records from this table.
  175. {
  176. $errors = array();
  177. $this->delete_count = null;
  178.  
  179. // retrieve all records which match criteria in $where
  180. $fieldarray = $this->getData_raw($where);
  181. $errors = array_merge($errors, $this->errors);
  182.  
  183. // now delete them one at a time
  184. $count = 0;
  185. foreach ($fieldarray as $rowdata) {
  186. $rowdata['rdc_no_rollup'] = true; // do not cause delete of child to update the parent in a callback
  187. $rowdata = $this->_cm_pre_cascadeDelete($rowdata);
  188. $rowdata = $this->deleteRecord($rowdata, $parent_table);
  189. if (!empty($this->errors)) {
  190. foreach ($this->errors as $error) {
  191. $errors[] = "$this->tablename - $error";
  192. } // foreach
  193. break;
  194. } // if
  195. $count++;
  196. } // foreach
  197. unset($fieldarray);
  198.  
  199. if (count($errors) > 0) {
  200. $this->errors = $errors;
  201. return false;
  202. } // if
  203.  
  204. // save count so that values may be accumulated
  205. $this->delete_count[strtoupper($this->tablename)] = $count;
  206.  
  207. // $count rows were deleted
  208. return $this->getLanguageText('sys0004', $count, strtoupper($this->tablename));
  209.  
  210. } // cascadeDelete
  211.  
  212. // ****************************************************************************
  213. function cascadeNullify ($update_array, $where)
  214. // Parent record is being deleted, so nullify foreign keys in associated records in this table.
  215. {
  216. $errors = array();
  217.  
  218. // retrieve all records which match criteria in $where
  219. $fieldarray = $this->getData_raw($where);
  220. $errors = array_merge($errors, $this->errors);
  221.  
  222. // now update them one at a time
  223. foreach ($fieldarray as $rowdata) {
  224. $rowdata = array_merge($rowdata, $update_array);
  225. $rowdata = $this->updateRecord($rowdata);
  226. foreach ($this->errors as $error) {
  227. $errors[] = "$this->tablename - $error";
  228. } // foreach
  229. } // foreach
  230.  
  231. if (count($errors) > 0) {
  232. $this->errors = $errors;
  233. return false;
  234. } // if
  235.  
  236. return true;
  237.  
  238. } // cascadeNullify
  239.  
  240. // ****************************************************************************
  241. function changeConfig ($fieldarray)
  242. // check to seein any configuration settings need to be changed.
  243. {
  244. $where = null;
  245.  
  246. if (is_object($this->custom_processing_object)) {
  247. if (method_exists($this->custom_processing_object, '_cm_changeConfig')) {
  248. $fieldarray = $this->custom_processing_object->_cm_changeConfig($where, $fieldarray);
  249. } // if
  250. } // if
  251. if ($this->custom_replaces_standard) {
  252. $this->custom_replaces_standard = false;
  253. } else{
  254. // change current table configuration (optional)
  255. $fieldarray = $this->_cm_changeConfig($where, $fieldarray);
  256. } // if
  257.  
  258. return $fieldarray;
  259.  
  260. } // changeConfig
  261.  
  262. // ****************************************************************************
  263. function checkWorkflow ($where)
  264. // check workflow system to see if this task is a pending workitem.
  265. {
  266. $this->errors = array();
  267.  
  268. if (preg_match('/^(workflow|audit)$/i', $this->dbname) OR defined('TRANSIX_NO_WORKFLOW') OR defined('RADICORE_NO_WORKFLOW')) {
  269. // do nothing
  270. } else {
  271. // find out if this task/context is a workitem within a workflow instance
  272. $this->_examineWorkflowInstance($where);
  273. } // if
  274.  
  275. return $this->errors;
  276.  
  277. } // checkWorkflow
  278.  
  279. // ****************************************************************************
  280. function clearEditableData ($fieldarray)
  281. // initialise all editable fields in $fieldarray.
  282. {
  283. $fieldspec = $this->fieldspec;
  284.  
  285. foreach ($fieldarray as $field => $value) {
  286. if (array_key_exists($field, $fieldspec)) {
  287. if ($field == 'curr_or_hist') {
  288. // reset to 'current' dates (the default)
  289. $fieldarray[$field] = 'C';
  290. } elseif (array_key_exists('noedit', $fieldspec[$field])) {
  291. // field is not editable, so leave it alone
  292. } else {
  293. // field is editable, so remove current value
  294. $fieldarray[$field] = NULL;
  295. } // if
  296. } else {
  297. $fieldarray[$field] = NULL;
  298. } // if
  299. } // foreach
  300.  
  301. $this->fieldarray = $fieldarray;
  302.  
  303. return $fieldarray;
  304.  
  305. } // clearEditableData
  306.  
  307. // ****************************************************************************
  308. function clearScrollArray ()
  309. // initialise the internal $scrollarray.
  310. {
  311. $this->scrollarray = array();
  312.  
  313. $this->scrollindex = 0;
  314. $this->pageno = 0;
  315. $this->numrows = 0;
  316. $this->lastpage = 0;
  317.  
  318. return;
  319.  
  320. } // clearScrollArray
  321.  
  322. // ****************************************************************************
  323. function commit ()
  324. // commit this transaction
  325. {
  326. $errors = array();
  327.  
  328. $this->sql_union = null;
  329.  
  330. if (preg_match('/^(workflow|audit)$/i', $this->dbname) OR defined('TRANSIX_NO_WORKFLOW') OR defined('RADICORE_NO_WORKFLOW')) {
  331. // do nothing
  332. } else {
  333. // if this task+context is a pending workitem then update it
  334. $errors = $this->_examineWorkflow($this->fieldarray);
  335. } // if
  336.  
  337. $DML =& $this->_getDBMSengine($this->dbname);
  338. if ($errors) {
  339. $result = $DML->rollback($this->dbname_server);
  340. } else {
  341. if ($result = $DML->commit($this->dbname_server)) {
  342. // update has been committed, so remove any 'run_at_cancel' reference
  343. if ($this->initiated_from_controller) {
  344. if (isset($GLOBALS['script_vars']['task_id_run_at_cancel'])) {
  345. unset($GLOBALS['script_vars']['task_id_run_at_cancel']);
  346. unset($GLOBALS['script_vars']['task_id_run_at_cancel_context']);
  347. } // if
  348. $script_vars = updateScriptVars($GLOBALS['script_vars']);
  349. } // if
  350. } else {
  351. $errors[] = $this->getLanguageText('sys0009'); // 'Commit failed'
  352. } // if
  353. } // if
  354.  
  355. $GLOBALS['transaction_has_started'] = FALSE;
  356.  
  357. return $errors;
  358.  
  359. } // commit
  360.  
  361. // ****************************************************************************
  362. function convertTimeZone ($fieldarray, $fieldspec)
  363. // convert any datetime fields from client timezone to server timezone.
  364. {
  365. if (isset($_SESSION['display_timezone_party']) AND is_True($_SESSION['display_timezone_party'])) {
  366. if (!empty($fieldarray['party_timezone'])) {
  367. $timezone_client = $fieldarray['party_timezone']; // timezone of data's party
  368. } else {
  369. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  370. } // if
  371. } else {
  372. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  373. } // if
  374.  
  375. if (empty($_SESSION['timezone_server']) OR empty($timezone_client)) {
  376. return $fieldarray; // nothing to do
  377. } // if
  378.  
  379. $dateobj =& RDCsingleton::getInstance('date_class');
  380.  
  381. foreach ($fieldspec as $field => $spec) {
  382. if (!empty($fieldarray[$field])) {
  383. if (preg_match('/^(datetime|timestamp)$/i', $spec['type'])) {
  384. if (!isset($spec['noedit']) AND !isset($spec['nodisplay'])) {
  385. $datetime = $dateobj->getInternalDateTime($fieldarray[$field], $spec);
  386. if ($datetime === false) {
  387. $this->errors[$field] = $dateobj->errors;
  388. } // if
  389. $fieldarray[$field] = convertTZ($datetime,
  390. $timezone_client,
  391. $_SESSION['timezone_server']);
  392. } // if
  393. } elseif (preg_match('/^(date)$/i', $spec['type'])) {
  394. if (!isset($spec['noedit']) AND !isset($spec['nodisplay'])) {
  395. $date = $dateobj->getInternalDate($fieldarray[$field], $spec);
  396. if ($date === false) {
  397. $this->errors[$field] = $dateobj->errors;
  398. } // if
  399. $fieldarray[$field] = convertTZdate($date,
  400. '12:00:00',
  401. $timezone_client,
  402. $_SESSION['timezone_server']);
  403. } // if
  404. } // if
  405. } // if
  406. } // foreach
  407.  
  408. return $fieldarray;
  409.  
  410. } // convertTimeZone
  411.  
  412. // ****************************************************************************
  413. function currentOrHistoric ($string, $start_date='start_date', $end_date='end_date')
  414. // convert the string 'current/historic/future' into a date range.
  415. // NOTE: defaults to fields named START_DATE and END_DATE, but this may be changed.
  416. {
  417. if (empty($start_date)) {
  418. $start_date = 'start_date';
  419. } // if
  420. if (empty($end_date)) {
  421. $end_date = 'end_date';
  422. } // if
  423.  
  424. // convert search string into an indexed array
  425. $search = where2array($string, false, false);
  426.  
  427. if (isset($search['curr_or_hist'])) {
  428. // replace Current/Historic/Future with a range of dates
  429. $search1 = stripOperators($search);
  430.  
  431. // check that $start_date and $end_date exist in this table
  432. if (!array_key_exists($start_date, $this->fieldspec) OR !array_key_exists($end_date, $this->fieldspec)) {
  433. $search1['curr_or_hist'] = 'invalid';
  434. } else {
  435. $today = getTimeStamp('date');
  436. switch ($search1['curr_or_hist']) {
  437. case 'C':
  438. // search for records with CURRENT dates
  439. $search[$start_date] = "<='$today 23:59:59'";
  440. $search[$end_date] = ">='$today 00:00:00'";
  441. break;
  442. case 'H':
  443. // search for records with HISTORIC dates
  444. $search[$end_date] = "<'$today 00:00:00'";
  445. break;
  446. case 'F':
  447. // search for records with FUTURE dates
  448. $search[$start_date] = ">'$today 23:59:59'";
  449. default:
  450. ;
  451. } // switch
  452. } // if
  453.  
  454. // rebuild search string without 'curr_or_hist' flag
  455. unset($search['curr_or_hist']);
  456. $string = array2where($search);
  457. } // if
  458.  
  459. return $string;
  460.  
  461. } // currentOrHistoric
  462.  
  463. // ****************************************************************************
  464. function customButton ($fieldarray, $button, $postarray, $row=null)
  465. // user pressed a custom button.
  466. {
  467. if ($this->errors) {
  468. return $this->getFieldArray(); // object has unresolved errors, so do nothing
  469. } // if
  470.  
  471. // filter out any data which does not belong in this table
  472. $postarray = getPostArray($postarray, $this->fieldspec);
  473.  
  474. if (!is_long(key($fieldarray))) {
  475. $fieldarray = array($fieldarray); // ensure it is indexed by row
  476. } // if
  477.  
  478. if ($this->rows_per_page == 1) {
  479. // this is the only row
  480. $row = 0;
  481. $fieldarray = array_update_associative($fieldarray[$row], $postarray, $this->fieldspec);
  482. $output = $this->_cm_customButton($fieldarray, $button);
  483. } else {
  484. // this is one of many rows
  485. if (empty($row)) $row=1; // default
  486. $row = $row-1; // screen rows start at #1 while database rows start at zero
  487. if (array_key_exists($row, $fieldarray)) {
  488. $fieldarray = array_update_indexed($fieldarray, $postarray, $this->fieldspec);
  489. $output = $this->_cm_customButton($fieldarray[$row], $button);
  490. } // if
  491. } // if
  492.  
  493. reset($output);
  494. if (is_long(key($output))) {
  495. // output is indexed, so replace entire array
  496. $this->fieldarray = $output;
  497. } else {
  498. // output is associative, so replace single row
  499. if ($this->rows_per_page == 1) {
  500. $this->fieldarray = array($row => $output);
  501. } else {
  502. $this->fieldarray[$row] = $output;
  503. } // if
  504. } // if
  505.  
  506. // see if any additional data is required or needs to be changed
  507. $this->fieldarray = $this->getExtraData($this->fieldarray);
  508.  
  509. if (count($this->fieldarray) == 1) {
  510. if (empty($this->fieldarray[key($this->fieldarray)])) {
  511. $this->fieldarray = array(); // contains a single empty element, so clear it out
  512. } // if
  513. } // if
  514.  
  515. return $this->getFieldArray();
  516.  
  517. } // customButton
  518.  
  519. // ****************************************************************************
  520. function deleteMultiple ($fieldarray)
  521. // delete multiple records using data in $fieldarray.
  522. {
  523. $errors = array();
  524. $this->no_display_count = false;
  525. $count = 0;
  526.  
  527. if (isset($GLOBALS['batch']) AND is_True($GLOBALS['batch'])) {
  528. // check to see if this task is a pending workitem
  529. $errors = $this->checkWorkflow($fieldarray[0]);
  530. if ($errors) {
  531. return $fieldarray;
  532. } // if
  533. } // if
  534.  
  535. if (empty($this->errors)) {
  536. // perform any additional custom pre-processing
  537. if (is_object($this->custom_processing_object)) {
  538. if (method_exists($this->custom_processing_object, '_cm_pre_deleteMultiple')) {
  539. $fieldarray = $this->custom_processing_object->_cm_pre_deleteMultiple($fieldarray);
  540. } // if
  541. } // if
  542. if ($this->custom_replaces_standard) {
  543. $this->custom_replaces_standard = false;
  544. } else {
  545. $fieldarray = $this->_cm_pre_deleteMultiple($fieldarray);
  546. } // if
  547. } // if
  548.  
  549. if (!$this->errors) {
  550. // delete each row one by one
  551. foreach ($fieldarray as $rownum => $row) {
  552. $row = $this->deleteRecord($row);
  553. if (!empty($this->errors)) {
  554. // accumulate all errors
  555. //$errors = array_merge($errors, $this->errors);
  556. $errors[$rownum] = $this->errors;
  557. } else {
  558. $count = $count + $this->numrows;
  559. } // if
  560. } // foreach
  561.  
  562. if (empty($this->errors)) {
  563. // perform any additional custom post-processing
  564. if (is_object($this->custom_processing_object)) {
  565. if (method_exists($this->custom_processing_object, '_cm_post_deleteMultiple')) {
  566. $fieldarray = $this->custom_processing_object->_cm_post_deleteMultiple($fieldarray);
  567. } // if
  568. } // if
  569. if ($this->custom_replaces_standard) {
  570. $this->custom_replaces_standard = false;
  571. } else {
  572. $fieldarray = $this->_cm_post_deleteMultiple($fieldarray);
  573. } // if
  574. } // if
  575.  
  576. } // if
  577.  
  578. if (is_True($this->no_display_count)) {
  579. // do not display record count
  580. } else {
  581. // '$count records were deleted from $tablename'
  582. $this->messages[] = $this->getLanguageText('sys0004', $count, strtoupper($this->tablename));
  583. } // if
  584.  
  585. $this->errors = $errors;
  586. $this->numrows = $count;
  587.  
  588. return $fieldarray;
  589.  
  590. } // deleteMultiple
  591.  
  592. // ****************************************************************************
  593. function deleteRecord ($fieldarray, $parent_table=null)
  594. // delete the record specified in $fieldarray.
  595. // ($parent_table is only used in a cascade delete)
  596. {
  597. $this->errors = array(); // initialise
  598.  
  599. if (empty($fieldarray)) {
  600. return $fieldarray; // nothing to delete
  601. } // if
  602.  
  603. if (is_string($fieldarray)) {
  604. // convert from string to array
  605. $fieldarray = where2array($fieldarray);
  606. } // if
  607.  
  608. // shift all field names to lower case
  609. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  610.  
  611. if (!$this->skip_getdata) {
  612. // check that full primary key (or candidate key) has been supplied
  613. list($where, $errors) = isPkeyComplete($fieldarray, $this->getPkeyNames(), $this->unique_keys);
  614. if (!empty($errors)) {
  615. $this->errors = $errors;
  616. } // if
  617.  
  618. if (empty($this->errors)) {
  619. // obtain copy of original record from database
  620. $where = array2where($fieldarray, $this->getPkeyNames(), $this);
  621. $originaldata = $this->_dml_ReadBeforeUpdate($where);
  622. if ($this->numrows == 0) {
  623. return $fieldarray; // there is nothing to delete
  624. } elseif ($this->numrows == 1) {
  625. // use only 1st row in $originaldata
  626. $originaldata = $originaldata[0];
  627. // insert non-key values for inclusion in audit log
  628. $fieldarray = array_merge($fieldarray, $originaldata);
  629. if (!empty($this->unique_keys)) {
  630. // rebuild $where from pkey in case candidate key was used
  631. $where = array2where($fieldarray, $this->getPkeyNames(), $this);
  632. } // if
  633. } else {
  634. // more than 1 record found - key is not unique
  635. $this->errors[] = $this->getLanguageText('sys0113');
  636. } // if
  637. } // if
  638. } // if
  639.  
  640. // check that this record can be deleted
  641. $numrows = $this->numrows;
  642. if (empty($this->errors)) {
  643. $fieldarray = $this->validateDelete($fieldarray, $parent_table);
  644. } // if
  645.  
  646. if (empty($this->errors)) {
  647. // perform any custom pre-delete processing
  648. if (is_object($this->custom_processing_object)) {
  649. if (method_exists($this->custom_processing_object, '_cm_pre_deleteRecord')) {
  650. $fieldarray = $this->custom_processing_object->_cm_pre_deleteRecord($fieldarray);
  651. } // if
  652. } // if
  653. if ($this->custom_replaces_standard) {
  654. $this->custom_replaces_standard = false;
  655. } else {
  656. $fieldarray = $this->_cm_pre_deleteRecord($fieldarray);
  657. } // if
  658. } // if
  659.  
  660. if (empty($this->errors)) {
  661. // delete any tables related to the specified record
  662. $this->deleteRelations($fieldarray);
  663. } // if
  664.  
  665. $this->numrows = $numrows;
  666. if (empty($this->errors) AND $this->numrows > 0) {
  667. // delete the specified record
  668. $this->_dml_deleteRecord($fieldarray);
  669. } // if
  670.  
  671. if (empty($this->errors)) {
  672. // perform any custom post-delete processing
  673. if (is_object($this->custom_processing_object)) {
  674. if (method_exists($this->custom_processing_object, '_cm_post_deleteRecord')) {
  675. $fieldarray = $this->custom_processing_object->_cm_post_deleteRecord($fieldarray);
  676. } // if
  677. } // if
  678. if ($this->custom_replaces_standard) {
  679. $this->custom_replaces_standard = false;
  680. } else {
  681. $fieldarray = $this->_cm_post_deleteRecord($fieldarray);
  682. } // if
  683. } // if
  684.  
  685. return $fieldarray;
  686.  
  687. } // deleteRecord
  688.  
  689. // ****************************************************************************
  690. function deleteRelations ($fieldarray)
  691. // delete any child records whch are linked to the current record.
  692. {
  693. $this->errors = array();
  694.  
  695. if (empty($this->child_relations)) {
  696. return;
  697. } // if
  698.  
  699. // process contents of $child_relations array
  700. foreach ($this->child_relations as $reldata) {
  701. $tblchild = $reldata['child'];
  702. switch (strtoupper($reldata['type'])) {
  703. case 'NULLIFY':
  704. case 'NUL':
  705. // set foreign key(s) to null
  706. $where = NULL;
  707. $update_array = array();
  708. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  709. //if (strlen($fldchild) < 1) {
  710. // // 'Name of child field missing in relationship with $tblchild'
  711. // $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  712. // break;
  713. //} // if
  714. if (!empty($fldchild)) {
  715. if (empty($where)) {
  716. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  717. } else {
  718. $where .= " AND $fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  719. } // if
  720. } // if
  721. $update_array[$fldchild] = NULL;
  722. } // foreach
  723.  
  724. if (empty($where)) {
  725. // 'Name of child field missing in relationship with $tblchild'
  726. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  727. break;
  728. } else {
  729. // instantiate an object for this table
  730. if (array_key_exists('subsys_dir', $reldata)) {
  731. // get path to current subsystem directory
  732. $dir = dirname($this->dirname);
  733. // switch to other subsystem directory
  734. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  735. } else {
  736. $dir = NULL;
  737. } // if
  738. if (!class_exists($tblchild)) {
  739. require_once $dir ."classes/$tblchild.class.inc";
  740. } // if
  741. $childobject = new $tblchild;
  742. if (!empty($this->dbname_old) AND $this->dbname_old == $childobject->dbname) {
  743. // name of parent database has been switched, so switch the child name as well
  744. $childobject->dbname_old = $childobject->dbname;
  745. $childobject->dbname = $this->dbname;
  746. } // if
  747. $childobject->audit_logging = $this->audit_logging;
  748. $childobject->sql_no_foreign_db = $this->sql_no_foreign_db;
  749. // now use this object to delete child records
  750. if (!$childobject->cascadeNullify($update_array, $where)) {
  751. $this->errors = array_merge($childobject->getErrors(), $this->errors);
  752. } // if
  753. unset($childobject);
  754. } // if
  755. break;
  756.  
  757. case 'DELETE';
  758. case 'DEL':
  759. case 'CASCADE':
  760. case 'CAS':
  761. // delete all related rows
  762. $where = NULL;
  763. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  764. //if (strlen($fldchild) < 1) {
  765. // // 'Name of child field missing in relationship with $tblchild'
  766. // $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  767. // break;
  768. //} // if
  769. if (!empty($fldchild)) {
  770. if (empty($where)) {
  771. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  772. } else {
  773. $where .= " AND $fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  774. } // if
  775. } // if
  776. } // foreach
  777.  
  778. if (empty($where)) {
  779. // 'Name of child field missing in relationship with $tblchild'
  780. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  781. break;
  782. } else {
  783. // instantiate an object for this table
  784. if (array_key_exists('subsys_dir', $reldata)) {
  785. // get path to current subsystem directory
  786. $dir = dirname($this->dirname);
  787. // switch to other subsystem directory
  788. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  789. } else {
  790. $dir = NULL;
  791. } // if
  792. if (!class_exists($tblchild)) {
  793. require_once $dir ."classes/$tblchild.class.inc";
  794. } // if
  795. $childobject = new $tblchild;
  796. if (!empty($this->dbname_old) AND $this->dbname_old == $childobject->dbname) {
  797. // name of parent database has been switched, so switch the child name as well
  798. $childobject->dbname_old = $childobject->dbname;
  799. $childobject->dbname = $this->dbname;
  800. } // if
  801. $childobject->audit_logging = $this->audit_logging;
  802. $childobject->sql_no_foreign_db = $this->sql_no_foreign_db;
  803. // check for 'order by' clause
  804. if (isset($reldata['orderby'])) {
  805. $childobject->default_orderby = $reldata['orderby'];
  806. } // if
  807. // now use this object to delete child records
  808. if (!$msg = $childobject->cascadeDelete($where, $this->tablename)) {
  809. $this->errors = array_merge($childobject->getErrors(), $this->errors);
  810. } else {
  811. if (!empty($childobject->delete_count) AND is_array($childobject->delete_count)) {
  812. foreach ($childobject->delete_count as $table => $count) {
  813. if (isset($this->delete_count[$table])) {
  814. $this->delete_count[$table] += $count;
  815. } else {
  816. $this->delete_count[$table] = $count;
  817. } // if
  818. } // foreach
  819. } // if
  820. } // if
  821. unset($childobject);
  822. } // if
  823. break;
  824.  
  825. case 'RESTRICTED':
  826. case 'RES':
  827. case 'IGN':
  828. // do nothing
  829. break;
  830.  
  831. case 'DEX':
  832. case 'NUX':
  833. // do nothing as it will be handled by a foreign key constraint
  834. break;
  835.  
  836. default:
  837. // 'Unknown relation type: $type'
  838. $this->errors[] = $this->getLanguageText('sys0010', $reldata['type']);
  839. } // switch
  840. } // foreach
  841.  
  842. return;
  843.  
  844. } // deleteRelations
  845.  
  846. // ****************************************************************************
  847. function deleteScrollItem ($index)
  848. // delete the specified item from $scrollarray, then return the details of the
  849. // next available item.
  850. {
  851. if ($index > count($this->scrollarray)) {
  852. // index is too high, so do not delete
  853. $index = count($this->scrollarray);
  854. } elseif ($index < 1) {
  855. // index is too low, so do not delete
  856. $index = 1;
  857. } else {
  858. // index is valid, so remove indicated item
  859. unset($this->scrollarray[$index]);
  860. // resequence the array after removing this item
  861. $array[0] = 'dummy';
  862. foreach ($this->scrollarray as $entry) {
  863. $array[] = $entry;
  864. } // foreach
  865. unset($array[0]);
  866. $this->scrollarray = $array;
  867. if ($index > count($this->scrollarray)) {
  868. // index is too high, so do not delete
  869. $index = count($this->scrollarray);
  870. } // if
  871. } // if
  872.  
  873. // replace $where with details from the next available entry in scrollarray
  874. if (is_array($this->scrollarray[$index])) {
  875. $where = array2where($this->scrollarray[$index]);
  876. } else {
  877. $where = $this->scrollarray[$index];
  878. } // if
  879.  
  880. // set values to be used by scrolling logic
  881. $this->scrollindex = $index;
  882. $this->pageno = $index;
  883. $this->lastpage = count($this->scrollarray);
  884.  
  885. return $where;
  886.  
  887. } // deletetScrollItem
  888.  
  889. // ****************************************************************************
  890. function deleteSelection ($selection)
  891. // delete/update a selection of records in one operation.
  892. {
  893. $this->errors = array();
  894.  
  895. if (empty($selection)) {
  896. // 'Nothing has been selected yet.'
  897. $this->errors[] = scriptPrevious($this->getLanguageText('sys0081'));
  898. return;
  899. } // if
  900.  
  901. // call custom method for specific processing
  902. $msg = $this->_cm_deleteSelection($selection);
  903.  
  904. return $msg;
  905.  
  906. } // deleteSelection
  907.  
  908. // ****************************************************************************
  909. function eraseRecord ($fieldarray)
  910. // delete the record, and ALL its children, specified in $fieldarray.
  911. {
  912. $this->errors = array();
  913.  
  914. if (is_string($fieldarray)) {
  915. // convert from string to array
  916. $fieldarray = where2array($fieldarray, false, false);
  917. } // if
  918.  
  919. // strip any operators from the value portion of the array
  920. $fieldarray = stripOperators($fieldarray);
  921.  
  922. // check that full primary key has been supplied
  923. list($where, $errors) = isPkeyComplete($fieldarray, $this->getPkeyNames());
  924. if (!empty($errors)) {
  925. $this->errors = $errors;
  926. } // if
  927.  
  928. if (empty($this->errors)) {
  929. // get field specifications for this database table
  930. $fieldspec = $this->fieldspec;
  931.  
  932. // remove any non-database fields from input array
  933. foreach ($fieldarray as $field => $fieldvalue) {
  934. // check that $field exists in $fieldspec array
  935. if (!array_key_exists($field, $fieldspec)) {
  936. // it does not (like the SUBMIT button, for example), so remove it
  937. unset ($fieldarray[$field]);
  938. } // if
  939. } // foreach
  940. } // if
  941.  
  942. // perform any custom pre-erase processing
  943. if (empty($this->errors)) {
  944. $fieldarray = $this->_cm_pre_eraseRecord($fieldarray);
  945. } // if
  946.  
  947. // delete any tables related to the specified record
  948. if (empty($this->errors)) {
  949. $this->eraseRelations($fieldarray);
  950. } // if
  951.  
  952. // delete the specified record
  953. if (empty($this->errors)) {
  954. $this->_dml_deleteRecord($fieldarray);
  955. } // if
  956.  
  957. // perform any custom post-delete processing
  958. if (empty($this->errors)) {
  959. $fieldarray = $this->_cm_post_eraseRecord($fieldarray);
  960. } // if
  961.  
  962. return $fieldarray;
  963.  
  964. } // eraseRecord
  965.  
  966. // ****************************************************************************
  967. function eraseRelations ($fieldarray)
  968. // erase any child records whch are linked to the current record.
  969. // this is done by treating every relationship type as CASCADE DELETE
  970. {
  971. $this->errors = array();
  972.  
  973. if (empty($this->child_relations) OR empty($fieldarray)) {
  974. return;
  975. } // if
  976.  
  977. // process contents of $child_relations array
  978. foreach ($this->child_relations as $reldata) {
  979. $tblchild = $reldata['child'];
  980. if (array_key_exists('subsys_dir', $reldata)) {
  981. // do not erase from a database in another subsystem
  982. } else {
  983. switch (strtoupper($reldata['type'])) {
  984. case 'DEX':
  985. case 'NUX':
  986. // do nothing as it will be handled by a foreign key constraint
  987. break;
  988.  
  989. case 'IGN':
  990. // ignore this relationship
  991. break;
  992.  
  993. case 'NULLIFY':
  994. case 'NUL':
  995. // set foreign key(s) to null
  996. $where = NULL;
  997. $update_array = array();
  998. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  999. if (strlen($fldchild) < 1) {
  1000. // 'Name of child field missing in relationship with $tblchild'
  1001. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  1002. break;
  1003. } // if
  1004. if (empty($where)) {
  1005. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  1006. } else {
  1007. $where .= " AND $fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  1008. } // if
  1009. $update_array[$fldchild] = NULL;
  1010. } // foreach
  1011.  
  1012. // instantiate an object for this table
  1013. if (array_key_exists('subsys_dir', $reldata)) {
  1014. // get path to current subsystem directory
  1015. $dir = dirname($this->dirname);
  1016. // switch to other subsystem directory
  1017. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  1018. } else {
  1019. $dir = NULL;
  1020. } // if
  1021. if (!class_exists($tblchild)) {
  1022. require_once $dir ."classes/$tblchild.class.inc";
  1023. } // if
  1024. $childobject = new $tblchild;
  1025. // now use this object to delete child records
  1026. if (!$childobject->cascadeNullify($update_array, $where)) {
  1027. $this->errors = array_merge($childobject->getErrors(), $this->errors);
  1028. } // if
  1029. unset($childobject);
  1030. break;
  1031.  
  1032. case 'DELETE':
  1033. case 'DEL':
  1034. case 'CASCADE':
  1035. case 'CAS':
  1036. case 'RESTRICTED':
  1037. case 'RES':
  1038. // erase all related rows
  1039. $where = NULL;
  1040. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  1041. if (strlen($fldchild) < 1) {
  1042. // 'Name of child field missing in relationship with $tblchild'
  1043. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  1044. break;
  1045. } // if
  1046. if (empty($where)) {
  1047. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  1048. } else {
  1049. $where .= " AND $fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  1050. } // if
  1051. } // foreach
  1052.  
  1053. // instantiate an object for this table
  1054. if (array_key_exists('subsys_dir', $reldata)) {
  1055. // get path to current subsystem directory
  1056. $dir = dirname($this->dirname);
  1057. // switch to other subsystem directory
  1058. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  1059. } else {
  1060. $dir = NULL;
  1061. } // if
  1062. if (!class_exists($tblchild)) {
  1063. require_once $dir ."classes/$tblchild.class.inc";
  1064. } // if
  1065. $childobject = new $tblchild;
  1066. // check for 'order by' clause
  1067. if (isset($reldata['orderby'])) {
  1068. $childobject->default_orderby = $reldata['orderby'];
  1069. } // if
  1070. // pass down the current audit logging switch
  1071. $childobject->audit_logging = $this->audit_logging;
  1072. $childdata = $childobject->getData_raw($where);
  1073. foreach ($childdata as $childrow) {
  1074. // now use this object to delete each child record one at a time
  1075. $childobject->eraseRecord($childrow);
  1076. if ($childobject->getErrors()) {
  1077. $this->errors = array_merge($childobject->getErrors(), $this->errors);
  1078. } // if
  1079. } // foreach
  1080. unset($childobject);
  1081. break;
  1082.  
  1083. default:
  1084. // 'Unknown relation type: $type'
  1085. $this->errors[] = $this->getLanguageText('sys0010', $reldata['type']);
  1086. } // switch
  1087. } // if
  1088.  
  1089. } // foreach
  1090.  
  1091. if (count($this->errors) > 0) {
  1092. return false;
  1093. } // if
  1094.  
  1095. return true;
  1096.  
  1097. } // eraseRelations
  1098.  
  1099. // ****************************************************************************
  1100. function executeQuery ($query)
  1101. // execute one or more pre-defined queries.
  1102. // $query may be a string (single query) or an array (multiple queries).
  1103. {
  1104. $DML =& $this->_getDBMSengine($this->dbname);
  1105.  
  1106. $DML->setRowLocks($this->row_locks);
  1107.  
  1108. if (is_array($query)) {
  1109. $temp = $query;
  1110. $temp = array_map("trim", $temp);
  1111. } else {
  1112. $query = trim($query);
  1113. // split string into an array of individual queries
  1114. $pattern = "/
  1115. ( # start group
  1116. [^';]+ # match as much as possible which doesn't include ' or ;
  1117. | # or
  1118. '[^']*' # a single quoted string
  1119. )* # end group, repeated
  1120. /six";
  1121. preg_match_all($pattern, $query, $regs);
  1122. $temp = $regs[0];
  1123. } // if
  1124.  
  1125. $query_array = array();
  1126. foreach ($temp as $entry) {
  1127. // ensure each entry ends with ';'
  1128. $entry = trim($entry);
  1129. if (!empty($entry)) {
  1130. if (substr($entry, -1, 1) != ';') {
  1131. $entry .= ';';
  1132. } // if
  1133. $query_array[] = $entry;
  1134. } // if
  1135. } // foreach
  1136.  
  1137. $result = $DML->multiQuery($this->dbname_server, $this->tablename, $query_array);
  1138.  
  1139. return $result;
  1140.  
  1141. } // executeQuery
  1142.  
  1143. // ****************************************************************************
  1144. function fetchRow ($resource)
  1145. // Fetch the next row from a resource created in the getData_serial() method.
  1146. {
  1147. $this->errors = array();
  1148.  
  1149. if ($this->skip_getdata) {
  1150. if (empty($this->fieldarray)) {
  1151. $row = false;
  1152. } else {
  1153. $row = array_shift($this->fieldarray);
  1154. $row = $this->_cm_post_fetchRow($row);
  1155. } // if
  1156. return $row;
  1157. } // if
  1158.  
  1159. $DML =& $this->_getDBMSengine($this->dbname);
  1160.  
  1161. $row = $DML->fetchRow($this->dbname_server, $resource);
  1162.  
  1163. if ($row) {
  1164. // perform any custom post-retrieve processing
  1165. if (is_object($this->custom_processing_object)) {
  1166. if (method_exists($this->custom_processing_object, '_cm_post_fetchRow')) {
  1167. $row = $this->custom_processing_object->_cm_post_fetchRow($row);
  1168. } // if
  1169. } // if
  1170. if ($this->custom_replaces_standard) {
  1171. $this->custom_replaces_standard = false;
  1172. } else {
  1173. if ($row) {
  1174. $row = $this->_cm_post_fetchRow($row);
  1175. } // if
  1176. } // if
  1177. if (empty($row)) {
  1178. // this row has been cancelled, so read another one
  1179. $row = $this->fetchRow($resource);
  1180. } // if
  1181. } // if
  1182.  
  1183. return $row;
  1184.  
  1185. } // fetchRow
  1186.  
  1187. // ****************************************************************************
  1188. function fetchRowChild ($row)
  1189. // See if there is are any child records associated with the current row.
  1190. // (for example, a node in a tree structure may have child nodes)
  1191. // Any child rows are returned one at a time.
  1192. // Note that each child row may also have its own children.
  1193. {
  1194. $this->errors = array();
  1195.  
  1196. if (empty($row)) return FALSE;
  1197.  
  1198. $keys = array();
  1199. // get names of SENIOR and JUNIOR keys
  1200. if (is_object($this->custom_processing_object)) {
  1201. if (method_exists($this->custom_processing_object, '_cm_getNodeKeys')) {
  1202. $keys = $this->custom_processing_object->_cm_getNodeKeys($keys);
  1203. } // if
  1204. } // if
  1205. if ($this->custom_replaces_standard) {
  1206. $this->custom_replaces_standard = false;
  1207. } else {
  1208. if ($row) {
  1209. $keys = $this->_cm_getNodeKeys($keys);
  1210. } // if
  1211. } // if
  1212.  
  1213. $snr_id = $keys['snr_id'];
  1214. $jnr_id = $keys['jnr_id'];
  1215.  
  1216. $resources =& $this->resource_array;
  1217. if (!is_array($resources)) {
  1218. $resources = array();
  1219. } // if
  1220.  
  1221. if (empty($resources)) {
  1222. // create a new resource
  1223. $where = "$snr_id='{$row[$jnr_id]}'";
  1224. $resource = $this->getData_serial($where);
  1225. } else {
  1226. $resource = array_pop($resources);
  1227. } // if
  1228. $resources[] =& $resource;
  1229.  
  1230. $row = $this->fetchRow($resource); // read a single row
  1231.  
  1232. if (empty($row)) {
  1233. $null = array_pop($resources); // this resource has been exhausted
  1234. while (!empty($resources)) {
  1235. $resource = array_pop($resources);
  1236. $row = $this->fetchRow($resource); // read a single row
  1237. if (!empty($row)) {
  1238. $resources[] =& $resource; // resource not exhausted yet, so put it back
  1239. // create a new resource for possible children
  1240. $where = "$snr_id='{$row[$jnr_id]}'";
  1241. $child_resource = $this->getData_serial($where);
  1242. $resources[] = $child_resource;
  1243. break;
  1244. } // if
  1245. } // while
  1246. } else {
  1247. $where = "$snr_id='{$row[$jnr_id]}'";
  1248. $child_resource = $this->getData_serial($where);
  1249. $resources[] = $child_resource;
  1250. } // if
  1251.  
  1252. if (!empty($row) AND !empty($row['level'])) {
  1253. $row['level'] = count($resources);
  1254. } // if
  1255.  
  1256. return $row;
  1257.  
  1258. } // fetchRowChild
  1259.  
  1260. // ****************************************************************************
  1261. function filePickerSelect ($selection)
  1262. // Deal with selection from a filepicker screen.
  1263. {
  1264. $selection = $this->_cm_filePickerSelect($selection);
  1265.  
  1266. return $selection;
  1267.  
  1268. } // filePickerSelect
  1269.  
  1270. // ****************************************************************************
  1271. function fileUpload ($input_name, $temp_file)
  1272. // Specify file name to be used for the upload.
  1273. {
  1274. $this->errors = array();
  1275.  
  1276. $fieldarray = where2array($this->where);
  1277.  
  1278. $output_name = $this->_cm_fileUpload($input_name, $temp_file, $fieldarray);
  1279.  
  1280. return $this->upload_subdir .'/' .$output_name;
  1281.  
  1282. } // fileUpload
  1283.  
  1284. // ****************************************************************************
  1285. function formatData ($fieldarray, &$css_array)
  1286. // format values retrieved from the database before they are shown to the user.
  1287. // (such as changing dates from 'CCYY-MM-DD' to 'dd Mmm CCYY'
  1288. // NOTE: $css_array is passed BY REFERENCE as it may be altered.
  1289. {
  1290. if (empty($fieldarray)) return $fieldarray;
  1291.  
  1292. $dateobj =& RDCsingleton::getInstance('date_class');
  1293.  
  1294. if (!empty($fieldarray['party_timezone'])) {
  1295. if (!isset($_SESSION['display_timezone_party']) OR $_SESSION['display_timezone_party'] === false) {
  1296. $this->messages[] = getLanguageText('sys0238'); // "DateTimes shown in User's timezone"
  1297. } else {
  1298. $this->messages[] = getLanguageText('sys0239'); // "DateTimes shown in Party's timezone"
  1299. } // if
  1300. } // if
  1301.  
  1302. foreach ($fieldarray as $fieldname => $fieldvalue) {
  1303. // only deal with fields defined in $fieldspec
  1304. if (isset($this->fieldspec[$fieldname])) {
  1305. // get specifications for current field
  1306. $fieldspec = $this->fieldspec[$fieldname];
  1307. if (!isset($fieldspec['type'])) {
  1308. $fieldspec['type'] = 'string'; // set default type
  1309. } // if
  1310.  
  1311. if ($GLOBALS['mode'] == 'search') {
  1312. if (preg_match('/^(is not null|is null)$/i', trim($fieldvalue), $regs )) {
  1313. $fieldvalue = strtoupper($regs[0]);
  1314. $fieldspec['type'] = 'string';
  1315. $operator = '';
  1316. } elseif (preg_match("/^(<>|<=|<|>=|>|!=|=)/", $fieldvalue, $regs )) {
  1317. $operator = $regs[0];
  1318. // strip operator from front of string
  1319. $fieldvalue = substr($fieldvalue, strlen($operator));
  1320. if (substr($fieldvalue, 0, 1) == "'") {
  1321. // remove leading quote
  1322. $fieldvalue = substr($fieldvalue, 1);
  1323. } // if
  1324. if (substr($fieldvalue, -1) == "'") {
  1325. // remove trailing quote
  1326. $fieldvalue = substr($fieldvalue, 0, -1);
  1327. } // if
  1328. } else {
  1329. $operator = '=';
  1330. } // if
  1331. } else {
  1332. $operator = '=';
  1333. } // if
  1334.  
  1335. switch (strtolower($fieldspec['type'])) {
  1336. case 'string':
  1337. if (isset($fieldspec['control']) AND $fieldspec['control'] == 'multidrop') {
  1338. list($operator, $value, $delimiter) = extractOperatorValue($fieldvalue);
  1339. if (trim($operator) == 'IN') {
  1340. // turn this string into an array
  1341. $value = trim($value, '()');
  1342. $array = explode(',', $value);
  1343. foreach ($array as $key => $entry) {
  1344. if (substr($entry, 0, 1) == "'") {
  1345. // remove leading quote
  1346. $entry = substr($entry, 1);
  1347. } // if
  1348. if (substr($entry, -1, 1) == "'") {
  1349. // remove leading quote
  1350. $entry = substr($entry, 0, strlen($entry)-1);
  1351. } // if
  1352. $array[$key] = $entry;
  1353. } // foreach
  1354. $fieldvalue = $array;
  1355. $operator = '=';
  1356. } // if
  1357. } // if
  1358. break;
  1359. case 'set':
  1360. case 'array':
  1361. if (!is_array($fieldvalue)) {
  1362. // convert string into an array
  1363. if (strlen($fieldvalue) > 0) {
  1364. // note: postgresql uses '{}' to enclose the array
  1365. $fieldvalue = explode(',', trim($fieldvalue, '{}'));
  1366. } else {
  1367. $fieldvalue = array();
  1368. } // if
  1369. } // if
  1370. break;
  1371. case 'boolean':
  1372. if (is_bool($fieldvalue) or strlen($fieldvalue) > 0) {
  1373. $boolean = $this->getLanguageArray('boolean');
  1374. // set boolean fields to either TRUE or FALSE
  1375. if (is_True($fieldvalue)) {
  1376. if (isset($fieldspec['true'])) {
  1377. $fieldvalue = $fieldspec['true'];
  1378. } elseif (isset($boolean['true'])) {
  1379. $fieldvalue = $boolean['true'];
  1380. } // if
  1381. } else {
  1382. if (isset($fieldspec['false'])) {
  1383. $fieldvalue = $fieldspec['false'];
  1384. } elseif (isset($boolean['false'])) {
  1385. $fieldvalue = $boolean['false'];
  1386. } // if
  1387. } // if
  1388. } else {
  1389. // value has not defined yet
  1390. if ($GLOBALS['mode'] != 'search') {
  1391. if (isset($fieldspec['default'])) {
  1392. // default value has been defined, so use it
  1393. $fieldvalue = $fieldspec['default'];
  1394. } // if
  1395. } else {
  1396. // leave as undefined
  1397. } // if
  1398. } // if
  1399. break;
  1400. case 'date':
  1401. if (isset($fieldspec['infinityisnull']) and substr($fieldvalue, 0, 10) == '9999-12-31') {
  1402. // this date is shown to the user as empty
  1403. $fieldvalue = '';
  1404. } else {
  1405. if ($GLOBALS['mode'] == 'search' and strpos($fieldvalue, '%')) {
  1406. // this is already in LIKE format for a search screen. so leave it alone
  1407. // (apart from removing trailing '%' which will be replaced later)
  1408. $fieldvalue = rtrim($fieldvalue, '%');
  1409. } elseif (!empty($fieldvalue)) {
  1410. if ($this->no_convert_timezone === FALSE AND isset($_SESSION['timezone_server'])) {
  1411. $date = $dateobj->getInternalDate($fieldvalue);
  1412. if ($date === false) {
  1413. $this->errors[$fieldname] = $dateobj->errors;
  1414. return $fieldarray;
  1415. } // if
  1416. if (isset($_SESSION['display_timezone_party']) AND is_True($_SESSION['display_timezone_party'])) {
  1417. if (!empty($fieldarray['party_timezone'])) {
  1418. $timezone_client = $fieldarray['party_timezone']; // timezone of data's party
  1419. } else {
  1420. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  1421. } // if
  1422. } else {
  1423. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  1424. } // if
  1425. $fieldvalue = convertTZdate($date, '12:00:00', $_SESSION['timezone_server'], $timezone_client);
  1426. } // if
  1427. // convert date from internal to external format
  1428. if ($date = $dateobj->getExternalDate($fieldvalue, $_SESSION['date_format_output'])) {
  1429. $fieldvalue = $date;
  1430. } else {
  1431. // date cannot be converted, so leave as is
  1432. } // if
  1433. } // if
  1434. } // if
  1435. break;
  1436. case 'datetime':
  1437. case 'timestamp':
  1438. if (isset($fieldspec['infinityisnull']) and substr($fieldvalue, 0, 10) == '9999-12-31') {
  1439. // this date is shown to the user as empty
  1440. $fieldvalue = '';
  1441. } else {
  1442. if (!empty($fieldvalue)) {
  1443. if ($this->no_convert_timezone === FALSE AND isset($_SESSION['timezone_server'])) {
  1444. $datetime = $dateobj->getInternalDateTime($fieldvalue, $fieldspec);
  1445. if ($datetime === false) {
  1446. $this->errors[$fieldname] = $dateobj->errors;
  1447. return $fieldarray;
  1448. } // if
  1449. if (isset($_SESSION['display_timezone_party']) AND is_True($_SESSION['display_timezone_party'])) {
  1450. if (!empty($fieldarray['party_timezone'])) {
  1451. $timezone_client = $fieldarray['party_timezone']; // timezone of data's party
  1452. } else {
  1453. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  1454. } // if
  1455. } else {
  1456. $timezone_client = $_SESSION['timezone_client']; // timezone of logon user
  1457. } // if
  1458. $fieldvalue = convertTZ($datetime, $_SESSION['timezone_server'], $timezone_client);
  1459. } // if
  1460. // look for a time portion (ends with '99:99' or '99:99:99')
  1461. if (preg_match('/([0-9]{2}:[0-9]{2}){1}(:[0-9]{2})?$/', $fieldvalue, $regs)) {
  1462. $time = $regs[0];
  1463. $date = substr($fieldvalue, 0, -strlen($time));
  1464. } else {
  1465. $date = $fieldvalue;
  1466. $time = null;
  1467. } // if
  1468. // convert date from internal to external format
  1469. if ($date = $dateobj->getExternalDate($date, $_SESSION['date_format_output'])) {
  1470. $fieldvalue = trim($date) .' ' .substr(trim($time), 0, 8);
  1471. } else {
  1472. // date cannot be converted, so leave as is
  1473. } // if
  1474. } // if
  1475. } // if
  1476. break;
  1477. case 'time':
  1478. if (isset($fieldspec['size']) and $fieldspec['size'] == 5) {
  1479. // exclude the seconds portion of the time
  1480. $fieldvalue = substr($fieldarray[$fieldname], 0, 5);
  1481. } // if
  1482. break;
  1483. case 'integer':
  1484. if ($fieldvalue == 0 AND isset($fieldspec['blank_when_zero'])) {
  1485. if ($operator == '=') {
  1486. $fieldvalue = ''; // value is zero, so display blank
  1487. } // if
  1488. } // if
  1489. break;
  1490. case 'double':
  1491. case 'float':
  1492. case 'real':
  1493. if (!empty($fieldvalue)) {
  1494. if (is_numeric($fieldvalue)) {
  1495. $float = sprintf('%F', $fieldvalue);
  1496. $float = rtrim($float,'0'); // remove trailing zeroes after decimal point
  1497. $float = rtrim($float,'.'); // remove decimal point if it is the last character
  1498. if (strlen($float) > 18) {
  1499. $fieldvalue = (double)$fieldvalue; // number is too long, so display in scientific notation
  1500. } else {
  1501. $fieldvalue = $float; // display as decimal number
  1502. } // if
  1503. } // if
  1504. } // if
  1505. break;
  1506. case 'decimal':
  1507. case 'numeric':
  1508. if (isset($fieldspec['scale'])) {
  1509. $decimal_places = $fieldspec['scale'];
  1510. } else {
  1511. $decimal_places = 0;
  1512. } // if
  1513. if ($fieldvalue == 0 AND isset($fieldspec['blank_when_zero'])) {
  1514. if ($operator == '=') {
  1515. $fieldvalue = ''; // value is zero, so display blank
  1516. } // if
  1517. } else {
  1518. // remove any thousands separators
  1519. // this screws up -> $fieldvalue = number_unformat($fieldvalue);
  1520. // format number according to current locale settings
  1521. $strip_trailing_zero =& $fieldspec['strip_trailing_zero'];
  1522. $fieldvalue = formatNumber($fieldvalue, $decimal_places, $strip_trailing_zero);
  1523. } // if
  1524. break;
  1525. default:
  1526. ;
  1527. } // switch
  1528.  
  1529. if (preg_match('/^(csv|pdf)/i', strtolower($GLOBALS['mode']))) {
  1530. if (isset($fieldspec['optionlist'])) {
  1531. if (empty($fieldvalue)) {
  1532. $fieldvalue = null;
  1533. } else {
  1534. // convert value into corresponding entry(s) from optionlist
  1535. if (isset($this->lookup_data[$fieldspec['optionlist']])) {
  1536. $lookup = $this->lookup_data[$fieldspec['optionlist']];
  1537. if (!empty($lookup)) {
  1538. if (is_array($fieldvalue)) {
  1539. // convert array into a comma separated string
  1540. $string = '';
  1541. foreach ($fieldvalue as $key) {
  1542. $string .= $lookup[$key] .',';
  1543. } // foreach
  1544. $fieldvalue = rtrim($string, ',');
  1545. } else {
  1546. if (array_key_exists($fieldvalue, $lookup)) {
  1547. $fieldvalue = $lookup[$fieldvalue];
  1548. } // if
  1549. } // if
  1550. } // if
  1551. } // if
  1552. } // if
  1553. } elseif (isset($fieldspec['foreign_field'])) {
  1554. if (isset($fieldarray[$fieldspec['foreign_field']])) {
  1555. $fieldvalue = $fieldarray[$fieldspec['foreign_field']];
  1556. } // if
  1557. } // if
  1558. } // if
  1559.  
  1560. if (isset($fieldspec['password'])) {
  1561. if (isset($fieldspec['hash'])) {
  1562. if (preg_match('/(sha1|md5)/i', $fieldspec['hash'])) {
  1563. // for this hash type do not output anything
  1564. $fieldvalue = '';
  1565. } // if
  1566. } // if
  1567. } // if
  1568.  
  1569. // put changed value back into array
  1570. if ($GLOBALS['mode'] == 'search' AND $operator != '=') {
  1571. $fieldarray[$fieldname] = $operator.$fieldvalue;
  1572. } else {
  1573. $fieldarray[$fieldname] = $fieldvalue;
  1574. } // if
  1575.  
  1576. } else {
  1577. // not in $this->fieldspec, so cannot be formatted
  1578. $fieldarray[$fieldname] = $fieldvalue;
  1579. } // if
  1580. } // foreach
  1581.  
  1582. // perform any custom formatting
  1583. if (is_object($this->custom_processing_object)) {
  1584. if (method_exists($this->custom_processing_object, '_cm_formatData')) {
  1585. $fieldarray = $this->custom_processing_object->_cm_formatData($fieldarray, $css_array);
  1586. } // if
  1587. } // if
  1588. if ($this->custom_replaces_standard) {
  1589. $this->custom_replaces_standard = false;
  1590. } else {
  1591. $fieldarray = $this->_cm_formatData($fieldarray, $css_array);
  1592. } // if
  1593.  
  1594. return $fieldarray;
  1595.  
  1596. } // formatData
  1597.  
  1598. // ****************************************************************************
  1599. function free_result ($resource)
  1600. // free a resource created by getData_serial()
  1601. {
  1602. $result = $this->_dml_free_result($resource);
  1603.  
  1604. return $result;
  1605.  
  1606. } // free_result
  1607.  
  1608. // ****************************************************************************
  1609. function &getChildData ()
  1610. // return $fieldarray from the child object (if there is one).
  1611. // NOTE: output is passed by reference.
  1612. {
  1613. if (!is_object($this->child_object)) {
  1614. return FALSE;
  1615. } elseif (!method_exists($this->child_object, 'getFieldArray')) {
  1616. return FALSE;
  1617. } // if
  1618.  
  1619. $child_data =& $this->child_object->getFieldArray();
  1620.  
  1621. return $child_data;
  1622.  
  1623. } // getChildData
  1624.  
  1625. // ****************************************************************************
  1626. function getClassName ()
  1627. // return the name of this class, but without any numeric suffix.
  1628. // Example: table 'mnu_tran' may have subtypes (aliases) of 'mnu_tran_s01'
  1629. // and 'mnu_tran_jnr'. These will return the following:
  1630. // 'mnu_task' -> 'mnu_task'
  1631. // 'mnu_task_s01' -> 'mnu_task'
  1632. // 'mnu_task_jnr' -> 'mnu_task_jnr'
  1633. {
  1634. $tablename = removeTableSuffix(get_class($this));
  1635.  
  1636. return strtolower($tablename);
  1637.  
  1638. } // getClassName
  1639.  
  1640. // ****************************************************************************
  1641. function getColumnNames ($where=null)
  1642. // obtain list of column names which will be output with this SQL statement.
  1643. // (this is used in 'std.output4.inc')
  1644. {
  1645. $this->rows_per_page = 1;
  1646.  
  1647. $this->fieldspec = $this->getFieldSpec_original();
  1648.  
  1649. $fieldarray = array();
  1650. $fieldspec = array();
  1651.  
  1652. $this->lookup_data['selected'] = $this->getLanguageArray('selected');;
  1653.  
  1654. $data = $this->getData($where);
  1655. if (empty($data)) return $data;
  1656.  
  1657. $fieldarray = $data[0];
  1658.  
  1659. // initial value for each column is 'selected'
  1660. foreach ($fieldarray as $fieldname => &$fieldvalue) {
  1661. $fieldvalue = 'Y';
  1662. } // foreach
  1663.  
  1664. // modify list of column names and their default values
  1665. if (is_object($this->custom_processing_object)) {
  1666. if (method_exists($this->custom_processing_object, '_cm_getColumnNames')) {
  1667. $fieldarray = $this->custom_processing_object->_cm_getColumnNames($fieldarray);
  1668. } // if
  1669. } // if
  1670. if ($this->errors) return;
  1671. if ($this->custom_replaces_standard) {
  1672. $this->custom_replaces_standard = false;
  1673. } else {
  1674. $fieldarray = $this->_cm_getColumnNames($fieldarray);
  1675. if ($this->errors) return;
  1676. } // if
  1677.  
  1678. ksort($fieldarray);
  1679. foreach ($fieldarray as $fieldname => &$fieldvalue) {
  1680. // each field has a 'Yes/No' dropdown with an initial value
  1681. if (is_True($fieldvalue)) {
  1682. $fieldvalue = 'Y';
  1683. } else {
  1684. $fieldvalue = 'N';
  1685. } // if
  1686. $fieldspec[$fieldname] = array('type' => 'string',
  1687. 'control' => 'dropdown',
  1688. 'optionlist' => 'selected');
  1689. // add this column to the screen structure
  1690. $GLOBALS['screen_structure']['main']['fields'][] = array($fieldname => $fieldname, 'colspan' => 3);
  1691. } // foreach
  1692.  
  1693. // add controls for LIMIT and OFFSET
  1694. $fieldspec['rdc_limit'] = array('type' => 'integer', 'minvalue' => 0, 'maxvalue' => 4294967295, 'required' => 'y');
  1695. $fieldspec['rdc_offset'] = array('type' => 'integer', 'minvalue' => 0, 'maxvalue' => 4294967295, 'required' => 'y');
  1696. $fieldarray['rdc_limit'] = 1000;
  1697. $fieldarray['rdc_offset'] = 0;
  1698. // append fields for LIMIT and OFFSET
  1699. $col_count = count($GLOBALS['screen_structure']['main']['fields'])+1;
  1700. $GLOBALS['screen_structure']['main']['fields'][$col_count][] = array('label' => 'rdc_limit',);
  1701. $GLOBALS['screen_structure']['main']['fields'][$col_count][] = array('field' => 'rdc_limit');
  1702. $GLOBALS['screen_structure']['main']['fields'][$col_count][] = array('label' => 'rdc_offset');
  1703. $GLOBALS['screen_structure']['main']['fields'][$col_count][] = array('field' => 'rdc_offset');
  1704.  
  1705. $this->rows_per_page = 0; // allow multiple rows to be returned on the next call to getData()
  1706.  
  1707. $this->fieldspec = $fieldspec;
  1708. $this->fieldarray = $fieldarray;
  1709.  
  1710. return $fieldarray;
  1711.  
  1712. } // getColumnNames
  1713.  
  1714. // ****************************************************************************
  1715. function getCount ($where=null)
  1716. // get count of records that satisfy selection criteria in $where.
  1717. {
  1718. if (strlen(trim($where)) > 0) {
  1719. $count = $this->_dml_getCount($where);
  1720. return $count;
  1721. } else {
  1722. return 0;
  1723. } // if
  1724.  
  1725. } // getCount
  1726.  
  1727. // ****************************************************************************
  1728. function getData ($where=null)
  1729. // get data from this table using optional 'where' criteria.
  1730. // this is formatted before being displayed to the user.
  1731. {
  1732. $this->errors = array(); // initialise
  1733. $data_raw = array();
  1734.  
  1735. // if (!empty($this->sql_where)) {
  1736. // // remove anything in $this->sql_where which is duplicated in $where
  1737. // $this->sql_where = filterWhere1Where2($where, $this->sql_where, $this->tablename);
  1738. // } // if
  1739.  
  1740. $this->where = $where; // save
  1741.  
  1742. if (is_null($this->pageno)) {
  1743. $this->pageno = 1; //default
  1744. } // if
  1745.  
  1746. // convert $where from string to an associative array
  1747. $where_array = where2array($where, $this->pageno);
  1748.  
  1749. if (!empty($where_array['rdc_table_name'])) {
  1750. $where_array = convert_parent_id_to_child_id($where_array, $this->tablename, $this->parent_relations);
  1751. $where = array2where($where_array);
  1752. } // if
  1753.  
  1754. // make this data available if passed down by parent object
  1755. if (empty($this->fieldarray)) {
  1756. $fieldarray = array();
  1757. } else {
  1758. if (is_string(key($this->fieldarray))) {
  1759. $fieldarray = $this->fieldarray;
  1760. } else {
  1761. $fieldarray = array_shift($this->fieldarray);
  1762. } // if
  1763. } // if
  1764.  
  1765. if ($this->initiated_from_controller) {
  1766. // replace with original unmodified version
  1767. $this->sql_search = $this->sql_search_orig;
  1768. } // if
  1769.  
  1770. // perform any custom pre-retrieve processing
  1771. if (is_object($this->custom_processing_object)) {
  1772. if (method_exists($this->custom_processing_object, '_cm_pre_getData')) {
  1773. $where = $this->custom_processing_object->_cm_pre_getData($where, $where_array, $fieldarray);
  1774. } // if
  1775. } // if
  1776. if ($this->errors) return;
  1777. if ($this->custom_replaces_standard) {
  1778. $this->custom_replaces_standard = false;
  1779. } else {
  1780. $where = $this->_cm_pre_getData($where, $where_array, $fieldarray);
  1781. if ($this->errors) return;
  1782. } // if
  1783.  
  1784. if ($this->where != $where) {
  1785. // $where has been modified, so update $where_array
  1786. $this->where = $where;
  1787. $where_array = where2array($where, $this->pageno);
  1788. } // if
  1789.  
  1790. if ($this->checkPrimaryKey AND !$this->allow_empty_where) {
  1791. // check that full primary key (or candidate key) has been supplied
  1792. list($where1, $errors1) = isPkeyComplete($where_array, $this->getPkeyNames(), $this->unique_keys, $this);
  1793. if (!empty($errors1)) {
  1794. $this->errors = $errors1;
  1795. return;
  1796. } // if
  1797. $this->checkPrimaryKey = false;
  1798. } // if
  1799.  
  1800. if ($this->skip_getdata) {
  1801. // use data already loaded in
  1802. if (is_int(key($this->fieldarray))) {
  1803. // already indexed by row
  1804. $data_raw = $this->fieldarray;
  1805. } else {
  1806. if (empty($this->fieldarray)) {
  1807. $data_raw = array();
  1808. } else {
  1809. // associative array, so make it row zero
  1810. $data_raw[0] = $this->fieldarray;
  1811. } // if
  1812. } // if
  1813. $this->numrows = count($data_raw);
  1814. if (empty($this->scrollarray)) {
  1815. // set record/page counts from contents of $this->fieldarray
  1816. if ($this->numrows == 0) {
  1817. $this->lastpage = 0;
  1818. $this->pageno = 0;
  1819. } else {
  1820. if ($this->rows_per_page > 0) {
  1821. $this->lastpage = ceil($this->numrows/$this->rows_per_page);
  1822. } else {
  1823. $this->lastpage = $this->numrows;
  1824. } // if
  1825. if ($this->pageno < 1) {
  1826. $this->pageno = 1;
  1827. } elseif ($this->pageno > $this->lastpage) {
  1828. $this->pageno = $this->lastpage;
  1829. } // if
  1830. } // if
  1831. } // if
  1832.  
  1833. } else {
  1834. // assemble the $where string from its component parts
  1835. $where_str = $this->_sqlAssembleWhere($where, $where_array);
  1836.  
  1837. // get the data from the database
  1838. $data_raw = $this->_dml_getData($where_str);
  1839. } // if
  1840.  
  1841. if (!empty($this->select_string)) {
  1842. $data_raw = $this->setSelectedRows($this->select_string, $data_raw);
  1843. } // if
  1844.  
  1845. if ($this->initiated_from_controller) {
  1846. if (isset($GLOBALS['script_vars']['task_id_run_at_end'])) {
  1847. if ($this->rows_per_page > 1
  1848. OR ($this->rows_per_page = 1 AND $this->numrows > 1)) {
  1849. // too many rows selected, so turn this option off
  1850. unset($GLOBALS['script_vars']['task_id_run_at_end']);
  1851. unset($GLOBALS['script_vars']['task_id_run_at_end_context']);
  1852. } else {
  1853. // set context for this option
  1854. $GLOBALS['script_vars']['task_id_run_at_end_context'] = $where;
  1855. } // if
  1856. } // if
  1857. } // if
  1858.  
  1859. if ($GLOBALS['mode'] != 'insert') {
  1860. // clear 'nodisplay' option which may have been by previous iteration
  1861. foreach ($this->fieldspec as $field => $spec) {
  1862. if (array_key_exists('autoinsert', $spec) or array_key_exists('autoupdate', $spec)) {
  1863. unset($this->fieldspec[$field]['nodisplay']);
  1864. } // if
  1865. } // foreach
  1866. } // if
  1867.  
  1868. // $entry = getEntryPoint($this);
  1869. // if (strtolower($entry) == 'getdata') {
  1870. if (isset($this->instruction)) {
  1871. $data_raw = $this->_processInstruction($data_raw);
  1872. } // if
  1873.  
  1874. // perform any custom post-retrieve processing
  1875. if (is_object($this->custom_processing_object)) {
  1876. if (method_exists($this->custom_processing_object, '_cm_post_getData')) {
  1877. $data_raw = $this->custom_processing_object->_cm_post_getData($data_raw, $where);
  1878. } // if
  1879. } // if
  1880. if ($this->custom_replaces_standard) {
  1881. $this->custom_replaces_standard = false;
  1882. } else {
  1883. $data_raw = $this->_cm_post_getData($data_raw, $where);
  1884. } // if
  1885. $this->where = $where;
  1886. // } // if
  1887.  
  1888. $this->fieldarray = $data_raw;
  1889.  
  1890. return $this->fieldarray;
  1891.  
  1892. } // getData
  1893.  
  1894. // ****************************************************************************
  1895. function getData_raw ($where=null)
  1896. // get data from this table using optional 'where' criteria.
  1897. // this is returned raw (as read from the database with any formatting).
  1898. {
  1899. $this->errors = array();
  1900.  
  1901. // convert $where from string to an associative array
  1902. $where_array = where2array($where);
  1903.  
  1904. if (isset($this->fieldspec['rdcaccount_id'])) {
  1905. // this table is split by account, so account_id must be supplied in WHERE string
  1906. if (!isset($where_array['rdcaccount_id'])) {
  1907. $account_id =& $_SESSION['rdcaccount_id'];
  1908. if (empty($account_id) AND preg_match('/(mnu_user|mnu_account)/i', $this->tablename)) {
  1909. // no account id supplied, so read everything on these tables only
  1910. } else {
  1911. if (empty($account_id) OR $account_id == 1) {
  1912. $account_id_string = "$this->tablename.rdcaccount_id='1'";
  1913. } else {
  1914. $account_id_string = "$this->tablename.rdcaccount_id IN ('1', '$account_id')";
  1915. } // if
  1916. if (empty($this->sql_where)) {
  1917. $this->sql_where = $account_id_string;
  1918. } else {
  1919. if (substr_count($this->sql_where, $account_id_string) == 0) {
  1920. $this->sql_where .= " AND $account_id_string";
  1921. } // if
  1922. } // if
  1923. } // if
  1924. } // if
  1925. } // if
  1926.  
  1927. if (!empty($this->sql_where)) {
  1928. if (preg_match('/^(OR )/i', $this->sql_where)) {
  1929. // begins with 'OR ', so do not append using ' AND '
  1930. $where .= ' '.$this->sql_where;
  1931. } else {
  1932. if (empty($where)) {
  1933. $where = $this->sql_where;
  1934. } else {
  1935. $where = "$where AND $this->sql_where";
  1936. } // if
  1937. } // if
  1938. } // if
  1939.  
  1940. if (!empty($this->sql_search)) {
  1941. // turn 'current/historic/future' into a range of dates
  1942. $this->sql_search = $this->currentOrHistoric($this->sql_search, $this->nameof_start_date, $this->nameof_end_date);
  1943. if (!empty($this->sql_search)) {
  1944. if (empty($where)) {
  1945. $where = $this->sql_search;
  1946. } else {
  1947. $where = "$where AND $this->sql_search";
  1948. } // if
  1949. } // if
  1950. } // if
  1951.  
  1952. // if (!empty($this->sql_from)) {
  1953. // $alias_array = extractAliasNames($this->sql_select);
  1954. // // anything in WHERE which has an alias name will be moved to HAVING
  1955. // $having_array = where2array($this->sql_having, false, false);
  1956. // $where = qualifyWhere($where, $this->tablename, $this->fieldspec, $this->sql_from, $this->sql_search_table, $alias_array, $having_array);
  1957. // } // if
  1958.  
  1959. $data_raw = $this->_dml_getData($where, TRUE);
  1960.  
  1961. return $data_raw;
  1962.  
  1963. } // getData_raw
  1964.  
  1965. // ****************************************************************************
  1966. function getData_serial ($where=null, $rdc_limit=null, $rdc_offset=null, $unbuffered=false)
  1967. // get data from this table using optional 'where' criteria.
  1968. // this does not return the records one page at a time but allows a serial
  1969. // read via the fetchRow() method of all records for processing in another way,
  1970. // such as exporting to CSV.
  1971. {
  1972. $this->errors = array(); // initialise
  1973.  
  1974. $this->where = $where; // save
  1975.  
  1976. // convert $where from string to an associative array
  1977. $where_array = where2array($where, $this->pageno);
  1978.  
  1979. if ($this->initiated_from_controller AND !empty($this->sql_search_orig)) {
  1980. // replace with original unmodified version
  1981. $this->sql_search = $this->sql_search_orig;
  1982. } // if
  1983.  
  1984. // perform any custom pre-retrieve processing
  1985. if (is_object($this->custom_processing_object)) {
  1986. if (method_exists($this->custom_processing_object, '_cm_pre_getData')) {
  1987. $where = $this->custom_processing_object->_cm_pre_getData($where, $where_array, $this->fieldarray);
  1988. } // if
  1989. } // if
  1990. if ($this->errors) return;
  1991. if ($this->custom_replaces_standard) {
  1992. $this->custom_replaces_standard = false;
  1993. } else {
  1994. $where = $this->_cm_pre_getData($where, $where_array);
  1995. if ($this->errors) return;
  1996. } // if
  1997.  
  1998. if ($this->where != $where) {
  1999. // $where has been modified, so update $where_array
  2000. $this->where = $where;
  2001. $where_array = where2array($where, $this->pageno);
  2002. } // if
  2003.  
  2004. if ($this->checkPrimaryKey) {
  2005. // check that full primary key (or candidate key) has been supplied
  2006. list($where1, $errors1) = isPkeyComplete($where_array, $this->getPkeyNames(), $this->unique_keys);
  2007. if (!empty($errors1)) {
  2008. $this->errors = $errors1;
  2009. return;
  2010. } // if
  2011. $this->checkPrimaryKey = false;
  2012. } // if
  2013.  
  2014. if ($this->skip_getdata) {
  2015. // do not populate $this->fieldarray from the database
  2016. if (is_int(key($this->fieldarray))) {
  2017. // already indexed by row
  2018. $data_raw = $this->fieldarray;
  2019. } else {
  2020. // associative array, so make it row zero
  2021. $data_raw[0] = $this->fieldarray;
  2022. } // if
  2023. $this->fieldarray = $data_raw;
  2024. $this->numrows = count($data_raw);
  2025. $resource = null;
  2026. } else {
  2027. // assemble the $where string from its component parts
  2028. $where_str = $this->_sqlAssembleWhere($where, $where_array);
  2029.  
  2030. // get the result from the database
  2031. $resource = $this->_dml_getData_serial($where_str, $rdc_limit, $rdc_offset, $this->unbuffered_query);
  2032. } // if
  2033.  
  2034. // Note: individual records are obtained using the fetchRow() method
  2035.  
  2036. return $resource;
  2037.  
  2038. } // getData_serial
  2039.  
  2040. // ****************************************************************************
  2041. function getDBname ()
  2042. // return the database name for this table.
  2043. {
  2044. return strtolower($this->dbname);
  2045.  
  2046. } // getDBname
  2047.  
  2048. // ****************************************************************************
  2049. function getEnum ($fieldname)
  2050. // get the contents of an ENUM field and return it as an array.
  2051. {
  2052. $array = $this->_dml_getEnum($fieldname);
  2053.  
  2054. return $array;
  2055.  
  2056. } // getEnum
  2057.  
  2058. // ****************************************************************************
  2059. function getErrors ()
  2060. // return array of error messages
  2061. {
  2062. $errors = $this->errors;
  2063. $this->errors = array();
  2064.  
  2065. if (!is_array($errors)) {
  2066. // convert string into an array
  2067. $errors = (array)$errors;
  2068. } // if
  2069.  
  2070. return $errors;
  2071.  
  2072. } // getErrors
  2073.  
  2074. // ****************************************************************************
  2075. function getExpanded ()
  2076. // get array of tree nodes which have been expanded
  2077. {
  2078. $expanded = $this->expanded;
  2079. $this->expanded = array();
  2080.  
  2081. return $expanded;
  2082.  
  2083. } // getExpanded
  2084.  
  2085. // ****************************************************************************
  2086. function getExtraData ($input, $where=null)
  2087. // get additional data for this table, such as lookup lists.
  2088. {
  2089. //$this->errors = array();
  2090.  
  2091. // $input may be an array or a string
  2092. if (empty($input)) {
  2093. $fieldarray[0] = array();
  2094. $key = 0;
  2095. $where = null;
  2096. } elseif (is_string($input)) {
  2097. // convert from string to associative array
  2098. $fieldarray[0] = where2array($input);
  2099. $key = 0;
  2100. $where = $input;
  2101. } else {
  2102. reset($input); // fix for version 4.4.1
  2103. if (is_string(key($input))) {
  2104. // associative array, so set it to row zero
  2105. $fieldarray[0] = $input;
  2106. $key = 0;
  2107. } else {
  2108. // indexed by row, so use it as-is
  2109. $fieldarray = $input;
  2110. $key = key($input);
  2111. } // if
  2112. // convert first row in $fieldarray to a string
  2113. //$where = array2where($fieldarray[$key]);
  2114. } // if
  2115.  
  2116. if (is_True($this->no_foreign_data)) {
  2117. // skip this next bit
  2118. } else {
  2119. // retrieve data from foreign (parent) tables for each row
  2120. foreach ($fieldarray as $rownum => $rowdata) {
  2121. $fieldarray[$rownum] = $this->getForeignData($rowdata);
  2122. } // foreach
  2123. } // if
  2124.  
  2125. // perform custom processing (such as obtaining lookup lists) on FIRST record only
  2126. if (is_object($this->custom_processing_object)) {
  2127. if (method_exists($this->custom_processing_object, '_cm_getExtraData')) {
  2128. $fieldarray[$key] = $this->custom_processing_object->_cm_getExtraData($where, $fieldarray[$key]);
  2129. } // if
  2130. } // if
  2131. if ($this->custom_replaces_standard) {
  2132. $this->custom_replaces_standard = false;
  2133. } else {
  2134. $fieldarray[$key] = $this->_cm_getExtraData($where, $fieldarray[$key]);
  2135. } // if
  2136.  
  2137. $fieldarray[$key] = array_change_key_case($fieldarray[$key], CASE_LOWER);
  2138.  
  2139. // change current table configuration (optional)
  2140. if (is_object($this->custom_processing_object)) {
  2141. if (method_exists($this->custom_processing_object, '_cm_changeConfig')) {
  2142. $fieldarray[$key] = $this->custom_processing_object->_cm_changeConfig($where, $fieldarray[$key]);
  2143. } // if
  2144. } // if
  2145. if ($this->custom_replaces_standard) {
  2146. $this->custom_replaces_standard = false;
  2147. } else{
  2148. // change current table configuration (optional)
  2149. $fieldarray[$key] = $this->_cm_changeConfig($where, $fieldarray[$key]);
  2150. } // if
  2151.  
  2152. $pattern_id = getPatternId();
  2153. if (preg_match('/MULTI4/i', $pattern_id) AND !empty($this->initial_values)) {
  2154. foreach ($fieldarray as $rownum => $rowdata) {
  2155. // insert any initial values obtained from MNU_INITIAL_VALUE_ROLE/USER table
  2156. foreach ($this->initial_values as $key1 => $value1) {
  2157. if (empty($rowdata[$key1])) {
  2158. // current value is empty, so overwrite with initial value
  2159. $rowdata[$key1] = $value1;
  2160. } // if
  2161. } // foreach
  2162. $fieldarray[$rownum] = $rowdata;
  2163. } // foreach
  2164. } // if
  2165.  
  2166. // store updated $fieldarray within this object
  2167. $this->fieldarray = $fieldarray;
  2168.  
  2169. return $this->getFieldArray();
  2170.  
  2171. } // getExtraData
  2172.  
  2173. // ****************************************************************************
  2174. function getFieldArray ()
  2175. // return array of data that currently resides within this object
  2176. // (usually stuff which was retrieved from the database).
  2177. {
  2178. if (empty($this->fieldarray)) {
  2179. return array();
  2180. } // if
  2181.  
  2182. reset($this->fieldarray);
  2183. if ($this->rows_per_page == 1) {
  2184. // return an associative array (one row only)
  2185. if (is_long(key($this->fieldarray))) {
  2186. return $this->fieldarray[0]; // convert indexed to associative
  2187. } else {
  2188. return $this->fieldarray;
  2189. } // if
  2190. } else {
  2191. // return an indexed array (one or more rows)
  2192. if (is_long(key($this->fieldarray))) {
  2193. return $this->fieldarray;
  2194. } else {
  2195. return array($this->fieldarray); // convert associative to indexed
  2196. } // if
  2197. } // if
  2198.  
  2199. } // getFieldArray
  2200.  
  2201. // ****************************************************************************
  2202. function getFieldSpec ()
  2203. // return array of field specifications (which may be adjusted by $this->field_access).
  2204. {
  2205. if (!empty($this->field_access)) {
  2206. // include specified access_type in $fieldspec array
  2207. foreach ($this->field_access as $field_id => $access_type) {
  2208. if (array_key_exists($field_id, $this->fieldspec)) {
  2209. $this->fieldspec[$field_id][$access_type] = 'y';
  2210. } // if
  2211. } // foreach
  2212. } // if
  2213.  
  2214. return $this->fieldspec;
  2215.  
  2216. } // getFieldSpec
  2217.  
  2218. // ****************************************************************************
  2219. function getFieldSpec_original ()
  2220. // set the specifications for this database table.
  2221. {
  2222. if (empty($this->fieldspec)) {
  2223. // first time only - look for changes in engine, prefix or database name
  2224. list($dbname, $this->dbprefix, $this->dbms_engine) = findDBConfig($this->dbname);
  2225. $this->dbname_server = $this->dbprefix.$dbname;
  2226. } // if
  2227.  
  2228. if (is_bool($this->audit_logging) OR !empty($this->audit_logging)) {
  2229. $save_audit_logging = $this->audit_logging;
  2230. } else {
  2231. $save_audit_logging = null;
  2232. } // if
  2233.  
  2234. $fieldspec = array();
  2235. $this->primary_key = array();
  2236. $this->unique_keys = array();
  2237. $this->child_relations = array();
  2238. $this->parent_relations = array();
  2239. $this->audit_logging = FALSE;
  2240. $this->default_orderby = '';
  2241. $this->alt_language_table = '';
  2242. $this->alt_language_cols = '';
  2243. $this->nameof_start_date = '';
  2244. $this->nameof_end_date = '';
  2245.  
  2246. $tablename = $this->getTableName();
  2247. if ($tablename != 'default') {
  2248. // include table specifications generated by Data Dictionary
  2249. if (!empty($this->dirname_dict)) {
  2250. require ($this->dirname_dict .'/' .$tablename .'.dict.inc');
  2251. } else {
  2252. require ($this->dirname .'/' .$tablename .'.dict.inc');
  2253. } // if
  2254. if (is_bool($save_audit_logging) OR !empty($save_audit_logging)) {
  2255. $this->audit_logging = $save_audit_logging;
  2256. } // if
  2257. } // if
  2258.  
  2259. if (!empty($_SESSION['date_format_output'])) {
  2260. $dateobj =& RDCsingleton::getInstance('date_class');
  2261. foreach ($fieldspec as $field => $spec) {
  2262. if (preg_match('/date/i', $spec['type'], $regs)) {
  2263. $date_length = $dateobj->getDateLength($_SESSION['date_format_output'], $spec['type']);
  2264. $fieldspec[$field]['size'] = $date_length;
  2265. } // if
  2266. } // foreach
  2267. } // if
  2268.  
  2269. if (defined('TRANSIX_NO_AUDIT') OR defined('NO_AUDIT_LOGGING')) {
  2270. $this->audit_logging = false;
  2271. } // if
  2272.  
  2273. //if (empty($this->custom_processing_object)) {
  2274. if ($this->dbname != 'default') {
  2275. $this->_getCustomProcessingObject();
  2276. } // if
  2277.  
  2278. return $fieldspec;
  2279.  
  2280. } // getFieldSpec_original
  2281.  
  2282. // ****************************************************************************
  2283. function getForeignData ($fieldarray)
  2284. // Retrieve data from foreign (parent) database tables.
  2285. // (parent tables are identified in $this->parent_relations)
  2286. {
  2287. if (empty($fieldarray)) {
  2288. return $fieldarray;
  2289. } // if
  2290.  
  2291. // perform custom processing before standard processing
  2292. if (is_object($this->custom_processing_object)) {
  2293. if (method_exists($this->custom_processing_object, '_cm_getForeignData')) {
  2294. $fieldarray = $this->custom_processing_object->_cm_getForeignData($fieldarray);
  2295. } // if
  2296. } // if
  2297. if ($this->custom_replaces_standard) {
  2298. $this->custom_replaces_standard = false;
  2299. } else {
  2300. $fieldarray = $this->_cm_getForeignData($fieldarray);
  2301. } // if
  2302.  
  2303. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  2304.  
  2305. foreach ($this->parent_relations as $reldata) {
  2306. if (isset($reldata['parent_field'])) {
  2307. // may be more than one parent_field, so turn it into an array of separate field names
  2308. list($parent_fields, $alias_array) = extractFieldNamesIndexed($reldata['parent_field']);
  2309. $ix = 0; // set to first entry
  2310. if (!empty($fieldarray[$parent_fields[$ix]])) {
  2311. // parent field is already there, so do nothing
  2312. } else {
  2313. // construct WHERE clause to read from parent table
  2314. $where_array = array();
  2315. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  2316. if (strlen($fldchild) < 1) {
  2317. // 'Name of child field missing in relationship with $tblchild'
  2318. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  2319. break;
  2320. } // if
  2321. if (!isset($fieldarray[$fldchild]) or strlen($fieldarray[$fldchild]) == 0) {
  2322. // foreign key field is missing, so stop further processing
  2323. $where_array = array();
  2324. break;
  2325. } // if
  2326. if (preg_match('/^(IS NULL|IS NOT NULL)$/i', trim($fieldarray[$fldchild]))) {
  2327. if ($GLOBALS['mode'] != 'search') {
  2328. // does not contain a proper value, so do not attempt to read
  2329. $fieldarray[$fldchild] = null;
  2330. } // if
  2331. $where_array = array();
  2332. break;
  2333. } // if
  2334. $where_array[$fldparent] = $fieldarray[$fldchild];
  2335. } // foreach
  2336. if (empty($where_array)) {
  2337. // $where is empty, so set foreign field(s) to empty
  2338. foreach ($parent_fields as $ix => $parent_field) {
  2339. if (!isset($this->fieldspec[$parent_field])) {
  2340. // field is not is current $fieldspec array, so it can be initialised
  2341. $fieldarray[$parent_field] = null;
  2342. } // if
  2343. } // foreach
  2344. } else {
  2345. $where = array2where($where_array, false, false, true);
  2346. $tblparent = $reldata['parent'];
  2347. // instantiate an object for this table
  2348. if (array_key_exists('subsys_dir', $reldata)) {
  2349. $save_cwd = getcwd();
  2350. // switch to other directory so that any includes() within the class
  2351. // are relative to that directory and not the current directory
  2352. $dir = dirname($this->dirname); // path to current subsystem directory
  2353. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/'; // switch to other subsystem directory
  2354. chdir($dir);
  2355. } else {
  2356. $save_cwd = NULL;
  2357. } // if
  2358. if (!class_exists($tblparent)) {
  2359. require_once "classes/$tblparent.class.inc";
  2360. } // end
  2361. $parentobj = new $tblparent;
  2362. $parentobj->sql_select = $reldata['parent_field'];
  2363. $parent_data = $parentobj->getData($where);
  2364. unset($parentobj);
  2365. if (!empty($parent_data)) {
  2366. // copy specified parent field(s) into $fieldarray
  2367. foreach ($parent_fields as $ix => $parent_field) {
  2368. if (empty($fieldarray[$parent_field])) {
  2369. // field is currently empty, so replace it with parent value
  2370. if (array_key_exists($parent_field, $parent_data[0])) {
  2371. $fieldarray[$parent_field] = $parent_data[0][$parent_field];
  2372. } else {
  2373. // original name not found, so look for an alias
  2374. list($original, $alias) = getFieldAlias3($alias_array[$ix]);
  2375. if ($original != $alias) {
  2376. $fieldarray[$parent_field] = $parent_data[0][$original];
  2377. } // if
  2378. } // if
  2379. } // if
  2380. } // foreach
  2381. } else {
  2382. if ($GLOBALS['mode'] == 'search') {
  2383. // key may be incomplete, so leave it alone
  2384. } else {
  2385. // not found, so set foreign key(s) to empty
  2386. //foreach ($reldata['fields'] as $fldchild => $fldparent) {
  2387. // if (in_array($fldchild, $this->primary_key)) {
  2388. // // part of primary key, so leave it alone
  2389. // } else {
  2390. // // not part of primary key, so empty it
  2391. // $fieldarray[$fldchild] = null;
  2392. // } // f
  2393. //} // foreach
  2394. } // if
  2395. } // if
  2396. if (!empty($save_cwd)) {
  2397. // switch back to the original working directory
  2398. chdir($save_cwd);
  2399. } // if
  2400. } // if
  2401. } // if
  2402. } // if
  2403. } // foreach
  2404.  
  2405. return $fieldarray;
  2406.  
  2407. } // getForeignData
  2408.  
  2409. // ****************************************************************************
  2410. function getInitialData ($where)
  2411. // get initial data for new records in this table.
  2412. {
  2413. $this->errors = array();
  2414. $this->numrows = 0;
  2415.  
  2416. if (!empty($where)) {
  2417. if (is_array($where)) {
  2418. $fieldarray = $where;
  2419. } else {
  2420. // convert 'where' string to an associative array
  2421. $fieldarray = where2array($where);
  2422. foreach ($fieldarray as $fieldname => $fieldvalue) {
  2423. if (!is_string($fieldname)) {
  2424. // this is a numeric index, not a valid field name, so remove it
  2425. unset($fieldarray[$fieldname]);
  2426. } else {
  2427. if (preg_match('/^(IS NULL|IS NOT NULL|NOT IN|IN[ ]?\()/i', trim($fieldvalue))) {
  2428. // not a valid value, so remove it
  2429. unset($fieldarray[$fieldname]);
  2430. } elseif (array_key_exists($fieldname, $this->fieldspec)) {
  2431. if (!empty($fieldvalue)) {
  2432. // do not allow any items in $where criteria to be changed
  2433. $this->fieldspec[$fieldname]['noedit'] = 'y';
  2434. } // if
  2435. } // if
  2436. } // if
  2437. } // foreach
  2438. } // if
  2439. } else {
  2440. $fieldarray = array();
  2441. } // if
  2442.  
  2443. if (!empty($this->initial_values)) {
  2444. // insert any initial values obtained from MNU_INITIAL_VALUE_ROLE/USER table
  2445. foreach ($this->initial_values as $key => $value) {
  2446. if (empty($fieldarray[$key])) {
  2447. // current value is empty, so overwrite with initial value
  2448. $fieldarray[$key] = $value;
  2449. } // if
  2450. } // foreach
  2451. } // if
  2452.  
  2453. if (is_True($this->allow_scrolling)) {
  2454. $save_pageno = $this->pageno;
  2455. $save_lastpage = $this->lastpage;
  2456. } // if
  2457.  
  2458. // perform any custom processing (optional)
  2459. $this->sqlSelectInit();
  2460. if (is_object($this->custom_processing_object)) {
  2461. if (method_exists($this->custom_processing_object, '_cm_getInitialData')) {
  2462. $fieldarray = $this->custom_processing_object->_cm_getInitialData($fieldarray);
  2463. } // if
  2464. } // if
  2465. if ($this->errors) return $fieldarray;
  2466. if ($this->custom_replaces_standard) {
  2467. $this->custom_replaces_standard = false;
  2468. } else {
  2469. $fieldarray = $this->_cm_getInitialData($fieldarray);
  2470. } // if
  2471. if ($this->errors) return $fieldarray;
  2472.  
  2473. if (is_True($this->allow_scrolling)) {
  2474. $this->pageno = $save_pageno;
  2475. $this->lastpage = $save_lastpage;
  2476. } // if
  2477.  
  2478. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  2479.  
  2480. if (isset($this->fieldspec['rdcaccount_id'])) {
  2481. if (empty($_SESSION['rdcaccount_id'])) {
  2482. if (preg_match('/(mnu_user|mnu_account)/i', $this->tablename)) {
  2483. // do nothing on this table
  2484. } else {
  2485. // use the 'sharing' id
  2486. $fieldarray['rdcaccount_id'] = 1;
  2487. } // if
  2488. } else {
  2489. if (isset($fieldarray['rdcaccount_id']) AND $fieldarray['rdcaccount_id'] != $_SESSION['rdcaccount_id']) {
  2490. // "User's account (X) is not compatible with record's account (Y)";
  2491. $this->errors['rdcaccount_id'] = getLanguageText('sys0232', $_SESSION['rdcaccount_id'], $fieldarray['rdcaccount_id']);
  2492. return $fieldarray;
  2493. } else {
  2494. // always use this user's account_id
  2495. $fieldarray['rdcaccount_id'] = $_SESSION['rdcaccount_id'];
  2496. } // if
  2497. } // if
  2498. } // if
  2499.  
  2500. // do not display autoinsert/autoupdate fields on input screens
  2501. foreach ($this->fieldspec as $field => $spec) {
  2502. if (array_key_exists('auto_increment', $spec) OR array_key_exists('autoinsert', $spec) OR array_key_exists('autoupdate', $spec)) {
  2503. $this->fieldspec[$field]['nodisplay'] = 'y';
  2504. } // if
  2505. } // foreach
  2506.  
  2507. reset($fieldarray); // fix to enable key($fieldarray) to work
  2508. if (!empty($fieldarray) and !is_string(key($fieldarray))) {
  2509. // this has multiple rows, so ignore
  2510. } else {
  2511. // shift all field names to lower case
  2512. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  2513. if (is_True($this->ignore_empty_fields)) {
  2514. // do not insert any missing fields
  2515. $this->ignore_empty_fields = false;
  2516. } else {
  2517. // insert values for any missing fields
  2518. foreach ($this->fieldspec as $fieldname => $spec) {
  2519. if (isset($spec['nondb'])) {
  2520. // this is a non-database field, so ignore it
  2521. } else {
  2522. if (!isset($fieldarray[$fieldname]) OR strlen($fieldarray[$fieldname]) < 1) {
  2523. if (isset($spec['default']) AND strlen($spec['default']) > 0 AND !preg_match('/(date|time|datetime)/i', $spec['type'])) {
  2524. if (array_key_exists('auto_increment', $spec) OR array_key_exists('autoinsert', $spec) OR array_key_exists('autoupdate', $spec) OR $fieldname == 'rdcaccount_id') {
  2525. // value will be inserted later
  2526. $fieldarray[$fieldname] = NULL;
  2527. } else {
  2528. // default value exists, so load it
  2529. $fieldarray[$fieldname] = $spec['default'];
  2530. } // if
  2531. } else {
  2532. // load an empty value so the field will appear in the XML output
  2533. $fieldarray[$fieldname] = NULL;
  2534. } // if
  2535. } // if
  2536. } // if
  2537. } // foreach
  2538. } // if
  2539. } // if
  2540.  
  2541. $this->fieldarray = $fieldarray;
  2542.  
  2543. return $fieldarray;
  2544.  
  2545. } // getInitialData
  2546.  
  2547. // ****************************************************************************
  2548. function getInitialDataMultiple ($where)
  2549. // get initial data for new records in this table.
  2550. // this is called before insertMultiple(), so there is no user dialog.
  2551. {
  2552. $this->errors = array();
  2553. $this->numrows = 0;
  2554.  
  2555. if (!empty($where)) {
  2556. if (is_array($where)) {
  2557. $fieldarray = $where;
  2558. } else {
  2559. // convert 'where' string to an array which is indexed by row number
  2560. $array1 = splitWhereByRow($where);
  2561. // convert 'where' for each row into an associative array
  2562. foreach ($array1 as $rownum => $rowdata) {
  2563. $fieldarray[] = where2array($rowdata);
  2564. } // foreach
  2565. } // if
  2566. } else {
  2567. $fieldarray = array();
  2568. } // if
  2569.  
  2570. // perform any custom processing (optional)
  2571. if (is_object($this->custom_processing_object)) {
  2572. if (method_exists($this->custom_processing_object, '_cm_getInitialDataMultiple')) {
  2573. $fieldarray = $this->custom_processing_object->_cm_getInitialDataMultiple($fieldarray);
  2574. } // if
  2575. } // if
  2576. if ($this->errors) return $fieldarray;
  2577.  
  2578. if ($this->custom_replaces_standard) {
  2579. $this->custom_replaces_standard = false;
  2580. } else {
  2581. // perform any custom processing (optional)
  2582. $fieldarray = $this->_cm_getInitialDataMultiple($fieldarray);
  2583. } // if
  2584. if ($this->errors) return $fieldarray;
  2585.  
  2586. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  2587.  
  2588. $this->fieldarray = $fieldarray;
  2589.  
  2590. return $fieldarray;
  2591.  
  2592. } // getInitialDataMultiple
  2593.  
  2594. // ****************************************************************************
  2595. function getInstruction ()
  2596. // return an optional instruction to the previous script.
  2597. {
  2598. return $this->instruction;
  2599.  
  2600. } // getInstruction
  2601.  
  2602. // ****************************************************************************
  2603. function getLanguageArray ($id)
  2604. // get named array from the language file.
  2605. {
  2606. $classdir = $GLOBALS['classdir']; // save
  2607. $cwd = getcwd();
  2608. if (!empty($this->dirname) AND $cwd != dirname($this->dirname)) {
  2609. // switch to correct directory for retrieving message text
  2610. $GLOBALS['classdir'] = dirname($this->dirname);
  2611. chdir($GLOBALS['classdir']);
  2612. } // if
  2613.  
  2614. // call the function in the standard library
  2615. $string = getLanguageArray ($id);
  2616.  
  2617. $GLOBALS['classdir'] = $classdir; // restore
  2618. chdir($cwd);
  2619.  
  2620. return $string;
  2621.  
  2622. } // getLanguageArray
  2623.  
  2624. // ****************************************************************************
  2625. function getLanguageEntries ($rows, $parent_data, $fieldlist)
  2626. // ensure that $rows contains an entry for each supported language on MNU_LANGUAGE.
  2627. {
  2628. if (!empty($rows)) {
  2629. return $rows; // some records already there, so do nothing
  2630. } // if
  2631.  
  2632. // convert $fieldlist from string to array
  2633. $fieldlist = explode(',', $fieldlist);
  2634.  
  2635. // edit data passed down from parent record
  2636. foreach ($parent_data as $fieldname => $fieldvalue) {
  2637. // remove unwanted columns
  2638. if (!array_key_exists($fieldname, $this->fieldspec)) {
  2639. // field does not exist in this table, so remove it
  2640. unset($parent_data[$fieldname]);
  2641. } elseif (array_key_exists('pkey', $this->fieldspec[$fieldname])) {
  2642. // leave the primary key
  2643. } elseif ($this->fieldspec[$fieldname]['type'] != 'string') {
  2644. // not a string field, so remove it
  2645. unset($parent_data[$fieldname]);
  2646. } elseif (array_key_exists('autoinsert', $this->fieldspec[$fieldname])) {
  2647. unset($parent_data[$fieldname]);
  2648. } elseif (array_key_exists('autoupdate', $this->fieldspec[$fieldname])) {
  2649. unset($parent_data[$fieldname]);
  2650. } // if
  2651. } // foreach
  2652.  
  2653. $where = array2where($parent_data, $this->getPkeyNames(), $this);
  2654.  
  2655. // obtain list of supported languages
  2656. $language_array = $_SESSION['supported_languages'];
  2657. if (!empty($_SESSION['default_language'])) {
  2658. // remove default language as this is not an alternative
  2659. unset($language_array[$_SESSION['default_language']]);
  2660. } // if
  2661.  
  2662. // eliminate languages which already have an entry on this table
  2663. foreach ($rows as $rownum => $rowdata) {
  2664. if (array_key_exists($rowdata['language_id'], $language_array)) {
  2665. unset($language_array[$rowdata['language_id']]);
  2666. } // if
  2667. } // foreach
  2668.  
  2669. // create entries for languages which are missing
  2670. foreach ($language_array as $language_id => $language_code) {
  2671. $fieldarray = $parent_data;
  2672. $fieldarray['language_id'] = $language_id;
  2673. //$new_data[] = $fieldarray;
  2674. $newdata = $this->insertOrUpdate($fieldarray);
  2675. if ($this->errors) {
  2676. $result = $this->rollback();
  2677. return false;
  2678. } // if
  2679. $rows[] = $newdata;
  2680. } // foreach
  2681.  
  2682. return $rows;
  2683.  
  2684. } // getLanguageEntries
  2685.  
  2686. // ****************************************************************************
  2687. function getLanguageText ($id, $arg1=null, $arg2=null, $arg3=null, $arg4=null, $arg5=null)
  2688. // get text from the language file and include up to 5 arguments.
  2689. {
  2690. $classdir = $GLOBALS['classdir']; // save
  2691. $cwd = getcwd();
  2692. if (!empty($this->dirname) AND $cwd != dirname($this->dirname)) {
  2693. // switch to correct directory for retrieving message text
  2694. $GLOBALS['classdir'] = dirname($this->dirname);
  2695. chdir($GLOBALS['classdir']);
  2696. } // if
  2697.  
  2698. // call the function in the standard library
  2699. $string = getLanguageText ($id, $arg1, $arg2, $arg3, $arg4, $arg5);
  2700.  
  2701. $GLOBALS['classdir'] = $classdir; // restore
  2702. chdir($cwd);
  2703.  
  2704. return $string;
  2705.  
  2706. } // getLanguageText
  2707.  
  2708. // ****************************************************************************
  2709. function getLastIndex ()
  2710. // return the last index number for $this->scrollArray.
  2711. {
  2712. return count($this->scrollarray);
  2713.  
  2714. } // getLastIndex
  2715.  
  2716. // ****************************************************************************
  2717. function getLastPage ()
  2718. // return the last page number for retrieved rows.
  2719. {
  2720. return (int)$this->lastpage;
  2721.  
  2722. } // getLastPage
  2723.  
  2724. // ****************************************************************************
  2725. function getLookupData ()
  2726. // get data to be used in lookups (dropdowns, radio buttons, etc).
  2727. // this is populated in getExtraData().
  2728. {
  2729. if (!empty($this->lookup_data)) {
  2730. $data = $this->lookup_data;
  2731. } else {
  2732. $data = array();
  2733. } // if
  2734.  
  2735. if (!empty($this->lookup_css)) {
  2736. $css = $this->lookup_css;
  2737. } else {
  2738. $css = array();
  2739. } // if
  2740.  
  2741. return array($data, $css);
  2742.  
  2743. } // getLookupData
  2744.  
  2745. // ****************************************************************************
  2746. function getMessages ()
  2747. // return any messages which are not errors.
  2748. {
  2749. $messages = (array)$this->messages;
  2750.  
  2751. $this->messages = array();
  2752.  
  2753. return $messages;
  2754.  
  2755. } // getMessages
  2756.  
  2757. // ****************************************************************************
  2758. function getNodeData ($expanded, $where=null)
  2759. // retrieve requested tree structure from the database.
  2760. // $expanded may be a list of nodes which are to be expanded, or the word
  2761. // 'ALL' to sigify that all possible nodes should be expanded.
  2762. // $where identifies the start point of a tree structure
  2763. {
  2764. if (empty($where)) {
  2765. $wherearray = null;
  2766. } else {
  2767. // turn $where string into an associative array
  2768. $wherearray = where2array($where);
  2769. } // if
  2770.  
  2771. if (isset($this->instruction)) {
  2772. // save this until AFTER the call to _cm_getNodeData
  2773. $instruction = $this->instruction;
  2774. unset($this->instruction);
  2775. } // if
  2776.  
  2777. if (empty($expanded)) {
  2778. $expanded = array();
  2779. } // if
  2780.  
  2781. $rows_per_page = $this->rows_per_page; // save
  2782. $pageno = empty($this->pageno) ? 1 : $this->pageno;
  2783.  
  2784. // pass control to custom method
  2785. $fieldarray = $this->_cm_getNodeData($expanded, $where, $wherearray);
  2786.  
  2787. $this->rows_per_page = $rows_per_page; // restore
  2788. $this->lastpage = ceil($this->numrows/$this->rows_per_page);
  2789. if ($pageno > $this->lastpage) {
  2790. $this->pageno = $this->lastpage;
  2791. } else {
  2792. $this->pageno = $pageno;
  2793. } // if
  2794.  
  2795. if (isset($instruction)) {
  2796. // process an instructions from a child script
  2797. $this->instruction = $instruction;
  2798. $fieldarray = $this->_processInstruction($fieldarray);
  2799. } // if
  2800.  
  2801. $this->fieldarray = $fieldarray;
  2802.  
  2803. $this->where = $where; // save this for any child forms
  2804.  
  2805. return $fieldarray;
  2806.  
  2807. } // getNodeData
  2808.  
  2809. // ****************************************************************************
  2810. function getNumRows ()
  2811. // return the number of rows retrived for the current page.
  2812. {
  2813. return (int)$this->numrows;
  2814.  
  2815. } // getNumRows
  2816.  
  2817. // ****************************************************************************
  2818. function getOrderBy ()
  2819. // return current sort order (to be used in sql SELECT statement).
  2820. {
  2821. // allow sort order to be customised
  2822. $orderby = $this->_cm_getOrderBy($this->sql_orderby);
  2823.  
  2824. if (empty($orderby)) {
  2825. $orderby = $this->default_orderby_task;
  2826. } // if
  2827. if (empty($orderby)) {
  2828. $orderby = $this->default_orderby;
  2829. } // if
  2830.  
  2831. if (empty($orderby)) {
  2832. $this->sql_orderby_seq = null;
  2833. } else {
  2834. if (!empty($this->sql_from)) {
  2835. $orderby = qualifyOrderby($orderby, $this->tablename, $this->fieldspec, $this->sql_select, $this->sql_from);
  2836. } // if
  2837. $this->sql_orderby_seq = $this->getOrderBySeq($orderby, $this->sql_orderby_seq);
  2838. } // if
  2839.  
  2840. return $orderby;
  2841.  
  2842. } // getOrderBy
  2843.  
  2844. // ****************************************************************************
  2845. function getOrderBySeq (&$orderby=null, $orderby_seq=null)
  2846. // return sort sequence ('asc' or 'desc').
  2847. // NOTE: $orderby is passed by reference as it may be modified
  2848. {
  2849. if (empty($orderby)) {
  2850. $orderby_seq = null;
  2851. } else {
  2852. // find out if any sort sequence has been specified on any first field
  2853. $array = explode(',', $orderby);
  2854. // look for any trailing 'asc' or 'desc'
  2855. $pattern = '/( asc| ascending| desc| descending)$/i';
  2856. $found = false;
  2857. foreach ($array as $sortfield) {
  2858. if (preg_match($pattern, $sortfield, $regs)) {
  2859. $found = true;
  2860. if (count($array) == 1) {
  2861. // only one field, so remove sequence from fieldname
  2862. $orderby = substr($orderby, 0, -strlen($regs[0]));
  2863. $orderby_seq = trim($regs[0]);
  2864. } else {
  2865. // more than one field, so remove separate sequence
  2866. $orderby_seq = null;
  2867. } // if
  2868. } // if
  2869. } // foreach
  2870. if ($found == false AND empty($orderby_seq)) {
  2871. $orderby_seq = 'asc';
  2872. } // if
  2873. } // if
  2874.  
  2875. return $orderby_seq;
  2876.  
  2877. } // getOrderBySeq
  2878.  
  2879. // ****************************************************************************
  2880. function getPageNo ()
  2881. // get current page number to be retrieved for a multi-page display.
  2882. {
  2883. if (is_null($this->pageno)) {
  2884. if ($this->lastpage > 0) {
  2885. $this->pageno = 1; // default to first page
  2886. } // if
  2887. } // if
  2888.  
  2889. return (int)$this->pageno;
  2890.  
  2891. } // getPageNo
  2892.  
  2893. // ****************************************************************************
  2894. function &getParentData ()
  2895. // return $fieldarray from the parent object.
  2896. // NOTE: output is passed by reference.
  2897. {
  2898. if (!is_object($this->parent_object)) {
  2899. return FALSE;
  2900. } elseif (!method_exists($this->parent_object, 'getFieldArray')) {
  2901. return FALSE;
  2902. } // if
  2903.  
  2904. $parent_data = $this->parent_object->getFieldArray();
  2905.  
  2906. return $parent_data;
  2907.  
  2908. } // getParentData
  2909.  
  2910. // ****************************************************************************
  2911. function getPkeyArray ($fieldarray=null, $next_task=null)
  2912. // return the list of primary key values for the last selection of data
  2913. // which was retrieved from this table (or the passed array).
  2914. {
  2915. // get name(s) of field(s) which form the primary key
  2916. $pkeynames = $this->getPkeyNames();
  2917.  
  2918. if (!empty($next_task) AND !preg_match('/^(audit)/i', $next_task['task_id'])) {
  2919. // obtain any custom adjustments to this array
  2920. $task_id = $next_task['task_id'];
  2921. $pattern_id = $next_task['pattern_id'];
  2922. $pkeynames = $this->_cm_getPkeyNames($pkeynames, $task_id, $pattern_id);
  2923. if (empty($pkeynames)) {
  2924. // "Primary key has not been defined for table 'x'"
  2925. $this->errors[] = getLanguageText('sys0198', $this->tablename);
  2926. return false;
  2927. } // if
  2928. } // if
  2929.  
  2930. if (empty($fieldarray)) {
  2931. $fieldarray = $this->fieldarray;
  2932. } // if
  2933.  
  2934. reset($fieldarray); // fix for version 4.4.1
  2935. if (!is_array($fieldarray[key($fieldarray)])) {
  2936. // array is one level deep - convert to 2 levels
  2937. $fieldarray = array($fieldarray);
  2938. } // if
  2939.  
  2940. $pkeyarray = array();
  2941. $rowcount = 0;
  2942.  
  2943. // step through each row
  2944. foreach ($fieldarray as $row) {
  2945. // note that $rowcount starts at 1, not 0
  2946. $rowcount++;
  2947. foreach ($pkeynames as $fieldname) {
  2948. if (array_key_exists($fieldname, $row)) {
  2949. // add 'name=value' to array
  2950. $pkeyarray[$rowcount][$fieldname] =& $row[$fieldname];
  2951. } // if
  2952. if ($fieldname == 'id') {
  2953. // include name of this table so that 'id' can be translated in the child
  2954. $pkeyarray[$rowcount]['rdc_table_name'] = get_class($this);
  2955. } // if
  2956. } // foreach
  2957. } // foreach
  2958.  
  2959. return $pkeyarray;
  2960.  
  2961. } // getPkeyArray
  2962.  
  2963. // ****************************************************************************
  2964. function getPkeyNames ()
  2965. // return the list of primary key fields in this table.
  2966. {
  2967. if (!empty($this->primary_key)) {
  2968. $array = $this->primary_key;
  2969. } else {
  2970. // get names from contents of $this->fieldspec
  2971. $array = array();
  2972. foreach ($this->fieldspec as $field => $spec) {
  2973. // look for keyword 'pkey' in field specifications
  2974. if (isset($spec['pkey'])) {
  2975. $array[] = $field;
  2976. } // if
  2977. } // foreach
  2978. } // if
  2979.  
  2980. return $array;
  2981.  
  2982. } // getPkeyNames
  2983.  
  2984. // ****************************************************************************
  2985. function getPkeyNamesAdjusted ()
  2986. // return the (adjusted) list of primary key fields in this table.
  2987. {
  2988. // get array of original names
  2989. $pkey_names = $this->getPkeyNames();
  2990.  
  2991. // allow this array to be adjusted
  2992. $task_id = $_SESSION['pages'][getSelf()]['task_id'];
  2993. $pattern_id = getPatternId();
  2994.  
  2995. if (is_object($this->custom_processing_object)) {
  2996. if (method_exists($this->custom_processing_object, '_cm_getPkeyNames')) {
  2997. $pkey_names = $this->custom_processing_object->_cm_getPkeyNames($pkey_names, $task_id, $pattern_id);
  2998. } // if
  2999. } // if
  3000.  
  3001. if ($this->custom_replaces_standard) {
  3002. $this->custom_replaces_standard = false;
  3003. } else {
  3004. $pkey_names = $this->_cm_getPkeyNames($pkey_names, $task_id, $pattern_id);
  3005. } // if
  3006.  
  3007. return $pkey_names;
  3008.  
  3009. } // getPkeyNamesAdjusted
  3010.  
  3011. // ****************************************************************************
  3012. function getScrollIndex ()
  3013. // return current index which points to $scrollarray.
  3014. {
  3015. return $this->scrollindex;
  3016.  
  3017. } // getScrollIndex
  3018.  
  3019. // ****************************************************************************
  3020. function getScrollItem (&$index)
  3021. // pick out the primary key of the selected item from scrollarray and return
  3022. // it in $where so that the script can use it in the next getData() method.
  3023. // NOTE: $index is passed BY REFERENCE as it may be updated.
  3024. {
  3025. if ($index > count($this->scrollarray)) {
  3026. // index is too high, so reduce it
  3027. $index = count($this->scrollarray);
  3028. } // if
  3029.  
  3030. if (count($this->scrollarray) > 1) {
  3031. if (!function_exists('findJump')) {
  3032. require_once 'include.jump.inc';
  3033. } // if
  3034. // find out if this entry is between a pair of jump points
  3035. $index = findJump($index, $this->scrollindex);
  3036. } // if
  3037.  
  3038. // replace $where with details from the selected entry in scrollarray
  3039. if (is_array($this->scrollarray[$index])) {
  3040. // ensure $where contains nothing but primary key fields
  3041. $where = array2where($this->scrollarray[$index], $this->getPkeyNames());
  3042. } else {
  3043. $where = $this->scrollarray[$index];
  3044. } // if
  3045.  
  3046. // set values to be used by scrolling logic
  3047. $this->scrollindex = $index;
  3048. $this->pageno = $index;
  3049. $this->lastpage = count($this->scrollarray);
  3050.  
  3051. return $where;
  3052.  
  3053. } // getScrollItem
  3054.  
  3055. // ****************************************************************************
  3056. function getScrollSize ()
  3057. // return size of current $scrollarray.
  3058. {
  3059. return count($this->scrollarray);
  3060.  
  3061. } // getScrollSize
  3062.  
  3063. // ****************************************************************************
  3064. function getSearch ()
  3065. // return current selection criteria.
  3066. {
  3067. $search = mergeWhere($this->sql_where, $this->sql_search_orig);
  3068.  
  3069. return $search;
  3070.  
  3071. } // getSearch
  3072.  
  3073. // ****************************************************************************
  3074. function getTableName ()
  3075. // return the name of this table.
  3076. {
  3077. return strtolower($this->tablename);
  3078.  
  3079. } // getTableName
  3080.  
  3081. // ****************************************************************************
  3082. function getValRep ($item, $where=null, $orderby=null)
  3083. // get Value/Representation list from this table.
  3084. {
  3085. $item = strtolower($item);
  3086.  
  3087. // call custom method to obtain data as an associative array.
  3088. if (is_object($this->custom_processing_object)) {
  3089. if (method_exists($this->custom_processing_object, '_cm_getValRep')) {
  3090. $array = $this->custom_processing_object->_cm_getValRep($item, $where, $orderby);
  3091. } // if
  3092. } // if
  3093.  
  3094. if (empty($array)) {
  3095. $array = $this->_cm_getValRep($item, $where, $orderby);
  3096. } // if
  3097.  
  3098. return $array;
  3099.  
  3100. } // getValRep
  3101.  
  3102. // ****************************************************************************
  3103. function getWhere ($next_task)
  3104. // return current selection criteria (may have been amended) before it is
  3105. // passed to the next task.
  3106. {
  3107. $where = mergeWhere($this->where, $this->sql_where);
  3108.  
  3109. $array1 = splitWhereByRow($where);
  3110. if (count($array1) > 1 AND $this->rows_per_page == 1) {
  3111. // multiple rows selected, but only one row displayed, so ...
  3112. // reduce WHERE to current row only
  3113. $where = array2where($this->fieldarray, $this->getPkeyNamesAdjusted());
  3114. } // if
  3115.  
  3116. if (!empty($where)) {
  3117. $pkeynames = $this->getPkeyNames();
  3118. if (count($pkeynames) == 1) {
  3119. if ($pkeynames[0] == 'id') {
  3120. $where .= " AND rdc_table_name='".get_class($this)."'";
  3121. } // if
  3122. } // if
  3123. } // if
  3124.  
  3125. if (!empty($next_task) AND !preg_match('/^(audit)/i', $next_task['task_id'])) {
  3126. // obtain any custom adjustments to this string
  3127. $task_id = $next_task['task_id'];
  3128. $pattern_id = $next_task['pattern_id'];
  3129. if (is_object($this->custom_processing_object)) {
  3130. if (method_exists($this->custom_processing_object, '_cm_getWhere')) {
  3131. $where = $this->custom_processing_object->_cm_getWhere($where, $task_id, $pattern_id);
  3132. } // if
  3133. } // if
  3134. if ($this->custom_replaces_standard) {
  3135. $this->custom_replaces_standard = false;
  3136. } else {
  3137. $where = $this->_cm_getWhere($where, $task_id, $pattern_id);
  3138. } // if
  3139. } // if
  3140.  
  3141. return $where;
  3142.  
  3143. } // getWhere
  3144.  
  3145. // ****************************************************************************
  3146. function initialise ($where=null, &$selection=null, $search=null)
  3147. // perform any initialisation for the current task.
  3148. // Note that $selection is PASSED BY REFERENCE as it may be updated.
  3149. {
  3150. $this->pageno = null;
  3151. $this->where = null;
  3152.  
  3153. $pattern_id = getPatternId();
  3154.  
  3155. if (isset($GLOBALS['settings'])) {
  3156. if (is_string($GLOBALS['settings'])) {
  3157. parse_str($GLOBALS['settings'], $GLOBALS['settings']);
  3158. } // if
  3159. if (array_key_exists('allow_empty_where', $GLOBALS['settings'])) {
  3160. $this->allow_empty_where = TRUE;
  3161. } // if
  3162. } // if
  3163.  
  3164. // if (empty($this->custom_processing_object)) {
  3165. $this->_getCustomProcessingObject();
  3166. // } // if
  3167.  
  3168. if (preg_match('/^(mnu_initial_value_)/i', $this->tablename)) {
  3169. // do not look for initial values for the initial values tables
  3170. } else {
  3171. if ($this->initiated_from_controller) {
  3172. // obtain any initial values from MNU_INITIAL_VALUE_ROLE/USER table
  3173. $this->initial_values = $this->_getInitialValues();
  3174.  
  3175. if (preg_match('/^(list|output)/i', $pattern_id)) {
  3176. $this->sql_where = $this->_getInitialWhere($this->sql_where);
  3177. } // if
  3178. } // if
  3179. } // if
  3180.  
  3181. if (preg_match('/^(add|upd2)/i', $pattern_id)) {
  3182. // do not swap $selection with $where
  3183. } else {
  3184. if (empty($where) AND !empty($selection)) {
  3185. // $where is empty, so use $selection instead
  3186. $where = $selection;
  3187. $selection = null;
  3188. } // if
  3189. } // if
  3190.  
  3191. if (!empty($this->sql_where)) {
  3192. // extra WHERE provided in component script
  3193. if (empty($where)) {
  3194. $where = $this->sql_where;
  3195. } else {
  3196. //$where .= ' AND ' .$this->sql_where;
  3197. $where = mergeWhere($where, $this->sql_where);
  3198. } // if
  3199. //$this->sql_where = null;
  3200. } // if
  3201.  
  3202. $where2 = $where; // save for comparison
  3203.  
  3204. // perform any custom initialisation (optional)
  3205. if (is_object($this->custom_processing_object)) {
  3206. if (method_exists($this->custom_processing_object, '_cm_initialise')) {
  3207. $where2 = $this->custom_processing_object->_cm_initialise($where2, $selection, $search);
  3208. } // if
  3209. } // if
  3210. if ($this->errors) return $where2;
  3211. if ($this->custom_replaces_standard) {
  3212. $this->custom_replaces_standard = false;
  3213. } else {
  3214. $where2 = $this->_cm_initialise($where2, $selection, $search);
  3215. } // if
  3216. if ($this->errors) return $where2;
  3217.  
  3218. if ($where2 != $where) {
  3219. // this was changed in _cm_initialise(), so use the new version
  3220. $where = $where2;
  3221. } else {
  3222. if (preg_match('/^(add|upd2)/i', $pattern_id)) {
  3223. // do not swap $selection with $where
  3224. } else {
  3225. if (!empty($selection)) {
  3226. // $selection takes precedence over $where
  3227. $where = $selection;
  3228. $selection = null;
  3229. } // if
  3230. } // if
  3231. } // if
  3232.  
  3233. // convert $where string to an array
  3234. $fieldarray = where2array($where, false, false);
  3235.  
  3236. if (isset($this->fieldspec['rdcaccount_id'])) {
  3237. // is this field editable or non-editable?
  3238. if (isset($_SESSION['rdcaccount_id']) AND $_SESSION['rdcaccount_id'] > 1) {
  3239. $this->fieldspec['rdcaccount_id']['noedit'] = 'y';
  3240. } else{
  3241. if ($this->tablename == 'mnu_user') {
  3242. unset($this->fieldspec['rdcaccount_id']['noedit']);
  3243. unset($this->fieldspec['rdcaccount_id']['nodisplay']);
  3244. } else {
  3245. $this->fieldspec['rdcaccount_id']['noedit'] = 'y';
  3246. } // if
  3247. } // if
  3248. if (count($fieldarray) == 1) {
  3249. $fieldarray = unqualifyFieldArray($fieldarray);
  3250. if (isset($fieldarray['rdcaccount_id'])) {
  3251. // 'rdcaccount_id' is the only value, so can we remove it?
  3252. if ($this->tablename == 'mnu_account') {
  3253. // this is allowed on this table
  3254. } else {
  3255. $where = null;
  3256. $fieldarray = array();
  3257. } // if
  3258. } // if
  3259. } // if
  3260. } // if
  3261.  
  3262. if (!empty($this->alt_language_table)) {
  3263. if ($GLOBALS['mode'] == 'update') {
  3264. if ($_SESSION['user_language'] != $_SESSION['default_language']) {
  3265. if (!empty($this->alt_language_cols)) {
  3266. $screen_fields = getFieldsInScreen($GLOBALS['screen_structure'], $this->zone);
  3267. // cannot update text in base table which was obtained from alternative language table
  3268. $fieldnames = explode(', ', $this->alt_language_cols);
  3269. $display_message = false;
  3270. foreach ($fieldnames as $fieldname) {
  3271. $this->fieldspec[$fieldname]['noedit'] = 'y';
  3272. $this->noedit_array[$fieldname] = true;
  3273. if (in_array($fieldname, $screen_fields)) {
  3274. $display_message = true;
  3275. } // if
  3276. } // foreach
  3277. if ($display_message == true) {
  3278. $this->messages[] = $this->getLanguageText('sys0180');
  3279. } // if
  3280. } // if
  3281. } // if
  3282. } // if
  3283. } // if
  3284.  
  3285. $fieldarray2 = $fieldarray; // save for later comparison
  3286.  
  3287. // change current table configuration (optional)
  3288. if (is_object($this->custom_processing_object)) {
  3289. if (method_exists($this->custom_processing_object, '_cm_changeConfig')) {
  3290. $fieldarray2 = $this->custom_processing_object->_cm_changeConfig($where, $fieldarray2);
  3291. } // if
  3292. } // if
  3293. if ($this->custom_replaces_standard) {
  3294. $this->custom_replaces_standard = false;
  3295. } else {
  3296. $fieldarray2 = $this->_cm_changeConfig($where, $fieldarray2);
  3297. } // if
  3298.  
  3299. if ($fieldarray2 != $fieldarray) {
  3300. $where = array2where($fieldarray2, $this->fieldspec);
  3301. } // if
  3302.  
  3303. if (!empty($this->where)) {
  3304. // replace with string saved in _cm_initialise()
  3305. $where = $this->where;
  3306. } else {
  3307. if (!empty($where)) {
  3308. // remove any fields which do not exist in current table to avoid an SQL error
  3309. $extra = array();
  3310. if (is_object($this->custom_processing_object)) {
  3311. if (method_exists($this->custom_processing_object, '_cm_filterWhere')) {
  3312. $extra = $this->custom_processing_object->_cm_filterWhere($extra);
  3313. } // if
  3314. } // if
  3315. if ($this->custom_replaces_standard) {
  3316. $this->custom_replaces_standard = false;
  3317. } else {
  3318. $extra = $this->_cm_filterWhere($extra);
  3319. } // if
  3320. $where = filterWhere($where, $this->fieldspec, $this->tablename, $extra, $this);
  3321. } // if
  3322. } // if
  3323. $this->where = $where;
  3324.  
  3325. if ($this->initiated_from_controller == true AND $GLOBALS['mode'] == 'search') {
  3326. // rebuild array to include '=' and 'LIKE' operators
  3327. $fieldarray = where2array($where, false, false);
  3328. // do not allow any $where criteria to be changed
  3329. foreach ($fieldarray as $fieldname => $fieldvalue) {
  3330. if (is_integer($fieldname)) {
  3331. // this is an index to a string such as 'EXISTS (...)', so delete it
  3332. unset($fieldarray[$fieldname]);
  3333. } elseif (!empty($fieldvalue)) {
  3334. if (preg_match('/^(LIKE )/i', ltrim($fieldvalue))) {
  3335. // ignore values starting with 'LIKE ' as they come from previous search
  3336. } elseif (preg_match('/^(IS NULL|IS NOT NULL|NOT IN|IN[ ]?\(|NOT LIKE)/i', trim($fieldvalue))) {
  3337. // not a valid value, so remove it
  3338. unset($fieldarray[$fieldname]);
  3339. } else {
  3340. if (array_key_exists('control', $this->fieldspec[$fieldname])) {
  3341. // if 'control' is set then only operators of '=' are allowed
  3342. if (preg_match('/^=/', trim($fieldvalue))) {
  3343. $fieldarray[$fieldname] = stripOperators($fieldvalue);
  3344. $this->fieldspec[$fieldname]['noedit'] = 'y';
  3345. } else {
  3346. unset($fieldarray[$fieldname]);
  3347. } // if
  3348. } elseif (preg_match('/^=/', trim($fieldvalue))) {
  3349. $fieldarray[$fieldname] = stripOperators($fieldvalue);
  3350. $this->fieldspec[$fieldname]['noedit'] = 'y';
  3351. } else {
  3352. $this->fieldspec[$fieldname]['noedit'] = 'y';
  3353. if (preg_match('/^(null)$/i', $fieldvalue)) {
  3354. // replace 'null' (the string) with NULL (the value)
  3355. $fieldarray[$fieldname] = null;
  3356. } // if
  3357. } // if
  3358. } // if
  3359. } // if
  3360. } // foreach
  3361.  
  3362. foreach ($this->fieldspec as $fieldname => $fieldspec) {
  3363. // do not display any fields marked with 'nosearch'
  3364. if (isset($fieldspec['nosearch'])) {
  3365. $this->fieldspec[$fieldname]['nodisplay'] = 'y';
  3366. } // if
  3367. // remove 'required' property to make all fields optional
  3368. if (isset($fieldspec['required'])) {
  3369. unset($this->fieldspec[$fieldname]['required']);
  3370. } // if
  3371. } // foreach
  3372.  
  3373. // look for start_date and end_date in $fieldspec
  3374. if (!empty($this->nameof_start_date)) {
  3375. $start_date = $this->nameof_start_date;
  3376. } else {
  3377. $start_date = 'start_date';
  3378. } // if
  3379. if (!empty($this->nameof_end_date)) {
  3380. $end_date = $this->nameof_end_date;
  3381. } else {
  3382. $end_date = 'end_date';
  3383. } // if
  3384. if (isset($this->fieldspec[$start_date]) AND isset($this->fieldspec[$end_date])) {
  3385. $this->setCurrentOrHistoric();
  3386. } // if
  3387.  
  3388. if (!empty($this->sql_search_table)) {
  3389. $search_table = $this->sql_search_table;
  3390. } else {
  3391. $search_table = $this->tablename;
  3392. } // if
  3393.  
  3394. if (is_array($_SESSION['search']) AND isset($_SESSION['search'][$search_table])) {
  3395. // retrieve previous search criteria and copy into this screen
  3396. $previous = $_SESSION['search'][$search_table];
  3397. // convert from string to associative array
  3398. $previous = where2array($previous, false, false);
  3399. // remove any field that does not belong in this table
  3400. foreach ($previous as $field => $value) {
  3401. list($operator, $value, $delimiter) = extractOperatorValue($value);
  3402. $value = stripslashes($value);
  3403. if (!array_key_exists($field, $this->fieldspec)) {
  3404. // this field doesn't exist in current table, so remove the value
  3405. unset($previous[$field]);
  3406. } else {
  3407. if (strlen($value) > 1 AND substr_count($value, '%') == 1) {
  3408. // remove trailing '%'
  3409. $value = rtrim($value, '%');
  3410. } // if
  3411. } // if
  3412. // if field is aready in $fieldarray do NOT overwrite it
  3413. if (array_key_exists($field, $fieldarray)) {
  3414. unset($previous[$field]);
  3415. } else {
  3416. if (preg_match('/(=|LIKE)/i', $operator)) {
  3417. $previous[$field] = $value;
  3418. } elseif (preg_match('/^[a-zA-Z]+/', $operator)) {
  3419. // operator is alphabetic, so insert a space between it and the value
  3420. $previous[$field] = $operator.' '.$value;
  3421. } else {
  3422. $previous[$field] = $operator.$value;
  3423. } // if
  3424. } // if
  3425. } // foreach
  3426. // merge data into a single array
  3427. $fieldarray = array_merge($previous, $fieldarray);
  3428. } // if
  3429.  
  3430. if (isset($this->fieldspec['curr_or_hist'])) {
  3431. if (empty($fieldarray['curr_or_hist'])) {
  3432. // field is defined but no value is available, so set it to the default
  3433. $fieldarray['curr_or_hist'] = 'C';
  3434. } // if
  3435. } // if
  3436.  
  3437. // save, then convert back into string
  3438. $this->fieldarray = $fieldarray;
  3439. $where = array2where($fieldarray);
  3440.  
  3441. } // if
  3442.  
  3443. if (is_object($this->custom_processing_object)) {
  3444. if (method_exists($this->custom_processing_object, '_cm_setJavaScript')) {
  3445. $this->javascript = $this->custom_processing_object->_cm_setJavaScript($this->javascript);
  3446. } // if
  3447. } // if
  3448. if ($this->custom_replaces_standard) {
  3449. $this->custom_replaces_standard = false;
  3450. } else {
  3451. $this->javascript = $this->_cm_setJavaScript($this->javascript);
  3452. } // if
  3453.  
  3454. if (isset($GLOBALS['mode']) AND preg_match('/(search|list|read)/i', $GLOBALS['mode'])) {
  3455. // ignore this next bit
  3456. } else {
  3457. if ($this->initiated_from_controller) {
  3458. if (preg_match('/^(workflow|audit)$/i', $this->dbname) OR defined('TRANSIX_NO_WORKFLOW') OR defined('RADICORE_NO_WORKFLOW')) {
  3459. // do nothing
  3460. } else {
  3461. if (is_string($where) AND !empty($where)) {
  3462. // find out if this task/context is a workitem within a workflow instance
  3463. $this->_examineWorkflowInstance($where);
  3464. } // if
  3465. } // if
  3466. } // if
  3467. } // if
  3468.  
  3469. return $where;
  3470.  
  3471. } // initialise
  3472.  
  3473. // ****************************************************************************
  3474. function initialiseFileDownload ($where)
  3475. // perform any initialisation for the file download operation.
  3476. {
  3477. if ($this->skip_getdata) {
  3478. // do not read database, use $where string instead
  3479. if (!empty($where)) {
  3480. $fieldarray = where2array($where);
  3481. $this->numrows = 1;
  3482. } // if
  3483. } else {
  3484. $fieldarray = $this->getData_raw($where);
  3485.  
  3486. if ($this->numrows < 1) {
  3487. $this->errors[] = $this->getLanguageText('sys0085'); // 'Nothing retrieved from the database.'
  3488. return false;
  3489. } // if
  3490.  
  3491. // change from indexed to associative for first row
  3492. $fieldarray = $fieldarray[0];
  3493. } // if
  3494.  
  3495. $this->download_filename = 'download_filename';
  3496. $this->download_mode = ''; // 'inline' will disable option to save
  3497.  
  3498. // call customisable method in the subclass.
  3499. $fieldarray = $this->_cm_initialiseFileDownload($fieldarray);
  3500. if (!empty($this->errors)) {
  3501. return FALSE;
  3502. } // if
  3503.  
  3504. if (!isset($fieldarray['ignore_errors'])) {
  3505. if (!file_exists($this->download_filename) ) {
  3506. // 'file does not exist'
  3507. $this->errors[] = $this->getLanguageText('sys0057', $this->download_filename);
  3508. } // if
  3509. } // if
  3510.  
  3511. return $fieldarray;
  3512.  
  3513. } // initialiseFileDownload
  3514.  
  3515. // ****************************************************************************
  3516. function initialiseFilePicker ($where, $search=null)
  3517. // perform any initialisation for the filepicker operation.
  3518. {
  3519. $fieldarray = where2array($where);
  3520.  
  3521. if (empty($this->picker_subdir)) {
  3522. $this->picker_subdir = 'picker';
  3523. } // if
  3524. $this->picker_filetypes = array();
  3525.  
  3526. $this->where = $where;
  3527. $this->fieldarray = $fieldarray;
  3528.  
  3529. // call customisable method in the subclass.
  3530. $fieldarray = $this->_cm_initialiseFilePicker($fieldarray, $search);
  3531. if (!empty($this->errors)) {
  3532. return FALSE;
  3533. } // if
  3534.  
  3535. if (is_array($fieldarray)) {
  3536. $this->fieldarray = $fieldarray;
  3537. } // if
  3538.  
  3539. if (!isset($fieldarray['ignore_errors'])) {
  3540. if (!is_dir($this->picker_subdir) ) {
  3541. if (!is_dir(dirname($this->picker_subdir)) ) {
  3542. // 'source directory does not exist'
  3543. $this->errors[] = $this->getLanguageText('sys0059', $this->picker_subdir);
  3544. } // if
  3545. } // if
  3546. } // if
  3547.  
  3548. // turn array of file types into a string
  3549. $string = '';
  3550. foreach ($this->picker_filetypes as $filetype) {
  3551. if (empty($string)) {
  3552. $string = "(\." .$filetype;
  3553. } else {
  3554. $string .= "|\." .$filetype;
  3555. } // if
  3556. } // foreach
  3557. if (empty($string)) {
  3558. // default is any file extension
  3559. $string = '^([^\.])' // begins with anything but '.'
  3560. . '.*' // any number of characters
  3561. . '(\.[a-zA-Z0-9]+)$'; // ends with '.<anything>'
  3562. } else {
  3563. $string .= ')$';
  3564. } // f
  3565.  
  3566. $this->picker_filetypes = $string;
  3567.  
  3568. return;
  3569.  
  3570. } // initialiseFilePicker
  3571.  
  3572. // ****************************************************************************
  3573. function initialiseFileUpload ($where)
  3574. // perform any initialisation for the file upload operation.
  3575. {
  3576. $fieldarray = where2array($where);
  3577.  
  3578. $this->upload_subdir = 'uploadedfiles';
  3579. $this->upload_filetypes = array('image/gif');
  3580. $this->upload_maxfilesize = 1000000;
  3581.  
  3582. // call customisable method in the subclass.
  3583. if (is_object($this->custom_processing_object)) {
  3584. if (method_exists($this->custom_processing_object, '_cm_initialiseFileUpload')) {
  3585. $fieldarray = $this->custom_processing_object->_cm_initialiseFileUpload($fieldarray);
  3586. $this->resize_array = $this->custom_processing_object->resize_array;
  3587. $this->upload_subdir = $this->custom_processing_object->upload_subdir;
  3588. $this->upload_filetypes = $this->custom_processing_object->upload_filetypes;
  3589. $this->upload_maxfilesize = $this->custom_processing_object->upload_maxfilesize;
  3590. } // if
  3591. } // if
  3592. if ($this->custom_replaces_standard) {
  3593. $this->custom_replaces_standard = false;
  3594. } else {
  3595. $fieldarray = $this->_cm_initialiseFileUpload($fieldarray);
  3596. } // if
  3597. if (!empty($this->errors)) {
  3598. return FALSE;
  3599. } // if
  3600.  
  3601. $this->where = array2where($fieldarray);
  3602.  
  3603. if (!is_dir($this->upload_subdir) ) {
  3604. // 'destination directory does not exist'
  3605. $this->errors[] = $this->getLanguageText('sys0123', $this->upload_subdir);
  3606. } // if
  3607.  
  3608. return $this->where;
  3609.  
  3610. } // initialiseFileUpload
  3611.  
  3612. // ****************************************************************************
  3613. function insertMultiple ($fieldarray)
  3614. // insert multiple records using data in $fieldarray.
  3615. {
  3616. $this->errors = array();
  3617. $errors = array();
  3618. $this->no_display_count = false;
  3619. $count = 0;
  3620.  
  3621. reset($fieldarray); // fix for version 4.4.1
  3622. if (is_string(key($fieldarray))) {
  3623. // array is NOT indexed by row, so adjust it
  3624. $fieldarray = array($fieldarray);
  3625. } // if
  3626.  
  3627. // turn off feature in getInitialData() method
  3628. $this->ignore_empty_fields = true;
  3629.  
  3630. if (empty($this->errors)) {
  3631. // perform any additional custom pre-processing
  3632. if (is_object($this->custom_processing_object)) {
  3633. if (method_exists($this->custom_processing_object, '_cm_pre_insertMultiple')) {
  3634. $fieldarray = $this->custom_processing_object->_cm_pre_insertMultiple($fieldarray);
  3635. } // if
  3636. } // if
  3637. if ($this->custom_replaces_standard) {
  3638. $this->custom_replaces_standard = false;
  3639. } else {
  3640. $fieldarray = $this->_cm_pre_insertMultiple($fieldarray);
  3641. } // if
  3642. } // if
  3643.  
  3644. if (!$this->errors) {
  3645. // insert each row one by one
  3646. foreach ($fieldarray as $rownum => $data) {
  3647. if (!empty($data)) {
  3648. $this->numrows = 0;
  3649. $fieldarray[$rownum] = $this->insertRecord($fieldarray[$rownum]);
  3650. if (!empty($this->errors)) {
  3651. // keep $errors separate for each row
  3652. $errors[$rownum] = $this->errors;
  3653. } else {
  3654. $count = $count + $this->numrows;
  3655. // if ($GLOBALS['mode'] == 'batch') {
  3656. // if ($count % 100 == 0) {
  3657. // echo "<p>$count records written</p>\n";
  3658. // } // if
  3659. // } // if
  3660. } // if
  3661. } // if
  3662. } // foreach
  3663.  
  3664. $this->errors = $errors;
  3665. $this->numrows = $count;
  3666.  
  3667. if (is_True($this->no_display_count)) {
  3668. // do not display record count
  3669. } else {
  3670. // 'X records were inserted into tablename'
  3671. $this->messages[] = $this->getLanguageText('sys0005', $count, strtoupper($this->tablename));
  3672. } // if
  3673.  
  3674. if (empty($this->errors)) {
  3675. // perform any additional custom post-processing
  3676. if (is_object($this->custom_processing_object)) {
  3677. if (method_exists($this->custom_processing_object, '_cm_post_insertMultiple')) {
  3678. $fieldarray = $this->custom_processing_object->_cm_post_insertMultiple($fieldarray);
  3679. } // if
  3680. } // if
  3681. if ($this->custom_replaces_standard) {
  3682. $this->custom_replaces_standard = false;
  3683. } else {
  3684. $fieldarray = $this->_cm_post_insertMultiple($fieldarray);
  3685. } // if
  3686. } // if
  3687.  
  3688. // reset $this->fieldarray which was set to a single row by insertRecord()
  3689. $this->fieldarray = $fieldarray;
  3690. } // if
  3691.  
  3692. $this->ignore_empty_fields = false;
  3693.  
  3694. return $fieldarray;
  3695.  
  3696. } // insertMultiple
  3697.  
  3698. // ****************************************************************************
  3699. function insertOrUpdate ($fieldarray)
  3700. // this will insert or update a group of records.
  3701. {
  3702. $this->errors = array();
  3703. $errors = array();
  3704.  
  3705. reset($fieldarray); // fix for version 4.4.1
  3706. if (is_string(key($fieldarray))) {
  3707. // array is NOT indexed by row, so adjust it
  3708. $fieldarray = array($fieldarray);
  3709. $is_assoc = true; // this is an associative array (single row)
  3710. } else {
  3711. $is_assoc = false;
  3712. } // if
  3713.  
  3714. if (is_object($this->custom_processing_object)) {
  3715. if (method_exists($this->custom_processing_object, '_cm_pre_insertOrUpdate')) {
  3716. $fieldarray = $this->custom_processing_object->_cm_pre_insertOrUpdate($fieldarray);
  3717. } // if
  3718. } // if
  3719. if ($this->custom_replaces_standard) {
  3720. $this->custom_replaces_standard = false;
  3721. } else {
  3722. $fieldarray = $this->_cm_pre_insertOrUpdate($fieldarray);
  3723. } // if
  3724. if ($this->errors) {
  3725. return $fieldarray;
  3726. } // if
  3727.  
  3728. // get array of fieldnames in the primary key
  3729. $pkeynames = $this->getPkeyNames();
  3730.  
  3731. $insert_count = 0;
  3732. $update_count = 0;
  3733. $unchange_count = 0;
  3734.  
  3735. foreach ($fieldarray as $rownum => $rowdata) {
  3736.  
  3737. // check if entire primary key (or candidate key) has been supplied
  3738. list($where, $errors) = isPkeyComplete($rowdata, $pkeynames, $this->unique_keys);
  3739. if (empty($where)) {
  3740. // not complete, so cannot perform lookup, record must be inserted
  3741. $count = 0;
  3742. $errors = array();
  3743. } else {
  3744. // find out if this record currently exists or not
  3745. $count = $this->getCount($where);
  3746. } // if
  3747.  
  3748. if ($count == 0) {
  3749. // record does not exist, so create it
  3750. $this->no_duplicate_error = true; // don't error if this is a duplicate
  3751. $rowdata = $this->insertRecord($rowdata);
  3752. if ($this->numrows > 0) {
  3753. $insert_count++;
  3754. } // if
  3755. } else {
  3756. // record already exists, so update it
  3757. $rowdata = $this->updateRecord($rowdata);
  3758. if ($this->numrows > 0) {
  3759. $update_count++;
  3760. } else {
  3761. $unchange_count++;
  3762. } // if
  3763. } // if
  3764. $this->no_duplicate_error = false;
  3765.  
  3766. if ($this->errors) {
  3767. if ($is_assoc) {
  3768. $errors = $this->errors;
  3769. } else {
  3770. $errors[$rownum] = $this->errors;
  3771. } // if
  3772. } // if
  3773.  
  3774. $fieldarray[$rownum] = $rowdata;
  3775.  
  3776. } // foreach
  3777.  
  3778. if (is_object($this->custom_processing_object)) {
  3779. if (method_exists($this->custom_processing_object, '_cm_post_insertOrUpdate')) {
  3780. $fieldarray = $this->custom_processing_object->_cm_post_insertOrUpdate($fieldarray, $insert_count, $update_count);
  3781. } // if
  3782. } // if
  3783. if ($this->custom_replaces_standard) {
  3784. $this->custom_replaces_standard = false;
  3785. } else {
  3786. $fieldarray = $this->_cm_post_insertOrUpdate($fieldarray, $insert_count, $update_count);
  3787. } // if
  3788.  
  3789. if (is_True($this->no_display_count)) {
  3790. // do not display record count
  3791. } else {
  3792. // "X records inserted, X records updated in <tablename>"
  3793. $this->messages = $this->getLanguageText('sys0098', $insert_count, $update_count, strtoupper($this->tablename));
  3794. } // if
  3795.  
  3796. $this->insert_count = $insert_count;
  3797. $this->update_count = $update_count;
  3798. $this->unchange_count = $unchange_count;
  3799. $this->errors = $errors;
  3800.  
  3801. if ($is_assoc) {
  3802. return $fieldarray[0]; // return an associative array
  3803. } else {
  3804. return $fieldarray; // return an indexed array
  3805. } // if
  3806.  
  3807. } // insertOrUpdate
  3808.  
  3809. // ****************************************************************************
  3810. function insertRecord ($fieldarray)
  3811. // insert a record using contents of $fieldarray.
  3812. {
  3813. $this->errors = array(); // initialise
  3814. $this->numrows = 0;
  3815.  
  3816. if (!empty($fieldarray)) {
  3817. reset($fieldarray); // fix for version 4.4.1
  3818. if (!is_string(key($fieldarray))) {
  3819. // input is indexed by row, so extract data for 1st row only
  3820. $fieldarray = $fieldarray[key($fieldarray)];
  3821. } // if
  3822. } // if
  3823.  
  3824. // shift all field names to lower case
  3825. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  3826.  
  3827. // do not allow auto-insert/auto-update fields to be pasted into an insert screen
  3828. foreach ($this->fieldspec as $field => $spec) {
  3829. if (array_key_exists('autoinsert', $spec) or array_key_exists('autoupdate', $spec)) {
  3830. unset($fieldarray[$field]);
  3831. } // if
  3832. } // foreach
  3833.  
  3834. if (!empty($this->initial_values)) {
  3835. // insert any initial values obtained from MNU_INITIAL_VALUE_ROLE/USER table
  3836. foreach ($this->initial_values as $key => $value) {
  3837. if (empty($fieldarray[$key])) {
  3838. // current value is empty, so overwrite with initial value
  3839. $fieldarray[$key] = $value;
  3840. } // if
  3841. } // foreach
  3842. } // if
  3843.  
  3844. //if ($this->initiated_from_controller) {
  3845. // deal with numbers in foreign formats
  3846. //$fieldarray = $this->unFormatNumber($fieldarray); // (NOTE: this is now done in array_update_associative() function)
  3847. // deal with datetime in different timezones
  3848. //$fieldarray = $this->convertTimeZone($fieldarray); // NOTE: now done AFTER _cm_pre_insertRecord() method
  3849. //} // if
  3850.  
  3851. // redo any custom initialisation
  3852. $this->sqlSelectInit();
  3853. if (is_object($this->custom_processing_object)) {
  3854. if (method_exists($this->custom_processing_object, '_cm_getInitialData')) {
  3855. $fieldarray = $this->custom_processing_object->_cm_getInitialData($fieldarray);
  3856. } // if
  3857. } // if
  3858. if ($this->custom_replaces_standard) {
  3859. $this->custom_replaces_standard = false;
  3860. } else {
  3861. $fieldarray = $this->_cm_getInitialData($fieldarray);
  3862. } // if
  3863.  
  3864. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  3865.  
  3866. if (empty($this->errors)) {
  3867. // perform any custom pre-insert processing
  3868. if (is_object($this->custom_processing_object)) {
  3869. if (method_exists($this->custom_processing_object, '_cm_pre_insertRecord')) {
  3870. $fieldarray = $this->custom_processing_object->_cm_pre_insertRecord($fieldarray);
  3871. } // if
  3872. } // if
  3873. if ($this->custom_replaces_standard) {
  3874. $this->custom_replaces_standard = false;
  3875. } else {
  3876. $fieldarray = $this->_cm_pre_insertRecord($fieldarray);
  3877. } // if
  3878. } // if
  3879.  
  3880. if ($this->initiated_from_controller === TRUE AND $this->no_convert_timezone === FALSE) {
  3881. if (!empty($fieldarray) AND !empty($GLOBALS['screen_structure'])) {
  3882. // deal with datetimes from screen input which may be in different timezone
  3883. $fieldarray = $this->convertTimeZone($fieldarray, $this->fieldspec);
  3884. } // if
  3885. } // if
  3886.  
  3887. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  3888.  
  3889. $insertarray = $fieldarray; // copy to temporary area
  3890.  
  3891. if (empty($this->errors) AND is_array($insertarray) AND !empty($insertarray)) {
  3892. // perform standard declarative checks on input array
  3893. // NOTE: this produces another array with data formatted for the database
  3894. $insertarray = $this->_validateInsert($insertarray);
  3895. // replace any fields which may have been modified during the validation process
  3896. $insertarray = array_merge($fieldarray, $insertarray);
  3897. } // if
  3898.  
  3899. if (empty($this->errors)) {
  3900. if ($this->skip_validation OR isset($insertarray['rdc_skip_validation'])) {
  3901. // do not perform any custom validation
  3902. } elseif (is_array($insertarray) AND !empty($insertarray)) {
  3903. // perform any custom pre-insert validation (1)
  3904. if (is_object($this->custom_processing_object)) {
  3905. if (method_exists($this->custom_processing_object, '_cm_commonValidation')) {
  3906. $insertarray = $this->custom_processing_object->_cm_commonValidation($insertarray, $insertarray);
  3907. } // if
  3908. } // if
  3909. if ($this->custom_replaces_standard) {
  3910. $this->custom_replaces_standard = false;
  3911. } else {
  3912. $insertarray = $this->_cm_commonValidation($insertarray, $insertarray);
  3913. } // if
  3914.  
  3915. if (empty($this->errors)) {
  3916. // perform any custom pre-insert validation (2)
  3917. if (is_object($this->custom_processing_object)) {
  3918. if (method_exists($this->custom_processing_object, '_cm_validateInsert')) {
  3919. $insertarray = $this->custom_processing_object->_cm_validateInsert($insertarray);
  3920. } // if
  3921. } // if
  3922. if ($this->custom_replaces_standard) {
  3923. $this->custom_replaces_standard = false;
  3924. } else {
  3925. $insertarray = $this->_cm_validateInsert($insertarray);
  3926. } // if
  3927. } // if
  3928. } // if
  3929. } // if
  3930.  
  3931. if (is_array($insertarray) AND !empty($insertarray)) {
  3932. $insertarray = array_change_key_case($insertarray, CASE_LOWER);
  3933. } // if
  3934.  
  3935. if (empty($this->errors)) {
  3936. if (is_array($insertarray) AND !empty($insertarray)) {
  3937. // perform any last minute adjustments
  3938. foreach ($this->fieldspec as $field => $spec) {
  3939. if (array_key_exists($field, $insertarray)) {
  3940. if (array_key_exists('autoinsert', $spec) OR array_key_exists('autoupdate', $spec)) {
  3941. // remove any autoinsert or autoupdate fields
  3942. unset($insertarray[$field]);
  3943. } // if
  3944. if (!empty($insertarray[$field])) {
  3945. if (preg_match('/(decimal|numeric|float|real|double)/i', $spec['type'])) {
  3946. // remove thousands separator and ensure decimal point is '.'
  3947. $insertarray[$field] = number_unformat($insertarray[$field], '.', ',');
  3948. if (array_key_exists('scale', $spec)) {
  3949. // round to the correct number of decimal places
  3950. $insertarray[$field] = number_format($insertarray[$field], $spec['scale'], '.', '');
  3951. } // if
  3952. } // if
  3953. } // if
  3954. } // if
  3955. } // foreach
  3956. // perform standard insert using validated data
  3957. $inserted = $this->_dml_insertRecord($insertarray);
  3958. // replace any non-database fields not included in the insert
  3959. $insertarray = array_merge($insertarray, $inserted);
  3960. } // if
  3961. } // if
  3962.  
  3963. // merge temporary area with original input
  3964. if (is_array($insertarray) AND !empty($insertarray)) {
  3965. $fieldarray = array_merge($fieldarray, $insertarray);
  3966. } // if
  3967.  
  3968. //if (empty($this->errors) AND is_array($insertarray) AND !empty($insertarray)) {
  3969. if (empty($this->errors)) {
  3970. // perform any custom post-insert processing
  3971. if (is_object($this->custom_processing_object)) {
  3972. if (method_exists($this->custom_processing_object, '_cm_post_insertRecord')) {
  3973. $fieldarray = $this->custom_processing_object->_cm_post_insertRecord($fieldarray);
  3974. } // if
  3975. } // if
  3976. if ($this->custom_replaces_standard) {
  3977. $this->custom_replaces_standard = false;
  3978. } else {
  3979. $fieldarray = $this->_cm_post_insertRecord($fieldarray);
  3980. } // if
  3981.  
  3982. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  3983.  
  3984. // if ($this->numrows > 0 AND !empty($this->alt_language_table) AND $_SESSION['logon_user_id'] != 'INTERNET') {
  3985. // // ensure that default entries exist for all supported languages
  3986. // $dbobject =& RDCsingleton::getInstance($this->alt_language_table);
  3987. // $data = array();
  3988. // $data = $dbobject->getLanguageEntries($data, $fieldarray, $this->alt_language_cols);
  3989. // if ($dbobject->errors) {
  3990. // //$this->errors = array_merge($this->errors, $dbobject->errors);
  3991. // $this->errors[$dbobject->getClassName()] = $dbobject->errors;
  3992. // } // if
  3993. // unset($dbobject);
  3994. // } // if
  3995. } // if
  3996.  
  3997. // turn this flag off
  3998. $this->skip_validation = FALSE;
  3999.  
  4000. // store updated $fieldarray within this object
  4001. $this->fieldarray = $fieldarray;
  4002.  
  4003. return $fieldarray;
  4004.  
  4005. } // insertRecord
  4006.  
  4007. // ****************************************************************************
  4008. function multiQuery ($query)
  4009. // process one or more SQL queries in one go.
  4010. // $query may be a string (single query) or an array (multiple queries).
  4011. {
  4012. $result = $this->executeQuery($query);
  4013.  
  4014. return $result;
  4015.  
  4016. } // multiQuery
  4017.  
  4018. // ****************************************************************************
  4019. function popupCall (&$popupname, $where, &$script_vars, $fieldarray, &$settings)
  4020. // processing before a popup form is called.
  4021. // NOTE: $popupname is passed BY REFERENCE as it may be altered.
  4022. // NOTE: $script_vars is passed BY REFERENCE as it may be altered.
  4023. {
  4024. // clear any previous selection
  4025. $script_vars['selection'] = NULL;
  4026.  
  4027. // the default is to select only one entry
  4028. $settings_array['select_one'] = true;
  4029.  
  4030. if (!empty($where)) {
  4031. $where_array = where2array($where);
  4032. foreach ($where_array as $where_field => $where_value) {
  4033. if (!isset($fieldarray[$where_field]) OR empty($fieldarray[$where_field])) {
  4034. $fieldarray[$where_field] = $where_value;
  4035. } // if
  4036. } // foreach
  4037. } // if
  4038.  
  4039. // allow $where and $settings to be altered
  4040. $popupname = strtolower($popupname);
  4041. if (is_object($this->custom_processing_object)) {
  4042. // call method which is specific to current project
  4043. if (method_exists($this->custom_processing_object, '_cm_popupCall')) {
  4044. $where = $this->custom_processing_object->_cm_popupCall($popupname, $where, $fieldarray, $settings_array);
  4045. } // if
  4046. } // if
  4047. if ($this->custom_replaces_standard) {
  4048. $this->custom_replaces_standard = false;
  4049. } else {
  4050. // call standard method
  4051. $where = $this->_cm_popupCall($popupname, $where, $fieldarray, $settings_array);
  4052. } // if
  4053.  
  4054. //$script_vars['where'] = $where; // do NOT update this value
  4055.  
  4056. $settings = '';
  4057. // convert $settings array into a string
  4058. foreach ($settings_array as $key => $value) {
  4059. if (is_bool($value)) {
  4060. if ($value === true) {
  4061. $value = 'TRUE';
  4062. } else {
  4063. $value = 'FALSE';
  4064. } // if
  4065. } // if
  4066. if (empty($settings)) {
  4067. $settings = "$key=$value";
  4068. } else {
  4069. $settings .= "&$key=$value";
  4070. } // if
  4071. } // foreach
  4072.  
  4073. return $where;
  4074.  
  4075. } // popupCall
  4076.  
  4077. // ****************************************************************************
  4078. function popupReturn ($fieldarray, $return_from, $selection, $popup_offset=null)
  4079. // process a selection returned from a popup screen.
  4080. // $fieldarray contains the record data when the popup button was pressed.
  4081. // $return_from identifies which popup screen was called.
  4082. // $selection contains a string identifying what was selected in that popup screen.
  4083. {
  4084. $this->errors = array();
  4085.  
  4086. $return_from = strtolower($return_from);
  4087.  
  4088. reset($fieldarray); // fix for version 4.4.1
  4089. if (!empty($fieldarray) and !is_string(key($fieldarray))) {
  4090. if (is_null($popup_offset)) {
  4091. // extract first row
  4092. $single_row = $fieldarray[key($fieldarray)];
  4093. $popup_offset = key($fieldarray)+1;
  4094. } else {
  4095. // extract specified row
  4096. $single_row = $fieldarray[$popup_offset-1];
  4097. } // if
  4098. } else {
  4099. // not indexed by row, so use entire array
  4100. $single_row = $fieldarray;
  4101. } // if
  4102.  
  4103. if (substr_count($selection, '=') == 0) {
  4104. $found = false;
  4105. // selection is not in format 'key=value', so it must be from a filepicker
  4106. foreach ($this->fieldspec as $field => $spec) {
  4107. if (isset($spec['task_id'])) {
  4108. if ($spec['task_id'] == $return_from) {
  4109. $found = true;
  4110. // now empty the description field obtained from the foreign table
  4111. $single_row[$field] = $selection;
  4112. break;
  4113. } // if
  4114. } // if
  4115. } // foreach
  4116. if ($found) {
  4117. // deal with any processing after a value has been returned
  4118. $select_array[$field] = $selection;
  4119. if (is_object($this->custom_processing_object)) {
  4120. if (method_exists($this->custom_processing_object, '_cm_popupReturn')) {
  4121. // call method which is specific to current project
  4122. $single_row = $this->custom_processing_object->_cm_popupReturn($single_row, $return_from, $select_array);
  4123. } // if
  4124. } // if
  4125. if ($this->custom_replaces_standard) {
  4126. $this->custom_replaces_standard = false;
  4127. } else {
  4128. // call standard method
  4129. $single_row = $this->_cm_popupReturn($single_row, $return_from, $select_array);
  4130. } // if
  4131. // store updated $fieldarray within this object
  4132. $this->fieldarray = $single_row;
  4133. } // if
  4134. return $single_row;
  4135. } // if
  4136.  
  4137. // convert selection string into an associative array
  4138. $select_array = where2array($selection);
  4139.  
  4140. // find entry in $fieldspec which uses this popup form
  4141. $found = false;
  4142. foreach ($this->fieldspec as $field => $spec) {
  4143. if (isset($spec['task_id'])) {
  4144. if ($spec['task_id'] == $return_from) {
  4145. $found = true;
  4146. if (isset($spec['foreign_field'])) {
  4147. // remove the description field obtained from the foreign table
  4148. unset($single_row[$spec['foreign_field']]);
  4149. } // if
  4150. // deal with any processing after a value has been returned
  4151. if (is_object($this->custom_processing_object)) {
  4152. if (method_exists($this->custom_processing_object, '_cm_popupReturn')) {
  4153. // call method which is specific to current project
  4154. $single_row = $this->custom_processing_object->_cm_popupReturn($single_row, $return_from, $select_array);
  4155. } // if
  4156. } // if
  4157. if ($this->custom_replaces_standard) {
  4158. $this->custom_replaces_standard = false;
  4159. } else {
  4160. // call standard method
  4161. $single_row = $this->_cm_popupReturn($single_row, $return_from, $select_array);
  4162. } // if
  4163.  
  4164. // look for any differences between the fieldname(s) returned by the popup
  4165. // and the fieldname(s) used in this table
  4166. foreach ($this->parent_relations as $parent) {
  4167. if (array_key_exists($field, $parent['fields'])) {
  4168. foreach ($parent['fields'] as $fld_child => $fld_parent) {
  4169. if ($fld_child != $fld_parent) {
  4170. if (isset($select_array[$fld_parent])) {
  4171. // convert the parent field name to the child field name
  4172. $select_array[$fld_child] = $select_array[$fld_parent];
  4173. unset($select_array[$fld_parent]);
  4174. } // if
  4175. } // if
  4176. } // foreach
  4177. break;
  4178. } // if
  4179. } // foreach
  4180. // merge $selection with $fieldarray
  4181. $single_row = array_merge($single_row, $select_array);
  4182. break;
  4183. } // if
  4184. } // if
  4185. } // foreach
  4186.  
  4187. if ($found) {
  4188. if ($GLOBALS['mode'] == 'insert') {
  4189. // redo any custom initialisation
  4190. $this->sqlSelectInit();
  4191. if (is_object($this->custom_processing_object)) {
  4192. if (method_exists($this->custom_processing_object, '_cm_getInitialData')) {
  4193. $single_row = $this->custom_processing_object->_cm_getInitialData($single_row);
  4194. } // if
  4195. } // if
  4196. if ($this->custom_replaces_standard) {
  4197. $this->custom_replaces_standard = false;
  4198. } else {
  4199. $single_row = $this->_cm_getInitialData($single_row);
  4200. } // if
  4201. } // if
  4202.  
  4203. $single_row = array_change_key_case($single_row, CASE_LOWER);
  4204.  
  4205. // retrieve data from foreign (parent) tables
  4206. $single_row = $this->getForeignData($single_row);
  4207.  
  4208. if ($GLOBALS['mode'] != 'search') {
  4209. // perform any post-popup processing
  4210. if (is_object($this->custom_processing_object)) {
  4211. if (method_exists($this->custom_processing_object, '_cm_post_popupReturn')) {
  4212. $single_row = $this->custom_processing_object->_cm_post_popupReturn($single_row, $return_from, $select_array);
  4213. } // if
  4214. } // if
  4215. if ($this->custom_replaces_standard) {
  4216. $this->custom_replaces_standard = false;
  4217. } else {
  4218. $single_row = $this->_cm_post_popupReturn($single_row, $return_from, $select_array);
  4219. } // if
  4220. } // if
  4221. } // if
  4222.  
  4223. $single_row = array_change_key_case($single_row, CASE_LOWER);
  4224.  
  4225. if (!empty($fieldarray) and !is_string(key($fieldarray))) {
  4226. // insert sigle row into array
  4227. $fieldarray[$popup_offset-1] = $single_row;
  4228. } else {
  4229. // not inexed by row, so replace entire array
  4230. $fieldarray = $single_row;
  4231. } // if
  4232.  
  4233. // see if any additional data is required or needs to be changed
  4234. $fieldarray = $this->getExtraData($fieldarray);
  4235.  
  4236. // store updated $fieldarray within this object
  4237. $this->fieldarray = $fieldarray;
  4238.  
  4239. return $fieldarray;
  4240.  
  4241. } // popupReturn
  4242.  
  4243. // ****************************************************************************
  4244. function post_fileUpload ($filename, $filesize)
  4245. // perform processing after a file has been uploaded.
  4246. {
  4247. $this->errors = array();
  4248.  
  4249. if (is_object($this->custom_processing_object)) {
  4250. if (method_exists($this->custom_processing_object, '_cm_post_fileUpload')) {
  4251. $this->custom_processing_object->resize_array = $this->resize_array;
  4252. $this->custom_processing_object->upload_subdir = $this->upload_subdir;
  4253. $this->custom_processing_object->upload_filetypes = $this->upload_filetypes;
  4254. $this->custom_processing_object->upload_maxfilesize = $this->upload_maxfilesize;
  4255. $filename = $this->custom_processing_object->_cm_post_fileUpload($filename, $filesize);
  4256. } // if
  4257. } // if
  4258. if ($this->custom_replaces_standard) {
  4259. $this->custom_replaces_standard = false;
  4260. } else {
  4261. $filename = $this->_cm_post_fileUpload($filename, $filesize);
  4262. } // if
  4263.  
  4264. return $filename;
  4265.  
  4266. } // post_fileUpload
  4267.  
  4268. // ****************************************************************************
  4269. function post_search ($search, $selection)
  4270. // perform final processing before $search is returned to the calling program
  4271. {
  4272. $this->errors = array();
  4273.  
  4274. if (is_object($this->custom_processing_object)) {
  4275. if (method_exists($this->custom_processing_object, '_cm_post_search')) {
  4276. $search = $this->custom_processing_object->_cm_post_search($search, $selection);
  4277. } // if
  4278. } // if
  4279.  
  4280. if ($this->custom_replaces_standard) {
  4281. $this->custom_replaces_standard = false;
  4282. } else {
  4283. $search = $this->_cm_post_search($search, $selection);
  4284. } // if
  4285.  
  4286. return $search;
  4287.  
  4288. } // post_search
  4289.  
  4290. // ****************************************************************************
  4291. function reInitialise ($fieldarray, $where)
  4292. // re-initialise $fieldarray after previous insert
  4293. {
  4294. // nullify all fields identified in $fieldspec
  4295. foreach ($this->fieldspec as $fieldname => $spec) {
  4296. $fieldarray[$fieldname] = NULL;
  4297. } // foreach
  4298.  
  4299. $this->fieldarray = $fieldarray;
  4300.  
  4301. return $fieldarray;
  4302.  
  4303. } // reInitialise
  4304.  
  4305. // ****************************************************************************
  4306. function reset ($where=null, $keep_orderby=false)
  4307. // reset all screen settings before starting afresh.
  4308. {
  4309. $this->setSqlSearch(null);
  4310.  
  4311. if (!is_True($keep_orderby)) {
  4312. $this->setOrderBy(null);
  4313. $this->setOrderBySeq(null);
  4314. } // if
  4315.  
  4316. $this->fieldarray = array();
  4317. $null = $this->initialise($where);
  4318.  
  4319. $this->setPageNo(1);
  4320.  
  4321. $this->_cm_reset($where);
  4322.  
  4323. return $where;
  4324.  
  4325. } // reset
  4326.  
  4327. // ****************************************************************************
  4328. function restart ($return_from, $return_action, $return_string=null)
  4329. // script is being restarted after running a child form, so check for further action.
  4330. {
  4331. $pattern_id = getPatternId();
  4332. $zone = $this->zone;
  4333.  
  4334. if (is_object($this->custom_processing_object)) {
  4335. if (method_exists($this->custom_processing_object, '_cm_restart')) {
  4336. $this->custom_processing_object->_cm_restart($pattern_id, $zone, $return_from, $return_action, $return_string);
  4337. } // if
  4338. } // if
  4339.  
  4340. if ($this->custom_replaces_standard) {
  4341. $this->custom_replaces_standard = false;
  4342. } else {
  4343. $this->_cm_restart($pattern_id, $zone, $return_from, $return_action, $return_string);
  4344. } // if
  4345.  
  4346. return;
  4347.  
  4348. } // restart
  4349.  
  4350. // ****************************************************************************
  4351. function rollback ()
  4352. // rollback this transaction due to some sort of error.
  4353. {
  4354. // remove entries created by this task
  4355. removeFromScriptSequence();
  4356.  
  4357. $DML =& $this->_getDBMSengine($this->dbname);
  4358.  
  4359. $result = $DML->rollback($this->dbname_server);
  4360.  
  4361. $GLOBALS['transaction_has_started'] = FALSE;
  4362.  
  4363. return $result;
  4364.  
  4365. } // rollback
  4366.  
  4367. // ****************************************************************************
  4368. function scriptNext ($task_id, $where=null, $selection=null, $task_array=array())
  4369. // suspend the current task before juming to a new task.
  4370. {
  4371. if ($GLOBALS['transaction_has_started'] == TRUE) {
  4372. $errors = $this->commit();
  4373. if ($errors) {
  4374. $this->rollback();
  4375. return false;
  4376. } // if
  4377. } // if
  4378.  
  4379. scriptNext($task_id, $where, $selection, $task_array);
  4380.  
  4381. } // scriptNext
  4382.  
  4383. // ****************************************************************************
  4384. function scriptPrevious ($errors=null, $messages=NULL, $action=NULL, $instruction=NULL)
  4385. // go back to the previous script in the current hierarchy.
  4386. {
  4387. if ($GLOBALS['transaction_has_started'] == TRUE) {
  4388. $errors = $this->commit();
  4389. if ($errors) {
  4390. $this->rollback();
  4391. return false;
  4392. } // if
  4393. } // if
  4394.  
  4395. scriptPevious($errors, $messages, $action, $instruction);
  4396.  
  4397. } // scriptPrevious
  4398.  
  4399. // ****************************************************************************
  4400. function selectDB ($dbname)
  4401. // select a different database via the current connection.
  4402. {
  4403. $DML =& $this->_getDBMSengine($this->dbname);
  4404.  
  4405. $result = $DML->selectDB($dbname);
  4406.  
  4407. return $result;
  4408.  
  4409. } // selectDB
  4410.  
  4411. // ****************************************************************************
  4412. function setAction ($action)
  4413. // process the designated action within the current object.
  4414. {
  4415. $this->errors = array();
  4416.  
  4417. switch (strtolower($action)){
  4418. case 'selectall':
  4419. foreach ($this->fieldarray as $row => $data) {
  4420. if (!empty($data)) {
  4421. $this->fieldarray[$row]['selected'] = true;
  4422. } // if
  4423. } // foreach
  4424. break;
  4425. case 'unselectall':
  4426. foreach ($this->fieldarray as $row => $data) {
  4427. if (!empty($data)) {
  4428. $this->fieldarray[$row]['selected'] = false;
  4429. } // if
  4430. } // foreach
  4431. break;
  4432. default:
  4433. $this->errors[] = $this->getLanguageText('sys0012'); // 'setAction: 2nd parameter is unknown action'
  4434. } // switch
  4435.  
  4436. return $this->fieldarray;
  4437.  
  4438. } // setAction
  4439.  
  4440. // ****************************************************************************
  4441. function setChildData ($data)
  4442. // return $fieldarray from the parent object.
  4443. {
  4444. if (!is_object($this->child_object)) {
  4445. return FALSE;
  4446. } elseif (!method_exists($this->child_object, 'setFieldArray')) {
  4447. return FALSE;
  4448. } // if
  4449.  
  4450. $this->child_object->setFieldArray($data);
  4451.  
  4452. return true;
  4453.  
  4454. } // setChildData
  4455.  
  4456. // ****************************************************************************
  4457. function setChildObject (&$childOBJ)
  4458. // insert a reference to this object's child in the current task.
  4459. {
  4460. if (is_object($childOBJ)) {
  4461. $this->child_object =& $childOBJ;
  4462. } // if
  4463.  
  4464. return;
  4465.  
  4466. } // setChildObject
  4467.  
  4468. // ****************************************************************************
  4469. function setCurrentOrHistoric ()
  4470. // this table contains fields START_DATE and END_DATE, so insert into search
  4471. // screen a dropdown list to select 'current', 'historic' or 'all' dates.
  4472. {
  4473.  
  4474. // create array of options and and put into LOOKUP_DATA
  4475. //$array['C'] = 'Current';
  4476. //$array['H'] = 'Historic';
  4477. //$array['F'] = 'Future';
  4478. $array = $this->getLanguageArray('curr_or_hist');
  4479. $this->lookup_data['curr_or_hist'] = $array;
  4480.  
  4481. // insert field into $fieldspec
  4482. $this->fieldspec['curr_or_hist'] = array('type' => 'string',
  4483. 'control' => 'dropdown',
  4484. 'optionlist' => 'curr_or_hist');
  4485. return;
  4486.  
  4487. } // setCurrentOrHistoric
  4488.  
  4489. // ****************************************************************************
  4490. function setDefaultOrderBy ($sql_orderby='')
  4491. // this allows a default sort order to be specified (see getData)
  4492. {
  4493. // only set if non-null value is given
  4494. if (!empty($sql_orderby)) {
  4495. $this->default_orderby_task = trim(strtolower($sql_orderby));
  4496. $this->sql_orderby_seq = $this->getOrderBySeq($sql_orderby);
  4497. } // if
  4498.  
  4499. return;
  4500.  
  4501. } // setDefaultOrderBy
  4502.  
  4503. // ****************************************************************************
  4504. function setFieldAccess ()
  4505. // get contents of ROLE_TASKFIELD for this role/task.
  4506. // this identifies if access to certain fields should be turned off.
  4507. {
  4508. $this->errors = array();
  4509. $array = array();
  4510.  
  4511. // MNU_ROLE_TASKFIELD contains a list of fields for the current task
  4512. // which may have the default ACCESS_TYPE altered for the current role.
  4513.  
  4514. // first we must obtain the user's current role setting
  4515. $dbrole =& RDCsingleton::getInstance('mnu_role');
  4516. $dbrole_data = $dbrole->getRole($_SESSION['logon_user_id']);
  4517. if ($dbrole->errors) {
  4518. $this->errors = $dbrole->errors;
  4519. return FALSE;
  4520. } // if
  4521. unset($dbrole);
  4522.  
  4523. $role_id = $dbrole_data['role_id'];
  4524. $role_list = $dbrole_data['role_list'];
  4525. $global_access = $dbrole_data['global_access'];
  4526.  
  4527. // If the security class has GLOBAL_ACCESS = 'y' there are no restrictions.
  4528. if (is_True($global_access)) return $array;
  4529.  
  4530. $dbobject =& RDCsingleton::getInstance('mnu_role_taskfield');
  4531.  
  4532. $dbobject->sql_select = 'role_id,task_id,field_id,access_type';
  4533. $dbobject->sql_from = 'mnu_role_taskfield ';
  4534. $dbobject->sql_where = "mnu_role_taskfield.role_id IN($role_list)";
  4535.  
  4536. $dbobject->sql_orderby = '';
  4537. $PHP_SELF = getSelf(); // reduce PHP_SELF to '/dir/file.php'
  4538. $where = "task_id='" .$_SESSION['pages'][$PHP_SELF]['task_id'] ."'";
  4539.  
  4540. $accessarray = $dbobject->getData_raw($where);
  4541. $this->errors = $dbobject->getErrors();
  4542. unset($dbobject);
  4543.  
  4544. // $accessarray contains a separate row for each field which must now be
  4545. // reduced to an associative array of 'field_id=access_type'
  4546. $array = array();
  4547. foreach ($accessarray as $row => $rowdata) {
  4548. $fieldname = strtolower($rowdata['field_id']);
  4549. $fieldvalue = strtolower($rowdata['access_type']);
  4550. // set access type for the field
  4551. switch ($fieldvalue) {
  4552. case 'ned':
  4553. $array[$fieldname] = 'noedit';
  4554. break;
  4555. case 'ndi':
  4556. $array[$fieldname] = 'nodisplay';
  4557. break;
  4558. default:
  4559. // ignore if access_type='full' (no restrictions)
  4560. } // switch
  4561. } // foreach
  4562.  
  4563. $this->field_access = $array;
  4564.  
  4565. return $array;
  4566.  
  4567. } // setFieldAccess
  4568.  
  4569. // ****************************************************************************
  4570. function setFieldArray ($fieldarray, $reset_pageno=true)
  4571. // this allows the current data array to be set or replaced.
  4572. {
  4573. if (empty($fieldarray)) {
  4574. $this->fieldarray = array();
  4575. } else {
  4576. reset($fieldarray); // fix for version 4.4.1
  4577. if (!is_string(key($fieldarray))) {
  4578. // input is indexed by row, so use it 'as is'
  4579. $this->fieldarray = $fieldarray;
  4580. } else {
  4581. // input is not indexed by row, so make it row zero
  4582. $this->fieldarray = array($fieldarray);
  4583. } // if
  4584. } // if
  4585.  
  4586. $this->numrows = count($this->fieldarray);
  4587.  
  4588. if ($this->numrows == 0) {
  4589. if ($reset_pageno === true) {
  4590. $this->pageno = 0;
  4591. $this->lastpage = 0;
  4592. } // if
  4593. } // if
  4594.  
  4595. return $this->fieldarray;
  4596.  
  4597. } // setFieldArray
  4598.  
  4599. // ****************************************************************************
  4600. function setInstruction ($instruction)
  4601. // load an optional instruction from the previous script.
  4602. {
  4603. $this->instruction = $instruction;
  4604.  
  4605. // process any instruction to expand a tree node
  4606. if (array_key_exists('expand', $instruction)) {
  4607. $this->expanded[$instruction['expand']] = true;
  4608. unset($instruction['expand']);
  4609. } // if
  4610.  
  4611. return;
  4612.  
  4613. } // setInstruction
  4614.  
  4615. // ****************************************************************************
  4616. function setLookupData ($input=null)
  4617. // fetch any lookup data and load into member variable.
  4618. {
  4619. // $input may be an array or a string
  4620. if (is_array($input)) {
  4621. reset($input); // fix for version 4.4.1
  4622. if (!empty($input) and !is_string(key($input))) {
  4623. // indexed by row, so use only row zero
  4624. $fieldarray = $input[key($input)];
  4625. } else {
  4626. $fieldarray = $input;
  4627. } // if
  4628. // convert into string after removing non-Pkey fields
  4629. $where = array2where($fieldarray, $this->getPkeyNames());
  4630. } else {
  4631. if (!empty($input)) {
  4632. // convert from string to an associative array
  4633. $fieldarray = where2array($input, false, false);
  4634. // convert back into string after removing non-Pkey fields
  4635. $where = array2where($fieldarray, $this->getPkeyNames());
  4636. } else {
  4637. $fieldarray = array();
  4638. $where = null;
  4639. } // if
  4640. } // if
  4641.  
  4642. // change current table configuration (optional)
  4643. if (is_object($this->custom_processing_object)) {
  4644. if (method_exists($this->custom_processing_object, '_cm_changeConfig')) {
  4645. $fieldarray = $this->custom_processing_object->_cm_changeConfig($where, $fieldarray);
  4646. } // if
  4647. } // if
  4648. if ($this->custom_replaces_standard) {
  4649. $this->custom_replaces_standard = false;
  4650. } else {
  4651. $fieldarray = $this->_cm_changeConfig($where, $fieldarray);
  4652. } // if
  4653.  
  4654. // see if any additional data is required or needs to be changed
  4655. $fieldarray = $this->_cm_getExtraData($where, $fieldarray);
  4656.  
  4657. return $fieldarray;
  4658.  
  4659. } // setLookupData
  4660.  
  4661. // ****************************************************************************
  4662. function setOrderBy ($sql_orderby, $sql_orderby_seq=null, $toggle=true)
  4663. // this allows a sort order to be changed by the user (see getData)
  4664. {
  4665. $this->sql_orderby = trim(strtolower($sql_orderby));
  4666.  
  4667. if (empty($this->sql_orderby)) {
  4668. $this->sql_orderby_seq = NULL;
  4669. $this->prev_sql_orderby = NULL;
  4670. return;
  4671. } // if
  4672.  
  4673. // reduce orderby from 'table.column, table.column, ...' to a single column name
  4674. $test_orderby = reduceOrderBy($sql_orderby);
  4675. $this->prev_sql_orderby = reduceOrderBy($this->prev_sql_orderby);
  4676.  
  4677. if ($test_orderby != $this->prev_sql_orderby) {
  4678. // column name has changed, so reset sequence to 'ASC'
  4679. $this->sql_orderby_seq = 'asc';
  4680. } else {
  4681. // toggle 'orderby_seq' between 'asc' and 'desc'
  4682. if (empty($this->sql_orderby_seq) OR $toggle === false) {
  4683. $this->sql_orderby_seq = $sql_orderby_seq;
  4684.  
  4685. } elseif (empty($sql_orderby_seq) OR $sql_orderby_seq == 'asc') {
  4686. $this->sql_orderby_seq = 'desc';
  4687. } else {
  4688. $this->sql_orderby_seq = 'asc';
  4689. } // if
  4690. } // if
  4691.  
  4692. return;
  4693.  
  4694. } // setOrderBy
  4695.  
  4696. // ****************************************************************************
  4697. function setOrderBySeq ($sql_orderby_seq)
  4698. // this allows a sort sequence ('asc' or 'desc') to be set (see getData)
  4699. {
  4700. $this->sql_orderby_seq = trim($sql_orderby_seq);
  4701.  
  4702. return;
  4703.  
  4704. } // setOrderBySeq
  4705.  
  4706. // ****************************************************************************
  4707. function setPageNo ($pageno=null)
  4708. // this allows a particular page number to be selected (see getData)
  4709. {
  4710. if (empty($pageno)) {
  4711. $this->pageno = 1;
  4712. } else {
  4713. $this->pageno = abs((int)$pageno);
  4714. } // if
  4715.  
  4716. // a new page has been selected, so clear what was selected on the previous page
  4717. $this->select_string = null;
  4718.  
  4719. return;
  4720.  
  4721. } // setPageNo
  4722.  
  4723. // ****************************************************************************
  4724. function setParentData ($data)
  4725. // return $fieldarray from the parent object.
  4726. {
  4727. if (!is_object($this->parent_object)) {
  4728. return FALSE;
  4729. } elseif (!method_exists($this->parent_object, 'setFieldArray')) {
  4730. return FALSE;
  4731. } // if
  4732.  
  4733. $this->parent_object->setFieldArray($data);
  4734.  
  4735. return true;
  4736.  
  4737. } // setParentData
  4738.  
  4739. // ****************************************************************************
  4740. function setParentObject (&$parentOBJ)
  4741. // insert a reference to this object's parent in the current task.
  4742. {
  4743. if (is_object($parentOBJ)) {
  4744. $this->parent_object =& $parentOBJ;
  4745. } // if
  4746.  
  4747. return;
  4748.  
  4749. } // setParentObject
  4750.  
  4751. // ****************************************************************************
  4752. function setRowsPerPage ($rows_per_page)
  4753. // this allows the default value to be changed
  4754. {
  4755. $this->rows_per_page = abs((int)$rows_per_page);
  4756.  
  4757. return;
  4758.  
  4759. } // setRowsPerPage
  4760.  
  4761. // ****************************************************************************
  4762. function setScrollArray ($where)
  4763. // construct an array of primary keys using the contents of $where
  4764. {
  4765. // convert $where (string) into an array of 'name=value' pairs
  4766. $wherearray = where2array($where);
  4767.  
  4768. // call custom method to construct $this->scrollarray
  4769. $array = $this->_cm_setScrollArray($where, $wherearray);
  4770.  
  4771. //$array = array_unique($array); // remove duplicates
  4772.  
  4773. // shift entries so that they start at position 1 not 0
  4774. array_unshift($array, 'dummy');
  4775. unset($array[0]);
  4776.  
  4777. // save this array for use during this object's life
  4778. $this->scrollarray = $array;
  4779.  
  4780. if ($this->pageno < 1) {
  4781. $this->pageno = 1;
  4782. } // if
  4783.  
  4784. // replace $where with details from 1st entry in scrollarray
  4785. if (is_array($this->scrollarray[$this->pageno])) {
  4786. $where = array2where($this->scrollarray[$this->pageno]);
  4787. } else {
  4788. $where = $this->scrollarray[$this->pageno];
  4789. } // if
  4790.  
  4791. // set initial values to be used by scrolling logic
  4792. $this->scrollindex = $this->pageno;
  4793. $this->numrows = count($this->scrollarray);
  4794. $this->lastpage = count($this->scrollarray);
  4795.  
  4796. return $where;
  4797.  
  4798. } // setScrollArray
  4799.  
  4800. // ****************************************************************************
  4801. function setScrollIndex ($index='1')
  4802. // this allows a particular index number to be selected (see getData)
  4803. {
  4804. $this->scrollindex = abs((int)$index);
  4805.  
  4806. return;
  4807.  
  4808. } // setScrollIndex
  4809.  
  4810. // ****************************************************************************
  4811. function setSelectedRows ($select_string, $rows)
  4812. // mark any rows as 'selected' if pkey exists in select string
  4813. {
  4814. $select_array = splitWhereByRow($select_string);
  4815. foreach ($select_array as $index => $string) {
  4816. $array1 = where2array($string); // convert string to array
  4817. $select_array[$index] = $array1; // replace string with array
  4818. } // foreach
  4819.  
  4820. // now compare each row of data with $select_array
  4821. foreach ($rows as $rownum => $rowdata) {
  4822. if (empty($select_array)) {
  4823. break; // no entries left, so exit
  4824. } // if
  4825. foreach ($select_array as $select_row => $select_array2) {
  4826. $found = false;
  4827. foreach ($select_array2 as $select_name => $select_value) {
  4828. if (!array_key_exists($select_name, $rowdata)) {
  4829. // this must be a dummy field, so ignore it
  4830. } else {
  4831. if ($rowdata[$select_name] == $select_value) {
  4832. $found = true;
  4833. } else {
  4834. $found = false;
  4835. break;
  4836. } // if
  4837. } // if
  4838. } // foreach
  4839. if ($found == true) {
  4840. // data matches selection, so mark this row as 'selected'
  4841. $rows[$rownum]['selected'] = true;
  4842. unset($select_array[$select_row]);
  4843. break;
  4844. } // if
  4845. } // foreach
  4846. } // foreach
  4847.  
  4848. return $rows;
  4849.  
  4850. } // setSelectedRows
  4851.  
  4852. // ****************************************************************************
  4853. function setSqlSearch ($sql_search=null, $save=false)
  4854. // set additional criteria to be used in sql select
  4855. {
  4856. $this->sql_search = $sql_search;
  4857. $this->sql_search_orig = $sql_search;
  4858.  
  4859. // this causes following variables to be reset
  4860. $this->pageno = 1;
  4861. $this->sql_having = null;
  4862.  
  4863. // new selection criteria has been entered, so clear what was selected previously
  4864. $this->select_string = null;
  4865.  
  4866. if (!empty($sql_search) AND $save == true) {
  4867. // save this so that it appears in the search screen
  4868. if (!empty($this->sql_search_table)) {
  4869. $_SESSION['search'][$this->sql_search_table] = $sql_search;
  4870. } else {
  4871. $_SESSION['search'][$this->tablename] = $sql_search;
  4872. } // if
  4873. } // if
  4874.  
  4875. return;
  4876.  
  4877. } // setSqlSearch
  4878.  
  4879. // ****************************************************************************
  4880. function setSqlGroupBy ($sql_groupby=null)
  4881. // set additional criteria to be used in sql select
  4882. {
  4883. $this->sql_groupby = trim($sql_groupby);
  4884.  
  4885. return;
  4886.  
  4887. } // setSqlSearch
  4888.  
  4889. // ****************************************************************************
  4890. function setSqlWhere ($sql_where)
  4891. // set additional criteria to be used with sql where
  4892. {
  4893. if (empty($this->sql_where)) {
  4894. $this->sql_where = $sql_where;
  4895. } else {
  4896. $this->sql_where .= ' AND ' .$sql_where;
  4897. } // if
  4898.  
  4899. return;
  4900.  
  4901. } // setSqlWhere
  4902.  
  4903. // ****************************************************************************
  4904. // function setSelectArray ($selection)
  4905. // // set optional selection criteria to be used in sql select
  4906. // {
  4907. // if (is_array($selection)) {
  4908. // // use only 1st element of this array
  4909. // $this->selectarray = $selection[key($selection)];
  4910. // } else {
  4911. // // convert string to an associative array
  4912. // $this->selectarray = where2array($selection);
  4913. // } // if
  4914. //
  4915. // } // setSelectArray
  4916.  
  4917. // ****************************************************************************
  4918. function sqlSelectDefault ()
  4919. // set components of the sql SELECT statement to their default values using
  4920. // the contents of $this->parent_relations.
  4921. {
  4922. $save_sql_no_foreign_db = $this->sql_no_foreign_db;
  4923. $this->sqlSelectInit();
  4924. $this->sql_no_foreign_db = $save_sql_no_foreign_db;
  4925.  
  4926. $this->sql_from = $this->_sqlForeignJoin($this->sql_select, $this->sql_from, $this->parent_relations);
  4927.  
  4928. $this->access_count = 1;
  4929.  
  4930. return;
  4931.  
  4932. } // sqlSelectDefault
  4933.  
  4934. // ****************************************************************************
  4935. function sqlSelectInit ()
  4936. // initialise all variables used to construct the sql SELECT statement.
  4937. {
  4938. $this->sql_select = null;
  4939. $this->sql_from = null;
  4940. $this->sql_where = null;
  4941. $this->sql_union = null;
  4942. $this->sql_groupby = null;
  4943. $this->sql_orderby = null;
  4944. $this->sql_orderby_seq = null;
  4945. $this->sql_having = null;
  4946. $this->sql_search = null;
  4947. $this->sql_search_orig = null;
  4948. $this->sql_search_table = null;
  4949. $this->pageno = null;
  4950. //$this->rows_per_page = null;
  4951. $this->access_count = null;
  4952. //$this->sql_no_foreign_db = false;
  4953.  
  4954. return;
  4955.  
  4956. } // sqlSelectInit
  4957.  
  4958. // ****************************************************************************
  4959. function startTransaction ()
  4960. // start a new transaction, to be terminated by either COMMIT or ROLLBACK.
  4961. {
  4962. $DML =& $this->_getDBMSengine($this->dbname);
  4963.  
  4964. $GLOBALS['lock_tables'] = FALSE; // set default, may be changed
  4965. $GLOBALS['lock_rows'] = FALSE; // set default, may be changed
  4966.  
  4967. $this->transaction_level = null; // set default, may be changed
  4968.  
  4969. // get optional locks from current object
  4970. $lock_array = $this->_cm_getDatabaseLock();
  4971.  
  4972. $new_array = array();
  4973.  
  4974. if ($GLOBALS['lock_tables'] == TRUE) {
  4975. if (empty($lock_array)) {
  4976. $lock_array['WRITE'][] = $this->tablename;
  4977. } // if
  4978.  
  4979. foreach ($lock_array as $row => $data) {
  4980. // if no READ/WRITE lock is specified, default to WRITE
  4981. if (!preg_match('/^(READ|WRITE)$/i', $row, $regs)) {
  4982. $lock_array['WRITE'][] = $data; // insert new entry
  4983. unset($lock_array[$row]); // delete old entry
  4984. } // if
  4985. } // foreach
  4986.  
  4987. // set up array of standard locks
  4988. $std_lock['WRITE']['audit'][] = 'audit_ssn';
  4989. $std_lock['WRITE']['audit'][] = 'audit_trn';
  4990. $std_lock['WRITE']['audit'][] = 'audit_tbl';
  4991. $std_lock['WRITE']['audit'][] = 'audit_fld';
  4992. $std_lock['READ'] ['menu'][] = 'mnu_role';
  4993. $std_lock['READ'] ['menu'][] = 'mnu_task';
  4994. $std_lock['READ'] ['menu'][] = 'mnu_initial_value_role';
  4995. $std_lock['READ'] ['menu'][] = 'mnu_initial_value_user';
  4996. $std_lock['READ'] ['workflow'][] = 'wf_workflow';
  4997. $std_lock['READ'] ['workflow'][] = 'wf_place';
  4998. $std_lock['READ'] ['workflow'][] = 'wf_transition';
  4999. $std_lock['READ'] ['workflow'][] = 'wf_arc';
  5000. $std_lock['WRITE']['workflow'][] = 'wf_case';
  5001. $std_lock['WRITE']['workflow'][] = 'wf_token';
  5002. $std_lock['WRITE']['workflow'][] = 'wf_workitem';
  5003.  
  5004. // compare $lock_array with $std_locks looking for duplicates
  5005. // NOTE: a WRITE lock will replace a READ lock
  5006. foreach ($lock_array as $mode => $mode_array) {
  5007. foreach ($mode_array as $row => $tablename) {
  5008. if (strpos($tablename, '.')) {
  5009. // split into $dbname and $tablename
  5010. list($dbname, $tablename) = explode('.', $tablename);
  5011. } else {
  5012. $dbname = $this->dbname;
  5013. } // if
  5014. if ($mode == 'WRITE') {
  5015. if (array_key_exists($dbname, $std_lock['READ'])) {
  5016. if (in_array($tablename, $std_lock['READ'][$dbname])) {
  5017. // remove any entry for the same table in the READ array
  5018. $stdrow = array_search($tablename, $std_lock['READ'][$dbname]);
  5019. unset($std_lock['READ'][$dbname][$stdrow]);
  5020. //} else {
  5021. // unset($lock_array[$mode][$row]);
  5022. } // if
  5023. } elseif (array_key_exists($dbname, $std_lock['WRITE'])) {
  5024. if (in_array($tablename, $std_lock['WRITE'][$dbname])) {
  5025. // remove any entry for the same table in the READ array
  5026. $stdrow = array_search($tablename, $std_lock['WRITE'][$dbname]);
  5027. unset($std_lock['WRITE'][$dbname][$stdrow]);
  5028. } // if
  5029. } // if
  5030. } else { // $mode == 'READ'
  5031. if (array_key_exists($dbname, $std_lock['READ'])) {
  5032. if (in_array($tablename, $std_lock['READ'][$dbname])) {
  5033. // remove any entry for the same table in the READ array
  5034. $stdrow = array_search($tablename, $std_lock['READ'][$dbname]);
  5035. unset($std_lock['READ'][$dbname][$stdrow]);
  5036. } // if
  5037. } elseif (array_key_exists($dbname, $std_lock['WRITE'])) {
  5038. if (in_array($tablename, $std_lock['WRITE'][$dbname])) {
  5039. // remove any entry for the same table in the READ array
  5040. unset($lock_array[$mode][$row]);
  5041. } // if
  5042. } // if
  5043. } // if
  5044. } // foreach
  5045. } // foreach
  5046.  
  5047. $switch_dbnames = array();
  5048. reset($lock_array);
  5049. // transfer $lock_array to $new_array
  5050. foreach ($lock_array as $mode => $mode_array) {
  5051. foreach ($mode_array as $row => $tablename) {
  5052. if (strpos($tablename, '.')) {
  5053. // split into $dbname and $tablename
  5054. list($dbname, $tablename) = explode('.', $tablename);
  5055. if (!array_key_exists($dbname, $switch_dbnames)) {
  5056. // does not exist yet, so create it now
  5057. $switch_dbnames[$dbname] = findDBName($dbname, $this->dbname);
  5058. } // if
  5059. // replace dictionary name with server name
  5060. $server_dbname = $switch_dbnames[$dbname];
  5061. $new_array[$mode][] = $server_dbname.$tablename;
  5062. } else {
  5063. $new_array[$mode][] = $tablename;
  5064. } // if
  5065. } // foreach
  5066. } // foreach
  5067.  
  5068. // transfer $std_lock to $new_array
  5069. foreach ($std_lock as $mode => $mode_array) {
  5070. foreach ($mode_array as $std_dbname => $std_table_array) {
  5071. foreach ($std_table_array as $std_tablename) {
  5072. if ($std_dbname == $this->dbname) {
  5073. $new_array[$mode][] = $std_tablename;
  5074. } else {
  5075. if (!array_key_exists($std_dbname, $switch_dbnames)) {
  5076. // does not exist yet, so create it now
  5077. $switch_dbnames[$std_dbname] = findDBName($std_dbname, $this->dbname);
  5078. } // if
  5079. // replace dictionary name with server name
  5080. $server_dbname = $switch_dbnames[$std_dbname];
  5081. $new_array[$mode][] = $server_dbname.$std_tablename;
  5082. } // if
  5083. } // foreach
  5084. } // foreach
  5085. } // foreach
  5086.  
  5087. } // if
  5088.  
  5089. $DML->transaction_level = $this->transaction_level;
  5090. $DML->table_locks = $new_array;
  5091. $DML->row_locks = $this->row_locks; // EX=Exclusive, SH=shared
  5092. $DML->row_locks_supp = $this->row_locks_supp; // DBMS-specific
  5093.  
  5094. $result = $DML->startTransaction($this->dbname_server);
  5095.  
  5096. $GLOBALS['transaction_has_started'] = TRUE;
  5097.  
  5098. return $result;
  5099.  
  5100. } // startTransaction
  5101.  
  5102. // ****************************************************************************
  5103. function unFormatData ($fieldarray)
  5104. // remove any formatting before data is given to the database.
  5105. // (such as changing dates from 'dd Mmm CCYY' to 'CCYY-MM-DD')
  5106. {
  5107. $dateobj =& RDCsingleton::getInstance('date_class');
  5108.  
  5109. foreach ($fieldarray as $fieldname => $fieldvalue) {
  5110. // only deal with fields defined in $fieldspec
  5111. if (isset($this->fieldspec[$fieldname])) {
  5112. // get specifications for current field
  5113. $fieldspec = $this->fieldspec[$fieldname];
  5114. if (!isset($fieldspec['type'])) {
  5115. $fieldspec['type'] = 'string'; // set default type
  5116. } // if
  5117.  
  5118. $operators = "/^(<>|<=|<|>=|>|!=|=|LIKE |IS NOT |IS |IN |BETWEEN )/i";
  5119. // does $fieldvalue start with a valid operator?
  5120. if (!preg_match($operators, ltrim($fieldvalue), $regs)) {
  5121. // no, so value can be (un)formatted
  5122. switch (strtolower($fieldspec['type'])) {
  5123. case 'string':
  5124. break;
  5125. case 'boolean':
  5126. break;
  5127. case 'date':
  5128. if (empty($fieldvalue)) {
  5129. if (isset($fieldspec['infinityisnull'])) {
  5130. if ($GLOBALS['mode'] == 'search') {
  5131. // do not modify this field in a search screen
  5132. } else {
  5133. // empty date is shown in the database as infinity
  5134. $fieldarray[$fieldname] = '9999-12-31';
  5135. } // if
  5136. } // if
  5137. } else {
  5138. // convert date from external to internal format
  5139. if ($internaldate = $dateobj->getInternalDate($fieldvalue)) {
  5140. // value is a valid date
  5141. $fieldarray[$fieldname] = $internaldate;
  5142. } // if
  5143. } // if
  5144. break;
  5145. case 'datetime':
  5146. if (!empty($fieldvalue)) {
  5147. // convert date from external to internal format
  5148. if ($internaldate = $dateobj->getInternalDateTime($fieldvalue)) {
  5149. // value is a valid date
  5150. $fieldarray[$fieldname] = $internaldate;
  5151. } // if
  5152. } // if
  5153. break;
  5154. case 'time':
  5155. break;
  5156. case 'float':
  5157. case 'double':
  5158. case 'real':
  5159. break;
  5160. default:
  5161. ;
  5162. } // switch
  5163. } // if
  5164. } // if
  5165. } // foreach
  5166.  
  5167. // perform any custom unformatting
  5168. $fieldarray = $this->_cm_unFormatData($fieldarray);
  5169.  
  5170. return $fieldarray;
  5171.  
  5172. } // unFormatData
  5173.  
  5174. // ****************************************************************************
  5175. function unFormatNumber ($fieldarray)
  5176. // remove any foreign formatting on numbers.
  5177. {
  5178. // if ($_SESSION['user_language'] == $_SESSION['default_language']) {
  5179. // return $fieldarray; // nothing to do
  5180. // } // if
  5181.  
  5182. foreach ($this->fieldspec as $field => $spec) {
  5183. if (!empty($fieldarray[$field])) {
  5184. if (preg_match('/(decimal|numeric|float|real|double|integer)/i', $spec['type'])) {
  5185. $fieldarray[$field] = number_unformat($fieldarray[$field]);
  5186. } // if
  5187. } // if
  5188. } // foreach
  5189.  
  5190. return $fieldarray;
  5191.  
  5192. } // unFormatNumber
  5193.  
  5194. // ****************************************************************************
  5195. function updateFieldArray ($fieldarray, $postarray)
  5196. // update fieldarray with data POSTed via javascript submit() function.
  5197. // NOTE: the output is passed by reference.
  5198. {
  5199. if ($this->errors) {
  5200. return $this->getFieldArray(); // object has unresolved errors, so do nothing
  5201. } // if
  5202.  
  5203. // filter out any data which does not belong in this table
  5204. $postarray = getPostArray($postarray, $this->fieldspec);
  5205.  
  5206. if (is_long(key($fieldarray))) {
  5207. $fieldarray_key = key($fieldarray); // does index start at 0 or 1?
  5208. } else {
  5209. $fieldarray_key = 0;
  5210. } // if
  5211.  
  5212. // each item in post array may have different values for different rows,
  5213. // so construct an array which is indexed by row number, not field name
  5214. $rows = array();
  5215. foreach ($postarray as $postname => $postvalue) {
  5216. if (is_array($postvalue)) {
  5217. foreach ($postvalue as $rownum => $value) {
  5218. if ($fieldarray_key == 0) {
  5219. $rownum = $rownum -1; // post array starts at 1, fieldarray starts at 0
  5220. } // if
  5221. $rows[$rownum][$postname] = $value;
  5222. } // foreach
  5223. } else {
  5224. // not linked with a particular row, so default to first row
  5225. $rows[$fieldarray_key][$postname] = $postvalue;
  5226. } // if
  5227. } // foreach
  5228.  
  5229. if (empty($rows)) {
  5230. return $this->getFieldArray(); // nothing to update in this object
  5231. } // if
  5232.  
  5233. reset($fieldarray);
  5234. if (!is_long(key($fieldarray))) {
  5235. $fieldarray = array($fieldarray);
  5236. } // if
  5237. $fieldarray_out = $fieldarray;
  5238.  
  5239. // deal with the changes on each row, one at a time
  5240. foreach ($rows as $rownum => $postdata) {
  5241. if (array_key_exists($rownum, $fieldarray)) {
  5242. // perform any custom pre-update processing
  5243. if (is_object($this->custom_processing_object)) {
  5244. if (method_exists($this->custom_processing_object, '_cm_updateFieldArray')) {
  5245. $fieldarray_out[$rownum] = $this->custom_processing_object->_cm_updateFieldArray($fieldarray[$rownum], $postdata, $rownum);
  5246. } // if
  5247. } // if
  5248. if ($this->custom_replaces_standard) {
  5249. $this->custom_replaces_standard = false;
  5250. } else {
  5251. $fieldarray_out[$rownum] = $this->_cm_updateFieldArray($fieldarray[$rownum], $postdata, $rownum);
  5252. } // if
  5253. if (!empty($this->errors)) {
  5254. return $this->getFieldArray();
  5255. } // if
  5256. // check to see if anything has been changed
  5257. $changes = getChanges($fieldarray_out[$rownum], $fieldarray[$rownum]);
  5258. if (!empty($changes)) {
  5259. // values have been changed internally, so remove from $postarray so they don't get overwritten
  5260. foreach ($changes as $name => $value) {
  5261. if (is_array($postarray[$name])) {
  5262. unset($postarray[$name][$rownum+1]);
  5263. } else {
  5264. unset($postarray[$name]);
  5265. } // if
  5266. } // foreach
  5267. } // if
  5268. } // if
  5269. } // foreach
  5270.  
  5271. if ($this->rows_per_page == 1) {
  5272. $fieldarray = array_update_associative($fieldarray_out[$fieldarray_key], $postarray, $this->fieldspec);
  5273. } else {
  5274. $fieldarray = array_update_indexed($fieldarray_out, $postarray, $this->fieldspec);
  5275. } // if
  5276.  
  5277. // see if any additional data is required or needs to be changed
  5278. $fieldarray = $this->getExtraData($fieldarray);
  5279.  
  5280. $this->fieldarray = $fieldarray;
  5281.  
  5282. return $this->getFieldArray();
  5283.  
  5284. } // updateFieldArray
  5285.  
  5286. // ****************************************************************************
  5287. function updateLinkData ($fieldarray, $postarray)
  5288. // $fieldarray is an array of field data (usually just primary keys).
  5289. // $postarray is an array of entries which have been selected.
  5290. // For each entry where SELECTED=TRUE make sure a database entry exists.
  5291. // For each entry where SELECTED=FALSE make sure a database entry does not exist.
  5292. {
  5293. $this->errors = array();
  5294.  
  5295. // perform any custom pre-update processing
  5296. if (is_object($this->custom_processing_object)) {
  5297. if (method_exists($this->custom_processing_object, '_cm_pre_updateLinkData')) {
  5298. $fieldarray = $this->custom_processing_object->_cm_pre_updateLinkData($fieldarray, $postarray);
  5299. } // if
  5300. } // if
  5301. if ($this->custom_replaces_standard) {
  5302. $this->custom_replaces_standard = false;
  5303. } else {
  5304. $fieldarray = $this->_cm_pre_updateLinkData($fieldarray, $postarray);
  5305. } // if
  5306. if (!empty($this->errors)) return $fieldarray;
  5307.  
  5308. // transfer values from $postarray to $fieldarray
  5309. // each fieldname in $postarray contains an array of values
  5310. foreach ($postarray as $fieldname => $valuearray) {
  5311. if ($fieldname != 'select') {
  5312. if (is_array($valuearray)) {
  5313. // copy row value from $postarray to $fieldarray for current $fieldname
  5314. foreach ($valuearray as $row => $value) {
  5315. // $fieldarray starts at 0, $postarray starts at 1
  5316. $fieldarray[$row-1][$fieldname] = $postarray[$fieldname][$row];
  5317. } // foreach
  5318. } // if
  5319. } // if
  5320. } // foreach
  5321.  
  5322. if (!empty($this->errors)) {
  5323. return $fieldarray;
  5324. } // if
  5325.  
  5326. $errors = array();
  5327.  
  5328. $default_orderby = $this->default_orderby; // save
  5329. $save_sql_select = $this->sql_select;
  5330. $save_sql_from = $this->sql_from;
  5331. $save_sql_search = $this->sql_search;
  5332.  
  5333. // get array of fieldnames in the primary key
  5334. $pkeynames = $this->getPkeyNames();
  5335.  
  5336. foreach ($fieldarray as $rownum => $rowdata) {
  5337.  
  5338. // construct 'where' clause from primary key
  5339. $where = array2where($rowdata, $pkeynames);
  5340.  
  5341. // find out if this record currently exists or not
  5342. $count = $this->getCount($where);
  5343.  
  5344. // perform action depending on value in $select array
  5345. if (isset($postarray['select'][$rownum+1])) {
  5346. $fieldarray[$rownum]['selected'] = 'T';
  5347. // row is marked for insert/update
  5348. if ($count == 0) {
  5349. // record does not exist, so create it
  5350. $rowdata = $this->insertRecord($rowdata);
  5351. } else {
  5352. // record already exists, so update it
  5353. $rowdata = $this->updateRecord($rowdata);
  5354. } // if
  5355. } else {
  5356. $fieldarray[$rownum]['selected'] = '';
  5357. // row is marked for deletion
  5358. if ($count > 0) {
  5359. $where = array2where($rowdata, $this->getPkeyNames());
  5360. $olddata = $this->_dml_ReadBeforeUpdate($where);
  5361. $rowdata = $this->deleteRecord($olddata[0]);
  5362. } // if
  5363. } // if
  5364.  
  5365. if ($this->errors) {
  5366. $errors[$rownum] = $this->errors;
  5367. } // if
  5368.  
  5369. } // foreach
  5370.  
  5371. $this->default_orderby = $default_orderby; // restore
  5372. $this->sql_select = $save_sql_select;
  5373. $this->sql_from = $save_sql_from;
  5374. $this->sql_search_orig = $save_sql_search;
  5375.  
  5376. // perform any custom post-update processing
  5377. if (is_object($this->custom_processing_object)) {
  5378. if (method_exists($this->custom_processing_object, '_cm_post_updateLinkData')) {
  5379. $fieldarray = $this->custom_processing_object->_cm_post_updateLinkData($fieldarray, $postarray);
  5380. } // if
  5381. } // if
  5382. if ($this->custom_replaces_standard) {
  5383. $this->custom_replaces_standard = false;
  5384. } else {
  5385. $fieldarray = $this->_cm_post_updateLinkData($fieldarray, $postarray);
  5386. } // if
  5387. if (!empty($this->errors)) {
  5388. $errors = array_merge($errors, $this->errors);
  5389. return $fieldarray;
  5390. } // if
  5391.  
  5392. $this->errors = $errors;
  5393. $this->fieldarray = $fieldarray;
  5394.  
  5395. return $fieldarray;
  5396.  
  5397. } // updateLinkData
  5398.  
  5399. // ****************************************************************************
  5400. function updateMultiple ($fieldarray, $postarray=array())
  5401. // update multiple records using original data in $fieldarray
  5402. // and changed data in $postarray.
  5403. {
  5404. $this->errors = array();
  5405. $this->numrows = 0;
  5406. $this->no_display_count = false;
  5407. $count = 0;
  5408.  
  5409. // transfer values from $postarray to $fieldarray
  5410. // each fieldname in $postarray is an array of values
  5411. foreach ($postarray as $fieldname => $valuearray) {
  5412. if (is_array($valuearray)) {
  5413. // copy row value from $postarray to $fieldarray for current $fieldname
  5414. foreach ($valuearray as $row => $value) {
  5415. // $fieldarray starts at 0, $postarray starts at 1
  5416. $fieldarray[$row-1][$fieldname] = $postarray[$fieldname][$row];
  5417. } // foreach
  5418. } // if
  5419. } // foreach
  5420.  
  5421. // perform any custom validation/processing before update
  5422. if (is_object($this->custom_processing_object)) {
  5423. if (method_exists($this->custom_processing_object, '_cm_pre_updateMultiple')) {
  5424. $fieldarray = $this->custom_processing_object->_cm_pre_updateMultiple($fieldarray);
  5425. } // if
  5426. } // if
  5427. if ($this->custom_replaces_standard) {
  5428. $this->custom_replaces_standard = false;
  5429. } else {
  5430. $fieldarray = $this->_cm_pre_updateMultiple($fieldarray);
  5431. } // if
  5432.  
  5433. if (empty($this->errors)) {
  5434. // create a separate array indexed by row number
  5435. $errors = array();
  5436. // now update each row in the database
  5437. foreach ($fieldarray as $row => $data) {
  5438. $fieldarray[$row] = $this->updateRecord($data);
  5439. if (!empty($this->errors)) {
  5440. // keep $errors separate for each row
  5441. $errors[$row] = $this->errors;
  5442. } else {
  5443. $count = $count + $this->numrows;
  5444. } // if
  5445. } // foreach
  5446. // overwrite proper variables
  5447. $this->errors = $errors;
  5448. $this->numrows = $count;
  5449. } // if
  5450.  
  5451. if (is_True($this->no_display_count)) {
  5452. // do not display record count
  5453. } else {
  5454. // '$count records were updated in $tablename'
  5455. $this->messages[] = $this->getLanguageText('sys0006', $count, strtoupper($this->tablename));
  5456. } // if
  5457.  
  5458. //if (empty($this->errors)) {
  5459. // perform any custom validation/processing after update
  5460. if (is_object($this->custom_processing_object)) {
  5461. if (method_exists($this->custom_processing_object, '_cm_post_updateMultiple')) {
  5462. $fieldarray = $this->custom_processing_object->_cm_post_updateMultiple($fieldarray);
  5463. } // if
  5464. } // if
  5465. if ($this->custom_replaces_standard) {
  5466. $this->custom_replaces_standard = false;
  5467. } else {
  5468. $fieldarray = $this->_cm_post_updateMultiple($fieldarray);
  5469. } // if
  5470. //} // if
  5471.  
  5472. // store updated $fieldarray within this object
  5473. $this->fieldarray = $fieldarray;
  5474.  
  5475. return $fieldarray;
  5476.  
  5477. } // updateMultiple
  5478.  
  5479. // ****************************************************************************
  5480. function updateRecord ($fieldarray)
  5481. // update a record using the contents of $fieldarray.
  5482. {
  5483. if (empty($fieldarray)) return $fieldarray;
  5484.  
  5485. $this->errors = array();
  5486.  
  5487. reset($fieldarray);
  5488. if (!is_string(key($fieldarray))) {
  5489. // input is indexed by row, so extract data for 1st row only
  5490. $fieldarray = $fieldarray[key($fieldarray)];
  5491. } // if
  5492.  
  5493. // shift all field names to lower case
  5494. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  5495.  
  5496. //if ($this->initiated_from_controller) {
  5497. // deal with numbers in foreign formats
  5498. //$fieldarray = $this->unFormatNumber($fieldarray); // (NOTE: this is now done in array_update_associative() function)
  5499. // deal with datetime in different timezones
  5500. //$fieldarray = $this->convertTimeZone($fieldarray); // (NOTE: this is now done after the _cm_pre_updateRecord() method)
  5501. //} // if
  5502.  
  5503. if (isset($this->fieldspec['rdcaccount_id'])) {
  5504. if (empty($_SESSION['rdcaccount_id'])) {
  5505. if (preg_match('/(mnu_user|mnu_account)/i', $this->tablename)) {
  5506. // do nothing on this table
  5507. } else {
  5508. // use the 'sharing' id
  5509. $fieldarray['rdcaccount_id'] = 1;
  5510. } // if
  5511. } else {
  5512. if ($fieldarray['rdcaccount_id'] != $_SESSION['rdcaccount_id']) {
  5513. // not allowed to update a shared record
  5514. $this->errors['rdcaccount_id'] = $this->getLanguageText('sys0189');
  5515. } // if
  5516. // not allowed to change the record's account
  5517. $fieldarray['rdcaccount_id'] = $_SESSION['rdcaccount_id'];
  5518. } // if
  5519. } // if
  5520.  
  5521. $updatearray = $fieldarray; // copy to temporary area
  5522.  
  5523. if (empty($this->errors)) {
  5524. // perform any custom pre-update processing
  5525. if (is_object($this->custom_processing_object)) {
  5526. if (method_exists($this->custom_processing_object, '_cm_pre_updateRecord')) {
  5527. $updatearray = $this->custom_processing_object->_cm_pre_updateRecord($updatearray);
  5528. } // if
  5529. } // if
  5530. if ($this->custom_replaces_standard) {
  5531. $this->custom_replaces_standard = false;
  5532. } else {
  5533. $updatearray = $this->_cm_pre_updateRecord($updatearray);
  5534. } // if
  5535. } // if
  5536.  
  5537. if ($this->initiated_from_controller === TRUE AND $this->no_convert_timezone === FALSE) {
  5538. if (!empty($updatearray) AND !empty($GLOBALS['screen_structure'])) {
  5539. // deal with datetimes from screen input which may be in different timezone
  5540. $updatearray = $this->convertTimeZone($updatearray, $this->fieldspec);
  5541. } // if
  5542. } // if
  5543.  
  5544. $updatearray = array_change_key_case($updatearray, CASE_LOWER);
  5545.  
  5546. if (empty($this->errors) AND !empty($updatearray)) {
  5547. // perform standard declarative checks on input data
  5548. $updatearray = $this->_validateUpdate($updatearray);
  5549. // replace any fields which may have been removed during the validation process
  5550. $updatearray = array_merge($fieldarray, $updatearray);
  5551. } // if
  5552.  
  5553. $originaldata = array();
  5554. if (empty($this->errors) AND !empty($updatearray)) {
  5555. // build 'where' string using values for primary key
  5556. $pkey_names = $this->getPkeyNames();
  5557. if (array_key_exists('rdcversion', $this->fieldspec) AND array_key_exists('rdcversion', $updatearray)) {
  5558. // add this field to the WHERE clause for this lookup
  5559. $pkey_names[] = 'rdcversion';
  5560. } // if
  5561. $where = array2where($updatearray, $pkey_names, $this);
  5562. if (!empty($where)) {
  5563. // obtain copy of original record from database
  5564. // (this may reuse previous SELECT statement which contains a JOIN)
  5565. $originaldata = $this->_dml_ReadBeforeUpdate($where, $this->reuse_previous_select);
  5566. } else {
  5567. $this->numrows = 0;
  5568. } // if
  5569. $this->reuse_previous_select = false;
  5570. if ($this->numrows <> 1) {
  5571. // 'Could not locate original $tablename record for updating ($where)'
  5572. $this->errors[] = $this->getLanguageText('sys0007', strtoupper($this->tablename), $where);
  5573. } else {
  5574. // use only 1st row in $originaldata
  5575. $originaldata = $originaldata[key($originaldata)];
  5576. // insert any missing values into updatearray before further validation
  5577. $updatearray = array_merge($originaldata, $updatearray);
  5578. } // if
  5579. } // if
  5580.  
  5581. if (empty($this->errors) AND is_array($updatearray) AND !empty($updatearray)) {
  5582. if ($this->skip_validation) {
  5583. // do not perform any custom validation
  5584. } else {
  5585. // perform any custom pre-update validation (1)
  5586. if (is_object($this->custom_processing_object)) {
  5587. if (method_exists($this->custom_processing_object, '_cm_commonValidation')) {
  5588. $updatearray = $this->custom_processing_object->_cm_commonValidation($updatearray, $originaldata);
  5589. } // if
  5590. } // if
  5591. if ($this->custom_replaces_standard) {
  5592. $this->custom_replaces_standard = false;
  5593. } else {
  5594. $updatearray = $this->_cm_commonValidation($updatearray, $originaldata);
  5595. } // if
  5596.  
  5597. if (empty($this->errors)) {
  5598. // perform any custom pre-update validation (2)
  5599. if (is_object($this->custom_processing_object)) {
  5600. if (method_exists($this->custom_processing_object, '_cm_validateUpdate')) {
  5601. $updatearray = $this->custom_processing_object->_cm_validateUpdate($updatearray, $originaldata);
  5602. } // if
  5603. } // if
  5604. if ($this->custom_replaces_standard) {
  5605. $this->custom_replaces_standard = false;
  5606. } else {
  5607. $updatearray = $this->_cm_validateUpdate($updatearray, $originaldata);
  5608. } // if
  5609. } // if
  5610.  
  5611. $updatearray = array_change_key_case($updatearray, CASE_LOWER);
  5612.  
  5613. } // if
  5614. } // if
  5615.  
  5616. if (empty($this->errors)) {
  5617. // everything OK so far, so update the database
  5618. if (is_array($updatearray) AND !empty($updatearray)) {
  5619. // perform any last-minute adjustments
  5620. foreach ($this->fieldspec as $field => $spec) {
  5621. if (array_key_exists($field, $updatearray)) {
  5622. if (array_key_exists('autoinsert', $spec) OR array_key_exists('autoupdate', $spec)) {
  5623. // remove any autoinsert or autoupdate fields
  5624. unset($updatearray[$field]);
  5625. //} elseif (array_key_exists('noedit', $spec) OR array_key_exists('nodisplay', $spec)) {
  5626. // // remove any non-editable fields
  5627. // unset($updatearray[$field]);
  5628. } // if
  5629. if (!empty($updatearray[$field])) {
  5630. if (is_array($this->allow_db_function) AND in_array($field, $this->allow_db_function)) {
  5631. // this is a function call, not a value, so leave it alone
  5632. } else {
  5633. if (preg_match('/(decimal|numeric|float|real|double)/i', $spec['type'])) {
  5634. // remove thousands separator and ensure decimal point is '.'
  5635. $updatearray[$field] = number_unformat($updatearray[$field], '.', ',');
  5636. if (preg_match("/^$field"."[+-][1-9]+/i", $updatearray[$field])) {
  5637. // assume value is in format 'field+1', so let it through
  5638. } elseif (array_key_exists('scale', $spec)) {
  5639. // round to the correct number of decimal places
  5640. $updatearray[$field] = number_format($updatearray[$field], $spec['scale'], '.', '');
  5641. } // if
  5642. } // if
  5643. } // if
  5644. } // if
  5645. } // if
  5646. } // foreach
  5647. // find out how many fields have changed
  5648. $changes = getChanges($updatearray, $originaldata);
  5649. } else {
  5650. $changes = array();
  5651. } // if
  5652. if (empty($changes)) {
  5653. $this->numrows = 0;
  5654. } else {
  5655. // pass both the updated and the original data for processing
  5656. $changes = $this->_dml_updateRecord($updatearray, $originaldata);
  5657. // merge actual updates with proposed updates
  5658. $updatearray = array_merge($updatearray, $changes);
  5659. } // if
  5660. } // if
  5661.  
  5662. $fieldarray = array_merge($originaldata, $fieldarray);
  5663. if (is_array($updatearray) AND !empty($updatearray)) {
  5664. // merge temporary area with original changes
  5665. $fieldarray = array_merge($fieldarray, $updatearray);
  5666. } // if
  5667.  
  5668. if (empty($this->errors)) {
  5669. // perform any custom post-update processing
  5670. if (is_object($this->custom_processing_object)) {
  5671. if (method_exists($this->custom_processing_object, '_cm_post_updateRecord')) {
  5672. $fieldarray = $this->custom_processing_object->_cm_post_updateRecord($fieldarray, $originaldata);
  5673. } // if
  5674. } // if
  5675. if ($this->custom_replaces_standard) {
  5676. $this->custom_replaces_standard = false;
  5677. } else {
  5678. $fieldarray = $this->_cm_post_updateRecord($fieldarray, $originaldata);
  5679. } // if
  5680. } // if
  5681.  
  5682. $fieldarray = array_change_key_case($fieldarray, CASE_LOWER);
  5683.  
  5684. // turn this flag off
  5685. $this->skip_validation = FALSE;
  5686.  
  5687. // store updated $fieldarray within this object
  5688. $this->fieldarray = $fieldarray;
  5689.  
  5690. return $fieldarray;
  5691.  
  5692. } // updateRecord
  5693.  
  5694. // ****************************************************************************
  5695. function updateSelection ($selection, $replace)
  5696. // update a selection of records in a single operation.
  5697. {
  5698. $this->errors = array();
  5699.  
  5700. if (is_long(key($selection))) {
  5701. $selection = $selection[key($selection)];
  5702. } // if
  5703.  
  5704. //$replace = trim($replace, ' ()');
  5705.  
  5706. // perform any custom pre-processing
  5707. if (is_object($this->custom_processing_object)) {
  5708. if (method_exists($this->custom_processing_object, '_cm_pre_updateSelection')) {
  5709. $selection = $this->custom_processing_object->_cm_pre_updateSelection($selection, $replace);
  5710. } // if
  5711. } // if
  5712. if ($this->custom_replaces_standard) {
  5713. $this->custom_replaces_standard = false;
  5714. } else {
  5715. $selection = $this->_cm_pre_updateSelection($selection, $replace);
  5716. } // if
  5717.  
  5718. if (empty($this->errors)) {
  5719. // call custom method for specific processing
  5720. $msg = $this->_cm_updateSelection($selection, $replace);
  5721. } // if
  5722.  
  5723. // perform any custom post-processing
  5724. if (is_object($this->custom_processing_object)) {
  5725. if (method_exists($this->custom_processing_object, '_cm_post_updateSelection')) {
  5726. $selection = $this->custom_processing_object->_cm_post_updateSelection($selection, $replace);
  5727. } // if
  5728. } // if
  5729. if ($this->custom_replaces_standard) {
  5730. $this->custom_replaces_standard = false;
  5731. } else {
  5732. $selection = $this->_cm_post_updateSelection($selection, $replace);
  5733. } // if
  5734.  
  5735. return $msg;
  5736.  
  5737. } // updateSelection
  5738.  
  5739. // ****************************************************************************
  5740. function validateDelete ($fieldarray, $parent_table=null)
  5741. // verify that the specified record can be deleted.
  5742. // ($parent_table is only used in a cascade delete)
  5743. {
  5744. $this->errors = array();
  5745.  
  5746. if ($this->skip_validation) {
  5747. // skip any validation
  5748. return $fieldarray;
  5749. } // if
  5750.  
  5751. if (is_string($fieldarray)) {
  5752. $fieldarray = where2array($fieldarray);
  5753. } else{
  5754. reset($fieldarray); // fix for version 4.4.1
  5755. if (!is_string(key($fieldarray))) {
  5756. // indexed by row, so use row zero only
  5757. $fieldarray = $fieldarray[key($fieldarray)];
  5758. } // if
  5759. } // if
  5760.  
  5761. if (isset($this->fieldspec['rdcaccount_id'])) {
  5762. if (!empty($_SESSION['rdcaccount_id'])) {
  5763. if ($fieldarray['rdcaccount_id'] != $_SESSION['rdcaccount_id']) {
  5764. // not allowed to delete a shared record
  5765. $this->errors['rdcaccount_id'] = $this->getLanguageText('sys0188');
  5766. } // if
  5767. } // if
  5768. } // if
  5769.  
  5770. // invoke custom method(s) (may be empty)
  5771. if (is_object($this->custom_processing_object)) {
  5772. if (method_exists($this->custom_processing_object, '_cm_validateDelete')) {
  5773. $this->custom_processing_object->_cm_validateDelete($fieldarray, $parent_table);
  5774. } // if
  5775. } // if
  5776. if ($this->custom_replaces_standard) {
  5777. $this->custom_replaces_standard = false;
  5778. } else {
  5779. $this->_cm_validateDelete($fieldarray, $parent_table);
  5780. } // if
  5781.  
  5782. if (!empty($this->errors)) return $fieldarray;
  5783.  
  5784. if (!empty($GLOBALS['settings'])) {
  5785. // check settings for any special restrictions
  5786. foreach ($GLOBALS['settings'] as $setting_field => $setting_value) {
  5787. $setting_field = strtolower($setting_field);
  5788. $setting_value = strtolower($setting_value);
  5789. if ($setting_value == '$logon_user_id') {
  5790. if (array_key_exists($setting_field, $fieldarray)) {
  5791. if ($fieldarray[$setting_field] != $_SESSION['logon_user_id']) {
  5792. // "This record can only be deleted by its owner/creator"
  5793. $this->errors[] = $this->getLanguageText('sys0115');
  5794. return $fieldarray;
  5795. } // if
  5796. } // if
  5797. } // if
  5798. } // foreach
  5799. } // if
  5800.  
  5801. if (empty($parent_table)) {
  5802. $parent_table = $this->tablename;
  5803. } // if
  5804.  
  5805. // all relationship data is held in a class variable
  5806. foreach ($this->child_relations as $reldata) {
  5807. $tblchild = $reldata['child'];
  5808. switch(strtoupper($reldata['type'])) {
  5809. case 'RESTRICTED':
  5810. case 'RES':
  5811. // delete is not allowed if relationship is 'restricted'
  5812. $where = NULL;
  5813. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  5814. //if (strlen($fldchild) < 1) {
  5815. // $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild)); // 'Name of child field missing in relationship with $tblchild';
  5816. // break;
  5817. //} // if
  5818. if (!empty($fldchild)) {
  5819. if (empty($where)) {
  5820. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  5821. } else {
  5822. $where .= ' AND ' ."$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  5823. } // if
  5824. } // if
  5825. } // foreach
  5826. if (empty($where)) {
  5827. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild)); // 'Name of child field missing in relationship with $tblchild';
  5828. break;
  5829. } else {
  5830. $where = $this->_dml_adjustWhere($where); // replace escape character if different
  5831. // instantiate an object for this table
  5832. if (array_key_exists('subsys_dir', $reldata)) {
  5833. // get path to current subsystem directory
  5834. $dir = dirname($this->dirname);
  5835. // switch to other subsystem directory
  5836. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  5837. } else {
  5838. $dir = NULL;
  5839. } // if
  5840. if (!class_exists($tblchild)) {
  5841. require_once $dir ."classes/$tblchild.class.inc";
  5842. } // if
  5843. $childobject = new $tblchild;
  5844. if (!empty($this->dbname_old) AND $this->dbname_old == $childobject->dbname) {
  5845. // name of parent database has been switched, so switch the child name as well
  5846. $childobject->dbname_old = $childobject->dbname;
  5847. $childobject->dbname = $this->dbname;
  5848. } // if
  5849. $count = $childobject->getCount($where);
  5850. unset($childobject);
  5851. if ($count <> 0) {
  5852. // 'Cannot delete - record still linked to $tblchild table'
  5853. $this->errors[] = $this->getLanguageText('sys0008', strtoupper($tblchild));
  5854. } // if
  5855. } // if
  5856. break;
  5857.  
  5858. case 'DELETE':
  5859. case 'DEL':
  5860. case 'CASCADE':
  5861. case 'CAS':
  5862. // check children of this child
  5863. $where = NULL;
  5864. foreach ($reldata['fields'] as $fldparent => $fldchild) {
  5865. //if (strlen($fldchild) < 1) {
  5866. // // 'Name of child field missing in relationship with $tblchild';
  5867. // $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild));
  5868. // break;
  5869. //} // if
  5870. if (!empty($fldchild)) {
  5871. if (empty($where)) {
  5872. $where = "$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  5873. } else {
  5874. $where .= ' AND ' ."$fldchild='" .addslashes($fieldarray[$fldparent]) ."'";
  5875. } // if
  5876. } //if
  5877. } // foreach
  5878. if (empty($where)) {
  5879. $this->errors[] = $this->getLanguageText('sys0110', strtoupper($tblchild)); // 'Name of child field missing in relationship with $tblchild';
  5880. break;
  5881. } else {
  5882. $where = $this->_dml_adjustWhere($where); // replace escape character if different
  5883. // instantiate an object for this table
  5884. if (array_key_exists('subsys_dir', $reldata)) {
  5885. // get path to current subsystem directory
  5886. $dir = dirname($this->dirname);
  5887. // switch to other subsystem directory
  5888. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  5889. } else {
  5890. $dir = NULL;
  5891. } // if
  5892. if (!class_exists($tblchild)) {
  5893. require_once $dir ."classes/$tblchild.class.inc";
  5894. } // if
  5895. $childobject = new $tblchild;
  5896. if (!empty($this->dbname_old) AND $this->dbname_old == $childobject->dbname) {
  5897. // name of parent database has been switched, so switch the child name as well
  5898. $childobject->dbname_old = $childobject->dbname;
  5899. $childobject->dbname = $this->dbname;
  5900. } // if
  5901. if (array_key_exists('orderby', $reldata)) {
  5902. $childobject->setOrderBy($reldata['orderby']);
  5903. } // if
  5904. $childarray = $childobject->getdata($where);
  5905. foreach ($childarray as $child) {
  5906. $pkey = $childobject->getPkeyArray($child);
  5907. $result = $childobject->validateDelete($pkey, $parent_table);
  5908. $errors = $childobject->getErrors();
  5909. if (!empty($errors)) {
  5910. $this->errors[$childobject->getClassName()] = $errors;
  5911. } // if
  5912. } // foreach
  5913. unset($childobject);
  5914. } // if
  5915. break;
  5916.  
  5917. case 'NULLIFY':
  5918. case 'NUL':
  5919. case 'IGN':
  5920. //do nothing
  5921. break;
  5922.  
  5923. case 'DEX':
  5924. case 'NUX':
  5925. // do nothing as it will be handled by a foreign key constraint
  5926. break;
  5927.  
  5928. default:
  5929. // 'Unknown relation type: $type'
  5930. $this->errors[] = $this->getLanguageText('sys0010', $reldata['type']);
  5931. } // switch
  5932. } // foreach
  5933.  
  5934. // remove any duplicate error messages
  5935. $this->errors = array_unique($this->errors);
  5936.  
  5937. return $fieldarray;
  5938.  
  5939. } // validateDelete
  5940.  
  5941. // ****************************************************************************
  5942. function validateSearch ($fieldarray)
  5943. // validate search screen input before it is passed back to the previous form.
  5944. {
  5945. $this->errors = array();
  5946.  
  5947. foreach ($this->fieldspec as $field => $spec) {
  5948. if (isset($spec['required'])) {
  5949. $fieldarray[$field] = trim($fieldarray[$field]);
  5950. if (empty($fieldarray[$field])) {
  5951. // '$field cannot be blank'
  5952. $this->errors[$field] = $this->getLanguageText('sys0020', $field);
  5953. } // if
  5954. } // if
  5955. } // foreach
  5956.  
  5957. if (is_object($this->custom_processing_object)) {
  5958. if (method_exists($this->custom_processing_object, '_cm_validateSearch')) {
  5959. $fieldarray = $this->custom_processing_object->_cm_validateSearch($fieldarray);
  5960. } // if
  5961. } // if
  5962. if ($this->custom_replaces_standard) {
  5963. $this->custom_replaces_standard = false;
  5964. } else {
  5965. $fieldarray = $this->_cm_validateSearch($fieldarray);
  5966. } // if
  5967.  
  5968. return $fieldarray;
  5969.  
  5970. } // validateSearch
  5971.  
  5972. // ****************************************************************************
  5973. function validateUpdate ($fieldarray)
  5974. // verify that the specified record can be updated.
  5975. {
  5976. if (is_string($fieldarray)) {
  5977. $fieldarray = where2array($fieldarray);
  5978. } else{
  5979. reset($fieldarray); // fix for version 4.4.1
  5980. if (!is_string(key($fieldarray))) {
  5981. // indexed by row, so use row zero only
  5982. $fieldarray = $fieldarray[key($fieldarray)];
  5983. } // if
  5984. } // if
  5985.  
  5986. // check settings for any special restrictions
  5987. foreach ($GLOBALS['settings'] as $setting_field => $setting_value) {
  5988. $setting_field = strtolower($setting_field);
  5989. $setting_value = strtolower($setting_value);
  5990. if ($setting_value == '$logon_user_id') {
  5991. if (array_key_exists($setting_field, $fieldarray)) {
  5992. if ($fieldarray[$setting_field] != $_SESSION['logon_user_id']) {
  5993. // "This record can only be updated by its owner/creator"
  5994. $this->errors[] = $this->getLanguageText('sys0116');
  5995. return false;
  5996. } // if
  5997. } // if
  5998. } // if
  5999. } // foreach
  6000.  
  6001. return true;
  6002.  
  6003. } // validateUpdate
  6004.  
  6005. // ****************************************************************************
  6006. // methods beginning with '_cm_' are designed to be customised as required
  6007. // ****************************************************************************
  6008. function _cm_changeConfig ($where, $fieldarray)
  6009. // Change the table configuration for the duration of this instance.
  6010. // $where = a string in SQL 'where' format.
  6011. // $fieldarray = the contents of $where as an array.
  6012. {
  6013. // customisable code goes here
  6014.  
  6015. return $fieldarray;
  6016.  
  6017. } // _cm_changeConfig
  6018.  
  6019. // ****************************************************************************
  6020. function _cm_commonValidation ($fieldarray, $originaldata)
  6021. // perform validation that is common to INSERT and UPDATE.
  6022. {
  6023. // customisable code goes here
  6024.  
  6025. return $fieldarray;
  6026.  
  6027. } // _cm_commonValidation
  6028.  
  6029. // ****************************************************************************
  6030. function _cm_customButton ($fieldarray, $button)
  6031. // user pressed a custom buttom.
  6032. {
  6033. // custom code goes here
  6034.  
  6035. return $fieldarray;
  6036.  
  6037. } // _cm_customButton
  6038.  
  6039. // ****************************************************************************
  6040. function _cm_deleteSelection ($selection)
  6041. // delete/update a selection of records in a single operation.
  6042. {
  6043. // remove this line after your customisation
  6044. //trigger_error($this->getLanguageText('sys0035', get_class($this)), E_USER_ERROR); // "DELETESELECTION method has not been defined in class"
  6045.  
  6046. // delete selected records.
  6047. $from = null; // used in multi-table delete
  6048. $using = null; // used in multi-table delete
  6049. $limit = null; // maximum number of rows to process
  6050. $count = $this->_dml_deleteSelection($selection, $from, $using, $limit);
  6051.  
  6052. // update selected records
  6053. //$count = $this->_dml_updateSelection ($selection, $replace, $limit);
  6054.  
  6055. // $count rows were deleted
  6056. return $this->getLanguageText('sys0004', $count, strtoupper($this->tablename));
  6057.  
  6058. } // _cm_deleteSelection
  6059.  
  6060. // ****************************************************************************
  6061. function _cm_filePickerSelect ($selection)
  6062. // Deal with selection from a filepicker screen.
  6063. {
  6064. // custom code goes here
  6065.  
  6066. return $selection;
  6067.  
  6068. } // _cm_filePickerSelect
  6069.  
  6070. // ****************************************************************************
  6071. function _cm_fileUpload ($input_name, $temp_file, $wherearray)
  6072. // Specify file name to be used for the upload.
  6073. // $input_name = file name supplied by client
  6074. // $temp_file = copy of file in temp directory
  6075. // $wherearray = contents of original $where string
  6076. // $output_name = file name to be used on server
  6077. {
  6078. // default name for destination file is same as input name
  6079. $output_name = $input_name;
  6080.  
  6081. return $output_name;
  6082.  
  6083. } // _cm_fileUpload
  6084.  
  6085. // ****************************************************************************
  6086. function _cm_filterWhere ($array=null)
  6087. // identify field names which are NOT to be filtered out of a $where string.
  6088. {
  6089. // custom code goes here
  6090. //$array[] = 'whatever';
  6091.  
  6092. return $array;
  6093.  
  6094. } // _cm_filterWhere
  6095.  
  6096. // ****************************************************************************
  6097. function _cm_formatData ($fieldarray, &$css_array)
  6098. // perform custom formatting before values are shown to the user.
  6099. // Note: $css_array is passed BY REFERENCE as it may be modified.
  6100. {
  6101. // customisable code goes here
  6102.  
  6103. return $fieldarray;
  6104.  
  6105. } // _cm_formatData
  6106.  
  6107. // ****************************************************************************
  6108. function _cm_getColumnNames ($fieldarray)
  6109. // modify data to be used by 'std.output4.inc'.
  6110. {
  6111. // custom code goes here
  6112.  
  6113. return $fieldarray;
  6114.  
  6115. } // _cm_getColumnNames
  6116.  
  6117. // ****************************************************************************
  6118. function _cm_getDatabaseLock ()
  6119. // return array of database tables to be locked in current transaction.
  6120. {
  6121. $GLOBALS['lock_tables'] = FALSE; // TRUE/FALSE
  6122. $GLOBALS['lock_rows'] = FALSE; // FALSE, SR (share), EX (exclusive)
  6123.  
  6124. //$this->transaction_level = 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED';
  6125. //$this->transaction_level = 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED';
  6126. //$this->transaction_level = 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ'; // *DEFAULT*
  6127. //$this->transaction_level = 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE';
  6128.  
  6129. // the format of each $lock_array entry is one of the following:
  6130. // $lock_array[] = 'tablename' (within current database)
  6131. // $lock_array[] = 'dbname.tablename' (within another database)
  6132. // $lock_array['READ'][] = '...' (for a READ lock)
  6133. // $lock_array['WRITE'][] = '...' (for a WRITE lock)
  6134. switch ($GLOBALS['mode']){
  6135. case 'insert':
  6136. $lock_array[] = $this->tablename;
  6137. break;
  6138. case 'update':
  6139. $lock_array[] = $this->tablename;
  6140. break;
  6141. case 'delete':
  6142. $lock_array[] = $this->tablename;
  6143. break;
  6144. default:
  6145. $lock_array = array();
  6146. } // switch
  6147.  
  6148. return $lock_array;
  6149.  
  6150. } // _cm_getDatabaseLock
  6151.  
  6152. // ****************************************************************************
  6153. function _cm_getExtraData ($where, $fieldarray)
  6154. // Perform custom processing for the getExtraData method.
  6155. // $where = a string in SQL 'where' format.
  6156. // $fieldarray = the contents of $where as an array.
  6157. {
  6158. // customisable code goes here
  6159.  
  6160. return $fieldarray;
  6161.  
  6162. } // _cm_getExtraData
  6163.  
  6164. // ****************************************************************************
  6165. function _cm_getForeignData ($fieldarray)
  6166. // Retrieve data from foreign (parent) tables.
  6167. {
  6168. // customisable code goes here
  6169.  
  6170. return $fieldarray;
  6171.  
  6172. } // _cm_getForeignData
  6173.  
  6174. // ****************************************************************************
  6175. function _cm_getInitialData ($fieldarray)
  6176. // Perform custom processing prior to insertRecord().
  6177. // $fieldarray contains data from the initial $where clause.
  6178. {
  6179. // customisable code goes here
  6180.  
  6181. return $fieldarray;
  6182.  
  6183. } // _cm_getInitialData
  6184.  
  6185. // ****************************************************************************
  6186. function _cm_getInitialDataMultiple ($fieldarray)
  6187. // Perform custom processing prior to insertMultiple.
  6188. // $fieldarray contains data from the initial $where clause,
  6189. // or current data from the outer object (if one exists).
  6190. {
  6191. // customisable code goes here
  6192.  
  6193. return $fieldarray;
  6194.  
  6195. } // _cm_getInitialDataMultiple
  6196.  
  6197. // ****************************************************************************
  6198. function _cm_getNodeData ($expanded, $where, $where_array = null)
  6199. // retrieve requested node data from the database.
  6200. // $expanded may be a list of nodes to be expanded, or 'ALL' nodes.
  6201. // $where may contain specific selection criteria as a string.
  6202. // $wherearray is $where but converted into an array.
  6203. {
  6204. //DebugBreak();
  6205. $this->sql_select = 'x_tree_node.node_id, x_tree_node.node_desc, x_tree_level.tree_level_seq, COUNT(child.node_id) AS child_count';
  6206. $this->sql_from = 'x_tree_node '
  6207. . 'LEFT JOIN x_tree_level ON (x_tree_level.tree_type_id=x_tree_node.tree_type_id AND x_tree_level.tree_level_id=x_tree_node.tree_level_id) '
  6208. . 'LEFT JOIN x_tree_node AS child ON (x_tree_node.node_id=child.node_id_snr) ';
  6209. $this->sql_where = '';
  6210. $this->sql_groupby = 'x_tree_node.node_id, x_tree_node.node_desc, x_tree_node.tree_level_id, x_tree_level.tree_level_seq';
  6211. $this->sql_having = '';
  6212. $this->sql_orderby = 'x_tree_node.tree_level_id, x_tree_node.node_id';
  6213.  
  6214. if (!empty($this->alt_language_table)) {
  6215. if ($_SESSION['user_language'] != $_SESSION['default_language']) {
  6216. // link to table which provides text in an alternative language
  6217. $pkey_array = array();
  6218. foreach ($this->primary_key as $fieldname) {
  6219. $pkey_array[$fieldname] = $fieldname;
  6220. } // foreach
  6221. $new_relation = array('parent' => $this->alt_language_table,
  6222. 'parent_field' => $this->alt_language_cols,
  6223. 'fields' => $pkey_array);
  6224. $new_relation['this'] = 'x_tree_node';
  6225. $this->sql_select = $this->_sqlSelectAlternateLanguage($this->sql_select, $new_relation);
  6226. } // if
  6227. } // if
  6228.  
  6229. if (array_key_exists('tree_type_id', $where_array)) {
  6230. // look for root nodes within this tree_type
  6231. $where_array['tree_level_seq'] = 1;
  6232. $where = array2where($where_array);
  6233. } // if
  6234.  
  6235. $data_raw = $this->getData($where);
  6236.  
  6237. // there is no pagination after level 1
  6238. $this->rows_per_page = 0;
  6239. $this->pageno = 1;
  6240.  
  6241. foreach ($data_raw as $row => $rowdata) {
  6242. // append data for current node to output array
  6243. $fieldarray[] = $rowdata;
  6244. $node_id = $rowdata['node_id'];
  6245. if ($rowdata['child_count'] > 0) {
  6246. // child nodes exist, but do we expand them?
  6247. if ($expanded == 'ALL' or array_key_exists($node_id, $expanded)) {
  6248. // tell system this row has been expanded
  6249. $fieldarray[count($fieldarray)-1]['expanded'] = 'y';
  6250. // this replaces 'ALL' with a list of actual nodes
  6251. $this->expanded[$node_id] = true;
  6252. // get the child nodes belonging to this parent node
  6253. $childdata = $this->getNodeData($expanded, "node_id_snr='$node_id'");
  6254. // add in child data after the parent
  6255. $fieldarray = array_merge($fieldarray, $childdata);
  6256. } else {
  6257. unset($this->expanded[$node_id]);
  6258. } // if
  6259. } // if
  6260. } // foreach
  6261.  
  6262. unset($data_raw);
  6263.  
  6264. return $fieldarray;
  6265.  
  6266. } // _cm_getNodeData
  6267.  
  6268. // ****************************************************************************
  6269. function _cm_getNodeKeys ($keys)
  6270. // identify the field names for the SENIOR to JUNIOR relationship
  6271. {
  6272. $keys['snr_id'] = 'snr_id';
  6273. $keys['jnr_id'] = 'jnr_id';
  6274.  
  6275. return $keys;
  6276.  
  6277. } // _cm_getNodeKeys
  6278.  
  6279. // ****************************************************************************
  6280. function _cm_getOrderBy ($orderby)
  6281. // Adjust name of orderby item before it is used in an sql SELECT statement.
  6282. {
  6283. // customisable code goes here
  6284.  
  6285. return $orderby;
  6286.  
  6287. } // _cm_getOrderBy
  6288.  
  6289. // ****************************************************************************
  6290. function _cm_getPkeyNames ($pkey_array, $task_id, $pattern_id)
  6291. // return the list of primary key fields in this table before the selection string
  6292. // is constructed and passed to another form.
  6293. // $pkey_array contains the current list of primary key fields.
  6294. // $task_id identifies the task to which the primary key(s) will be passed.
  6295. // $pattern_id identifies the task's pattern.
  6296. {
  6297. //$pkey_array[] = 'whatever'; // append to array
  6298. //$pkey_array = array('whatever'); // replace array
  6299.  
  6300. return $pkey_array;
  6301.  
  6302. } // _cm_getPkeyNames
  6303.  
  6304. // ****************************************************************************
  6305. function _cm_getValRep ($item=null, $where=null, $orderby=null)
  6306. // get Value/Representation list as an associative array.
  6307. {
  6308. $array = array();
  6309.  
  6310. // if ($item == 'item1_id') {
  6311. // // get data from the database
  6312. // $this->sql_select = 'item1_id, item1_desc';
  6313. // $this->sql_orderby = 'item1_desc';
  6314. // $this->sql_ordery_seq = 'asc';
  6315. // $data = $this->getData($where);
  6316. //
  6317. // // convert each row into 'id=desc' in the output array
  6318. // foreach ($data as $row => $rowdata) {
  6319. // $rowvalues = array_values($rowdata);
  6320. // $array[$rowvalues[0]] = $rowvalues[1];
  6321. // } // foreach
  6322. //
  6323. // return $array;
  6324. //
  6325. // } // if
  6326.  
  6327. // if ($item == 'item2') {
  6328. // $array = $this->getLanguageArray('item2');
  6329. // return $array;
  6330. // } // if
  6331.  
  6332. return $array;
  6333.  
  6334. } // _cm_getValRep
  6335.  
  6336. // ****************************************************************************
  6337. function _cm_getWhere ($where, $task_id, $pattern_id)
  6338. // allow WHERE string to be customised before being passed to next task.
  6339. {
  6340. // custom code goes here
  6341.  
  6342. return $where;
  6343.  
  6344. } // _cm_getWhere
  6345.  
  6346. // ****************************************************************************
  6347. function _cm_initialise ($where, &$selection, $search)
  6348. // perform any initialisation for the current task.
  6349. // NOTE: $selection is passed by reference as it may be amended.
  6350. // NOTE: $search is only available for OUTPUT tasks.
  6351. {
  6352. // customisable code goes here
  6353.  
  6354. // $pattern_id = getPatternId();
  6355. // if (preg_match('/^(add)/i', $pattern_id)) {
  6356. // // ignore contents of selection
  6357. // $selection = null;
  6358. // } else {
  6359. // if (!empty($selection)) {
  6360. // $where = $selection;
  6361. // $selection = null;
  6362. // } // if
  6363. // } // if
  6364.  
  6365. return $where;
  6366.  
  6367. } // _cm_initialise
  6368.  
  6369. // ****************************************************************************
  6370. function _cm_initialiseFileDownload ($fieldarray)
  6371. // perform any initialisation for the file download operation.
  6372. {
  6373. //$this->download_filename = $fieldarray['download_filename'];
  6374. //$this->download_mode = 'inline'; // disable option to save
  6375.  
  6376. return $fieldarray;
  6377.  
  6378. } // _cm_initialiseFileDownload
  6379.  
  6380. // ****************************************************************************
  6381. function _cm_initialiseFilePicker ($fieldarray, $search)
  6382. // perform any initialisation before displaying the File Picker screen.
  6383. {
  6384. // identify the subdirectory which contains the files
  6385. $this->picker_subdir = 'filepickersubdirectory';
  6386.  
  6387. // identify the file types that may be picked
  6388. $this->picker_filetypes = array(); // default is ANY file extension
  6389. $this->picker_filetypes = array('txt', 'bmp', 'doc');
  6390.  
  6391. return $fieldarray;
  6392.  
  6393. } // _cm_initialiseFilePicker
  6394.  
  6395. // ****************************************************************************
  6396. function _cm_initialiseFileUpload ($fieldarray)
  6397. // perform any initialisation before displaying the File Upload screen.
  6398. {
  6399. $this->upload_subdir = 'uploadedfiles';
  6400. //$this->upload_filetypes = array('image/x-png', 'image/gif');
  6401. $this->upload_filetypes = 'image'; // for any type of image
  6402. $this->upload_maxfilesize = 100;
  6403.  
  6404. return $fieldarray;
  6405.  
  6406. } // _cm_initialiseFileUpload
  6407.  
  6408. // ****************************************************************************
  6409. function _cm_ListView_header ($fieldarray)
  6410. // insert data into $fieldarray before title is printed in List View
  6411. {
  6412. // customisable code goes here
  6413.  
  6414. return $fieldarray;
  6415.  
  6416. } // _cm_ListView_header
  6417.  
  6418. // ****************************************************************************
  6419. // function _cm_ListView_pre_print ($prev_row, $curr_row)
  6420. // // allow extra rows to be created in List View
  6421. // {
  6422. // $rows = array();
  6423. //
  6424. // // this is deprecated - use _cm_ListView_print_before() and _cm_ListView_print_after() instead
  6425. //
  6426. // return $rows;
  6427. //
  6428. // } // _cm_ListView_pre_print
  6429.  
  6430. // ****************************************************************************
  6431. function _cm_ListView_print_before ($prev_row, $curr_row)
  6432. // allow extra rows to be created in List View
  6433. {
  6434. $output = array();
  6435.  
  6436. // customisable code goes here
  6437.  
  6438. return $output;
  6439.  
  6440. } // _cm_ListView_print_before
  6441.  
  6442. // ****************************************************************************
  6443. function _cm_ListView_print_after ($curr_row, $next_row)
  6444. // allow extra rows to be created in List View
  6445. {
  6446. $output = array();
  6447.  
  6448. // customisable code goes here
  6449.  
  6450. return $output;
  6451.  
  6452. } // _cm_ListView_print_after
  6453.  
  6454. // ****************************************************************************
  6455. function _cm_ListView_total ()
  6456. // pass back any data to be printed on last line of PDF report (list view).
  6457. {
  6458. $array = array();
  6459.  
  6460. // customisable code goes here
  6461.  
  6462. return $array;
  6463.  
  6464. } // _cm_ListView_total
  6465.  
  6466. // ****************************************************************************
  6467. function _cm_output_multi ($name, $fieldarray)
  6468. // get extra data to pass to PDF class.
  6469. {
  6470. $outarray = array();
  6471.  
  6472. switch ($name) {
  6473. case 'multi1':
  6474. // return a non-empty array to print an empty line
  6475. $outarray[] = array('dummy' => '');
  6476. break;
  6477.  
  6478. case 'multi2':
  6479. // return a non-empty array to print an empty line
  6480. $outarray[] = array('dummy' => '');
  6481. break;
  6482.  
  6483. case 'multi3':
  6484. // return a non-empty array to print an empty line
  6485. $outarray[] = array('dummy' => '');
  6486. break;
  6487.  
  6488. case 'multi4':
  6489. // return a non-empty array to print an empty line
  6490. $outarray[] = array('dummy' => '');
  6491. break;
  6492.  
  6493. case 'multi5':
  6494. // return a non-empty array to print an empty line
  6495. $outarray[] = array('dummy' => '');
  6496. break;
  6497.  
  6498. case 'multi6':
  6499. // return a non-empty array to print an empty line
  6500. $outarray[] = array('dummy' => '');
  6501. break;
  6502.  
  6503. case 'multi7':
  6504. // return a non-empty array to print an empty line
  6505. $outarray[] = array('dummy' => '');
  6506. break;
  6507.  
  6508. case 'multi8':
  6509. // return a non-empty array to print an empty line
  6510. $outarray[] = array('dummy' => '');
  6511. break;
  6512.  
  6513. case 'multi9':
  6514. // return a non-empty array to print an empty line
  6515. $outarray[] = array('dummy' => '');
  6516. break;
  6517.  
  6518. default:
  6519. // return a non-empty array to print an empty line
  6520. $outarray[] = array('dummy' => '');
  6521. break;
  6522. } // switch
  6523.  
  6524. if ($outarray) {
  6525. return $outarray;
  6526. } else {
  6527. return false;
  6528. } // if
  6529.  
  6530. } // _cm_output_multi
  6531.  
  6532. // ****************************************************************************
  6533. function _cm_popupCall (&$popupname, $where, $fieldarray, &$settings)
  6534. // if a popup button has been pressed the contents of $where may need to
  6535. // be altered before the popup screen is called.
  6536. // NOTE: $settings is passed BY REFERENCE as it may be altered as well.
  6537. // NOTE: $popupname is passed BY REFERENCE as it may be altered as well.
  6538. {
  6539. // clear out the contents of $where
  6540. //$where = '';
  6541.  
  6542. // allow only one entry to be selected (the default)
  6543. $settings['select_one'] = true;
  6544.  
  6545. // allow more than one entry to be selected
  6546. //$settings['select_one'] = false;
  6547.  
  6548. // allow a single result to be selected without user intervention
  6549. //$settings['choose_single_row'] = true;
  6550.  
  6551. //if ($popupname == 'foo(bar)') {
  6552. // // replace $where for this popup
  6553. // $where = "$where";
  6554. //} else {
  6555. // $where = '';
  6556. //} // if
  6557.  
  6558. return $where;
  6559.  
  6560. } // _cm_popupCall
  6561.  
  6562. // ****************************************************************************
  6563. function _cm_popupReturn ($fieldarray, $return_from, &$select_array)
  6564. // process a selection returned from a popup screen.
  6565. // $fieldarray contains the record data when the popup button was pressed.
  6566. // $return_from identifies which popup screen was called.
  6567. // $select_array contains an array of item(s) selected in that popup screen.
  6568. // NOTE: $select_array is passed BY REFERENCE so that it can be modified.
  6569. {
  6570. //if ($return_from == '???(popup)') {
  6571. // // change field name from 'foo_id' to 'bar_id'
  6572. // $select_array['bar_id'] = $select_array['foo_id'];
  6573. // unset($select_array['foo_id']);
  6574. //} // if
  6575.  
  6576. return $fieldarray;
  6577.  
  6578. } // _cm_popupReturn
  6579.  
  6580. // ****************************************************************************
  6581. function _cm_post_deleteMultiple ($rows)
  6582. // perform custom processing after multiple database records have been deleted.
  6583. {
  6584. // customisable code goes here
  6585.  
  6586. return $rows;
  6587.  
  6588. } // _cm_post_deleteMultiple
  6589.  
  6590. // ****************************************************************************
  6591. function _cm_post_deleteRecord ($fieldarray)
  6592. // perform custom processing after database record has been deleted.
  6593. {
  6594. // customisable code goes here
  6595.  
  6596. return $fieldarray;
  6597.  
  6598. } // _cm_post_deleteRecord
  6599.  
  6600. // ****************************************************************************
  6601. function _cm_post_eraseRecord ($fieldarray)
  6602. // perform custom processing after database record has been erased.
  6603. {
  6604. // customisable code goes here
  6605.  
  6606. return $fieldarray;
  6607.  
  6608. } // _cm_post_eraseRecord
  6609.  
  6610. // ****************************************************************************
  6611. function _cm_post_fetchRow ($fieldarray)
  6612. // perform custom processing after a call to fetchRow().
  6613. {
  6614. // customisable code goes here
  6615.  
  6616. return $fieldarray;
  6617.  
  6618. } // _cm_post_fetchRow
  6619.  
  6620. // ****************************************************************************
  6621. function _cm_post_fileUpload ($filename, $filesize)
  6622. // perform processing after a file has been uploaded.
  6623. {
  6624. // custom processing goes here
  6625.  
  6626. return;
  6627.  
  6628. } // _cm_post_fileUpload
  6629.  
  6630. // ****************************************************************************
  6631. function _cm_post_getData ($rows, &$where)
  6632. // perform custom processing after database record(s) are retrieved.
  6633. // NOTE: $where is passed BY REFERENCE so that it may be modified.
  6634. {
  6635. // customisable code goes here
  6636.  
  6637. return $rows;
  6638.  
  6639. } // _cm_post_getData
  6640.  
  6641. // ****************************************************************************
  6642. function _cm_post_insertMultiple ($rows)
  6643. // perform custom processing after multiple database records are inserted.
  6644. {
  6645. // customisable code goes here
  6646.  
  6647. return $rows;
  6648.  
  6649. } // _cm_post_insertMultiple
  6650.  
  6651. // ****************************************************************************
  6652. function _cm_post_insertOrUpdate ($fieldarray, $insert_count, $update_count)
  6653. // perform custom processing at end of insertOrUpdate() method.
  6654. {
  6655. // customisable code goes here
  6656.  
  6657. return $fieldarray;
  6658.  
  6659. } // _cm_post_insertOrUpdate
  6660.  
  6661. // ****************************************************************************
  6662. function _cm_post_insertRecord ($fieldarray)
  6663. // perform custom processing after database record has been inserted.
  6664. {
  6665. // customisable code goes here
  6666.  
  6667. return $fieldarray;
  6668.  
  6669. } // _cm_post_insertRecord
  6670.  
  6671. // ****************************************************************************
  6672. function _cm_post_lastRow ()
  6673. // perform custom processing after last record has been read.
  6674. {
  6675. $fieldarray = array();
  6676.  
  6677. // customisable code goes here
  6678.  
  6679. return $fieldarray;
  6680.  
  6681. } // _cm_post_fetchRow
  6682.  
  6683. // ****************************************************************************
  6684. function _cm_post_output ($string, $filename)
  6685. // perform any processing required after the output operation
  6686. {
  6687. // customisable code goes here
  6688.  
  6689. return $string;
  6690.  
  6691. } // _cm_post_output
  6692.  
  6693. // ****************************************************************************
  6694. function _cm_post_popupReturn ($fieldarray, $return_from, $select_array)
  6695. // perform any post-popup processing.
  6696. {
  6697. // customisable code goes here
  6698.  
  6699. return $fieldarray;
  6700.  
  6701. } // _cm_post_popupReturn
  6702.  
  6703. // ****************************************************************************
  6704. function _cm_post_search ($search, $selection)
  6705. // perform any post-search processing.
  6706. {
  6707. // customisable code goes here
  6708.  
  6709. return $search;
  6710.  
  6711. } // _cm_post_search
  6712.  
  6713. // ****************************************************************************
  6714. function _cm_post_updateLinkdata ($rows, $postarray)
  6715. // perform custom processing after multiple database records have been updated.
  6716. {
  6717. // customisable code goes here
  6718.  
  6719. return $rows;
  6720.  
  6721. } // _cm_post_updateLinkData
  6722.  
  6723. // ****************************************************************************
  6724. function _cm_post_updateMultiple ($rows)
  6725. // perform custom processing after multiple database records have been updated.
  6726. {
  6727. // customisable code goes here
  6728.  
  6729. return $rows;
  6730.  
  6731. } // _cm_post_updateMultiple
  6732.  
  6733. // ****************************************************************************
  6734. function _cm_post_updateRecord ($fieldarray, $old_data)
  6735. // perform custom processing after database record is updated.
  6736. {
  6737. // customisable code goes here
  6738.  
  6739. return $fieldarray;
  6740.  
  6741. } // _cm_post_updateRecord
  6742.  
  6743. // ****************************************************************************
  6744. function _cm_post_updateSelection ($selection, $replace)
  6745. // allow changes to be made after _cm_updateSelection method has been called.
  6746. {
  6747. // custom code goes here
  6748.  
  6749. return $selection;
  6750.  
  6751. } // _cm_post_updateSelection
  6752.  
  6753. // ****************************************************************************
  6754. function _cm_pre_cascadeDelete ($fieldarray)
  6755. // perform custom processing before database record is deleted as part of a
  6756. // cascade delete.
  6757. {
  6758. // customisable code goes here
  6759.  
  6760. return $fieldarray;
  6761.  
  6762. } // _cm_pre_cascadeDelete
  6763.  
  6764. // ****************************************************************************
  6765. function _cm_pre_deleteMultiple ($rows)
  6766. // perform custom processing before multiple database records are deleted.
  6767. // if anything is placed in $this->errors the delete will be terminated.
  6768. {
  6769. // customisable code goes here
  6770.  
  6771. return $rows;
  6772.  
  6773. } // _cm_pre_deleteMultiple
  6774.  
  6775. // ****************************************************************************
  6776. function _cm_pre_deleteRecord ($fieldarray)
  6777. // perform custom processing before database record is deleted.
  6778. // if anything is placed in $this->errors the deletion will be terminated.
  6779. {
  6780. // customisable code goes here
  6781.  
  6782. return $fieldarray;
  6783.  
  6784. } // _cm_pre_deleteRecord
  6785.  
  6786. // ****************************************************************************
  6787. function _cm_pre_eraseRecord ($fieldarray)
  6788. // perform custom processing before database record is erased.
  6789. // if anything is placed in $this->errors the erasure will be terminated.
  6790. {
  6791. // customisable code goes here
  6792.  
  6793. return $fieldarray;
  6794.  
  6795. } // _cm_pre_eraseRecord
  6796.  
  6797. // ****************************************************************************
  6798. function _cm_pre_getData ($where, $where_array, $fieldarray=null)
  6799. // perform custom processing before database record(s) are retrieved.
  6800. // (WHERE is supplied in two formats - string and array)
  6801. // $fieldarray may contain full details of the current record in the parent
  6802. // class, not just its primary key.
  6803. {
  6804. // customisable code goes here
  6805.  
  6806. // if (empty($this->sql_from)) {
  6807. // // construct default SELECT and FROM clauses using parent relations
  6808. // $this->sql_from = null;
  6809. // $this->sql_groupby = null;
  6810. // $this->sql_having = null;
  6811. // $this->sql_union = null;
  6812. // $this->sql_from = $this->_sqlForeignJoin($this->sql_select, $this->sql_from, $this->parent_relations);
  6813. // } // if
  6814.  
  6815. return $where;
  6816.  
  6817. } // _cm_pre_getData
  6818.  
  6819. // ****************************************************************************
  6820. function _cm_pre_insertMultiple ($rows)
  6821. // perform custom processing before multiple database records are inserted.
  6822. // if anything is placed in $this->errors the insert will be terminated.
  6823. {
  6824. // customisable code goes here
  6825.  
  6826. return $rows;
  6827.  
  6828. } // _cm_pre_insertMultiple
  6829.  
  6830. // ****************************************************************************
  6831. function _cm_pre_insertOrUpdate ($rows)
  6832. // perform custom processing at start of insertOrUpdate() method.
  6833. // if anything is placed in $this->errors the operation will be terminated.
  6834. {
  6835. // customisable code goes here
  6836.  
  6837. return $rows;
  6838.  
  6839. } // _cm_pre_insertOrUpdate
  6840.  
  6841. // ****************************************************************************
  6842. function _cm_pre_insertRecord ($fieldarray)
  6843. // perform custom processing before database record is inserted.
  6844. // if anything is placed in $this->errors the insert will be terminated.
  6845. {
  6846. // customisable code goes here
  6847.  
  6848. return $fieldarray;
  6849.  
  6850. } // _cm_pre_insertRecord
  6851.  
  6852. // ****************************************************************************
  6853. function _cm_pre_output ($filename)
  6854. // perform any processing required before the output operation.
  6855. // $filename is only available if the output is being sent to a disk file.
  6856. {
  6857. // customisable code goes here
  6858.  
  6859. return $filename;
  6860.  
  6861. } // _cm_pre_output
  6862.  
  6863. // ****************************************************************************
  6864. function _cm_pre_updateLinkdata ($rows, &$postarray)
  6865. // $rows is an array of field data (multiple rows).
  6866. // $postarray is an array of entries which have been selected.
  6867. // NOTE: $postarray is passed BY REFERENCE so that it may be modified.
  6868. // NOTE: $rows starts at 0, $select starts at 1.
  6869. // if anything is placed in $this->errors the update will be terminated.
  6870. {
  6871. // customisable code goes here
  6872.  
  6873. return $rows;
  6874.  
  6875. } // _cm_pre_updateLinkData
  6876.  
  6877. // ****************************************************************************
  6878. function _cm_pre_updateMultiple ($rows)
  6879. // perform custom processing before multiple database records are updated.
  6880. {
  6881. // customisable code goes here
  6882.  
  6883. return $rows;
  6884.  
  6885. } // _cm_pre_updateMultiple
  6886.  
  6887. // ****************************************************************************
  6888. function _cm_pre_updateRecord ($fieldarray)
  6889. // perform custom processing before database record is updated.
  6890. // errors are added to $this->errors.
  6891. {
  6892. //$this->row_locks = 'SH'; // shared
  6893. //$this->row_locks = 'EX'; // exclusive
  6894. //$this->row_locks_supp = '?' // DBMS-specific
  6895.  
  6896. // reuse existing SELECT statement in _dml_ReadBeforeUpdate() method
  6897. //$this->reuse_previous_select = true;
  6898.  
  6899. return $fieldarray;
  6900.  
  6901. } // _cm_pre_updateRecord
  6902.  
  6903. // ****************************************************************************
  6904. function _cm_pre_updateSelection ($selection, $replace)
  6905. // allow changes to be made before _cm_updateSelection method is called.
  6906. {
  6907. // custom code goes here
  6908.  
  6909. return $selection;
  6910.  
  6911. } // _cm_pre_updateSelection
  6912.  
  6913. // ****************************************************************************
  6914. function _cm_reset ($where)
  6915. // perform custom processing after RESET button is pressed.
  6916. {
  6917. // customisable code goes here
  6918.  
  6919. return;
  6920.  
  6921. } // _cm_reset
  6922.  
  6923. // ****************************************************************************
  6924. function _cm_restart ($pattern_id, $zone, $return_from, $return_action, $return_string)
  6925. // script is being restarted after running a child form, so check for further action.
  6926. {
  6927. // customisable code goes here
  6928.  
  6929. return;
  6930.  
  6931. } // _cm_restart
  6932.  
  6933. // ****************************************************************************
  6934. function _cm_setJavaScript ($javascript)
  6935. // insert any javascript to be included in the <HEAD> or <BODY> elements.
  6936. {
  6937.  
  6938. // customisable code goes here
  6939. //$javascript['head'][]['file'] = '...';
  6940. //$javascript['head'][]['code'] = '...';
  6941.  
  6942. //$javascript['body']['onload'] = '...';
  6943. //$javascript['body']['onunload'] = '...';
  6944.  
  6945. //$javascript['tbody']['onload'] = '...';
  6946. //$javascript['tbody']['onunload'] = '...';
  6947.  
  6948. //$javascript['script']['whatever'] = '...';
  6949.  
  6950. return $javascript;
  6951.  
  6952. } // _cm_setJavaScript
  6953.  
  6954. // ****************************************************************************
  6955. function _cm_setScrollArray ($where, $where_array)
  6956. // construct an array of primary keys to scroll through
  6957. {
  6958. $array = array();
  6959.  
  6960. $array = splitWhereByRow($where); // default - replace with custom code
  6961.  
  6962. return $array;
  6963.  
  6964. } // _cm_setScrollArray
  6965.  
  6966. // ****************************************************************************
  6967. function _cm_unFormatData ($fieldarray)
  6968. // remove custom formatting before values are passed to the database.
  6969. {
  6970. // customisable code goes here
  6971.  
  6972. return $fieldarray;
  6973.  
  6974. } // _cm_unFormatData
  6975.  
  6976. // ****************************************************************************
  6977. function _cm_updateFieldarray ($fieldarray, $postarray, $rownum)
  6978. // allow object to deal with any changes POSTed from the form.
  6979. // $fieldarray contains current data from one row.
  6980. // $postarray contains any changes made in the form for this row.
  6981. // $rownum identifies which row is being processed
  6982. {
  6983. // customisable code goes here
  6984.  
  6985. return $fieldarray;
  6986.  
  6987. } // _cm_updateFieldarray
  6988.  
  6989. // ****************************************************************************
  6990. function _cm_updateSelection ($selection, $replace)
  6991. // update multiple rows in a single operation.
  6992. {
  6993. if ($this->dbname == 'default' AND $this->tablename == 'default') {
  6994. // possibly called from custom processing object, so do nothing
  6995. return;
  6996. } // if
  6997.  
  6998. if (!is_string($selection) OR empty($replace)) {
  6999. // this combination is not valid
  7000. return;
  7001. } else {
  7002. // this is the default code, which may be replaced if necessary
  7003. $count = $this->_dml_updateSelection($selection, $replace);
  7004.  
  7005. // '$count records were updated in $tablename'
  7006. return $this->getLanguageText('sys0006', $count, strtoupper($this->tablename));
  7007. } // if
  7008.  
  7009. } // _cm_updateSelection
  7010.  
  7011. // ****************************************************************************
  7012. function _cm_validateDelete ($rowdata, $parent_table)
  7013. // verify that the selected record can be deleted.
  7014. // ($parent_table is only used in a cascade delete)
  7015. // if anything is placed in $this->errors the delete will be terminated.
  7016. {
  7017. // customisable code goes here
  7018.  
  7019. return;
  7020.  
  7021. } // _cm_validateDelete
  7022.  
  7023. // ****************************************************************************
  7024. function _cm_validateInsert ($rowdata)
  7025. // perform custom validation before an insert.
  7026. // if anything is placed in $this->errors the insert will be terminated.
  7027. {
  7028. // customisable code goes here
  7029.  
  7030. return $rowdata;
  7031.  
  7032. } // _cm_validateInsert
  7033.  
  7034. // ****************************************************************************
  7035. function _cm_validateSearch ($fieldarray)
  7036. // perform custom validation on data entered via a search screen.
  7037. // put any errors into $this->errors.
  7038. {
  7039. // customisable code goes here
  7040.  
  7041. return $fieldarray;
  7042.  
  7043. } // _cm_validateSearch
  7044.  
  7045. // ****************************************************************************
  7046. function _cm_validateUpdate ($fieldarray, $originaldata)
  7047. // perform custom validation before update.
  7048. // if anything is placed in $this->errors the update will be terminated.
  7049. {
  7050. // customisable code goes here
  7051.  
  7052. return $fieldarray;
  7053.  
  7054. } // _cm_validateUpdate
  7055.  
  7056. // ****************************************************************************
  7057. // methods beginning with '_ddl_' are for calling the Database Access object
  7058. // (for commands using the Data Definition Language)
  7059. // ****************************************************************************
  7060. function _ddl_getColumnSpecs ()
  7061. // obtain column specifications.
  7062. {
  7063. $DDL =& $this->_getDBMSengine($this->dbname);
  7064.  
  7065. $array = $DDL->ddl_getColumnSpecs();
  7066.  
  7067. return $array;
  7068.  
  7069. } // _ddl_getColumnSpecs
  7070.  
  7071. // ****************************************************************************
  7072. function _ddl_showColumns($dbname, $tablename)
  7073. // obtain a list of column names for the selected database table.
  7074. {
  7075. $DDL =& $this->_getDBMSengine($dbname);
  7076.  
  7077. $array = $DDL->ddl_showColumns($DDL->dbname, $tablename);
  7078.  
  7079. return $array;
  7080.  
  7081. } // _ddl_showColumns
  7082.  
  7083. // ****************************************************************************
  7084. function _ddl_showCreateTable ($dbname, $tablename)
  7085. // obtain a list of column names for the selected database table.
  7086. {
  7087. $DDL =& $this->_getDBMSengine($dbname);
  7088.  
  7089. $array = $DDL->ddl_showCreateTable($DDL->dbname, $tablename);
  7090.  
  7091. return $array;
  7092.  
  7093. } // _ddl_showCreateTable
  7094.  
  7095. // ****************************************************************************
  7096. function _ddl_showDatabases ($dbprefix)
  7097. // obtain a list of existing database names.
  7098. {
  7099. $DDL =& $this->_getDBMSengine($this->dbname);
  7100.  
  7101. $array = $DDL->ddl_showDatabases($dbprefix);
  7102.  
  7103. return $array;
  7104.  
  7105. } // _ddl_showDatabases
  7106.  
  7107. // ****************************************************************************
  7108. function _ddl_showTables ($dbname)
  7109. // obtain a list of table names for the selected database.
  7110. {
  7111. $DDL =& $this->_getDBMSengine($dbname);
  7112.  
  7113. $array = $DDL->ddl_showTables($DDL->dbname);
  7114.  
  7115. return $array;
  7116.  
  7117. } // _ddl_showTables
  7118.  
  7119. // ****************************************************************************
  7120. function _ddl_showTableKeys ($dbname, $tablename)
  7121. // obtain a list of existing database names.
  7122. {
  7123. $DDL =& $this->_getDBMSengine($dbname);
  7124.  
  7125. $array = $DDL->ddl_showTableKeys($DDL->dbname, $tablename);
  7126.  
  7127. return $array;
  7128.  
  7129. } // _ddl_showTableKeys
  7130.  
  7131. // ****************************************************************************
  7132. // methods beginning with '_dml_' are for calling the Database Access object
  7133. // (for commands using the Data Manipulation Language)
  7134. // ****************************************************************************
  7135. function _dml_deleteRecord ($fieldarray)
  7136. // delete the record whose primary key is contained within $fieldarray.
  7137. {
  7138. if (empty($fieldarray)) {
  7139. return; // nothing to delete
  7140. } // if
  7141.  
  7142. $DML =& $this->_getDBMSengine($this->dbname);
  7143.  
  7144. $DML->fieldspec = $this->fieldspec;
  7145. $DML->audit_logging = $this->audit_logging;
  7146. $DML->primary_key = $this->getPkeyNames();
  7147.  
  7148. // remove any non-database fields from input array
  7149. foreach ($fieldarray as $field => $fieldvalue) {
  7150. // check that $field exists in $fieldspec array
  7151. if (!array_key_exists($field, $DML->fieldspec)) {
  7152. // it does not (like the SUBMIT button, for example), so remove it
  7153. unset($fieldarray[$field]);
  7154. } // if
  7155. } // foreach
  7156.  
  7157. $DML->deleteRecord($this->dbname_server, $this->tablename, $fieldarray);
  7158.  
  7159. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7160. $this->numrows = $DML->getNumRows();
  7161.  
  7162. return;
  7163.  
  7164. } // _dml_deleteRecord
  7165.  
  7166. // ****************************************************************************
  7167. function _dml_adjustWhere ($string_in)
  7168. // the DBMS may require different escape characters, so adjust as necessary.
  7169. {
  7170. $DML =& $this->_getDBMSengine($this->dbname);
  7171.  
  7172. if (method_exists($DML, 'adjustWhere')) {
  7173. $string_out = $DML->adjustWhere($string_in);
  7174. } else {
  7175. $string_out = $string_in;
  7176. } // if
  7177.  
  7178. return $string_out;
  7179.  
  7180. } // _dml_adjustWhere
  7181.  
  7182. // ****************************************************************************
  7183. function _dml_deleteSelection ($selection, $from=null, $using=null, $limit=0)
  7184. // delete a selection of records in a single operation.
  7185. {
  7186. $DML =& $this->_getDBMSengine($this->dbname);
  7187.  
  7188. $DML->fieldspec = $this->fieldspec;
  7189. $DML->audit_logging = $this->audit_logging;
  7190.  
  7191. if (!$this->audit_logging OR defined('TRANSIX_NO_AUDIT') OR defined('NO_AUDIT_LOGGING')) {
  7192. // no audit logging, so delete everything in one operation
  7193. $count = $DML->deleteSelection($this->dbname_server, $this->tablename, $selection, $from, $using);
  7194. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7195. } else {
  7196. $this->sqlSelectInit();
  7197. $rows_per_page = $this->rows_per_page; // save
  7198. $this->setRowsPerPage($limit);
  7199. // audit logging is ON, so fetch everything and delete one row at a time
  7200. $resource = $this->_dml_getData_serial($selection);
  7201. $this->setRowsPerPage($rows_per_page); // restore
  7202. $count = $this->numrows;
  7203. $errors = array();
  7204. while ($row = $this->fetchRow($resource)) {
  7205. $this->deleteRecord($row);
  7206. $errors = array_merge($this->getErrors(), $errors);
  7207. } // while
  7208. $this->errors = $errors;
  7209. } // if
  7210.  
  7211. $this->numrows = $count;
  7212.  
  7213. return $count;
  7214.  
  7215. } // _dml_deleteSelection
  7216.  
  7217. // ****************************************************************************
  7218. function _dml_free_result ($resource)
  7219. // Get count of recors which match criteria in $where.
  7220. {
  7221. $DML =& $this->_getDBMSengine($this->dbname);
  7222.  
  7223. $result = $DML->free_result($this->dbname_server, $resource);
  7224.  
  7225. return $result;
  7226.  
  7227. } // _dml_free_result
  7228.  
  7229. // ****************************************************************************
  7230. function _dml_getCount ($where)
  7231. // Get count of recors which match criteria in $where.
  7232. {
  7233. $DML =& $this->_getDBMSengine($this->dbname);
  7234.  
  7235. $count = $DML->getCount($this->dbname_server, $this->tablename, $where);
  7236.  
  7237. if (is_null($count)) {
  7238. $count = 0;
  7239. } // if
  7240.  
  7241. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7242.  
  7243. return $count;
  7244.  
  7245. } // _dml_getCount
  7246.  
  7247. // ****************************************************************************
  7248. function _dml_getData ($where, $raw=false)
  7249. // Get data from the specified database table.
  7250. // Results may be affected by $where and $pageno.
  7251. {
  7252. $DML =& $this->_getDBMSengine($this->dbname);
  7253.  
  7254. $DML->fieldspec = $this->fieldspec;
  7255. $DML->pageno = $this->pageno;
  7256. $DML->rows_per_page = $this->rows_per_page;
  7257. $DML->sql_select = $this->sql_select;
  7258. $DML->sql_from = $this->sql_from;
  7259. $DML->sql_groupby = $this->sql_groupby;
  7260. $DML->sql_having = $this->sql_having;
  7261.  
  7262. if (!empty($this->sql_union)) {
  7263. if (substr(trim($this->sql_union), 0, 1) != '(') {
  7264. // this string must be enclosed in '(' and ')'
  7265. $this->sql_union = '('.trim($this->sql_union).')';
  7266. } // if
  7267. $DML->sql_union = $this->sql_union;
  7268. } // if
  7269.  
  7270. $DML->sql_orderby = $this->getOrderBy();
  7271. $DML->sql_orderby_seq = $this->sql_orderby_seq;
  7272. if (!empty($DML->sql_orderby) AND $raw === true) {
  7273. $DML->sql_orderby = validateSortItem2 ($DML->sql_orderby, $DML->sql_select, $DML->fieldspec);
  7274. } // if
  7275. $this->prev_sql_orderby = $DML->sql_orderby;
  7276.  
  7277. $DML->setRowLocks($this->row_locks);
  7278.  
  7279. $array = $DML->getData($this->dbname_server, $this->tablename, $where);
  7280.  
  7281. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7282. $this->numrows = $DML->getNumRows();
  7283. $this->pageno = $DML->getPageNo();
  7284. $this->lastpage = $DML->getLastPage();
  7285.  
  7286. $this->sql_union = null;
  7287.  
  7288. return $array;
  7289.  
  7290. } // _dml_getData
  7291.  
  7292. // ****************************************************************************
  7293. function _dml_getData_serial ($where=null, $rdc_limit=null, $rdc_offset=null, $unbuffered_query=false)
  7294. // Issue an SQL query and return result, not an array of data.
  7295. // Individual rows will be returned using the fetchRow() method.
  7296. {
  7297. $this->errors = array();
  7298.  
  7299. $DML =& $this->_getDBMSengine($this->dbname, $unbuffered_query);
  7300.  
  7301. $DML->fieldspec = $this->fieldspec;
  7302. $DML->pageno = $this->pageno;
  7303. $DML->rows_per_page = $this->rows_per_page;
  7304. $DML->sql_select = $this->sql_select;
  7305. $DML->sql_from = $this->sql_from;
  7306. $DML->sql_groupby = $this->sql_groupby;
  7307. $DML->sql_having = $this->sql_having;
  7308.  
  7309. if (!empty($this->sql_union)) {
  7310. if (substr(trim($this->sql_union), 0, 1) != '(') {
  7311. // this string must be enclosed in '(' and ')'
  7312. $this->sql_union = '('.trim($this->sql_union).')';
  7313. } // if
  7314. $DML->sql_union = $this->sql_union;
  7315. } // if
  7316.  
  7317. $DML->sql_orderby = $this->getOrderBy();
  7318. $DML->sql_orderby_seq = $this->sql_orderby_seq;
  7319.  
  7320. $result = $DML->getData_serial($this->dbname_server, $this->tablename, $where, $rdc_limit, $rdc_offset);
  7321.  
  7322. $this->numrows = $DML->getNumRows();
  7323.  
  7324. return $result;
  7325.  
  7326. } // _dml_getData_serial
  7327.  
  7328. // ****************************************************************************
  7329. function _dml_getEnum ($item)
  7330. // Get the details of an ENUM item from the database.
  7331. {
  7332. $DML =& $this->_getDBMSengine($this->dbname);
  7333.  
  7334. $array = $DML->getEnum($this->dbname_server, $this->tablename, $item);
  7335.  
  7336. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7337.  
  7338. return $array;
  7339.  
  7340. } // _dml_getEnum
  7341.  
  7342. // ****************************************************************************
  7343. function _dml_insertRecord ($fieldarray)
  7344. // insert a record using the contents of $fieldarray.
  7345. {
  7346. $DML =& $this->_getDBMSengine($this->dbname);
  7347.  
  7348. // use ORIGINAL, not CURRENT specifications for this database table
  7349. $DML->fieldspec = $this->getFieldSpec_original();
  7350. // include other important variables
  7351. $DML->primary_key = $this->getPkeyNames();
  7352. $DML->unique_keys = $this->unique_keys;
  7353. $DML->audit_logging = $this->audit_logging;
  7354. $DML->no_duplicate_error = $this->no_duplicate_error;
  7355. $DML->retry_on_duplicate_key = $this->retry_on_duplicate_key;
  7356. $DML->update_on_duplicate_key = $this->update_on_duplicate_key;
  7357. $DML->allow_db_function = $this->allow_db_function;
  7358.  
  7359. // remove any non-database fields from input array
  7360. foreach ($fieldarray as $field => $fieldvalue) {
  7361. // check that $field exists in $fieldspec array
  7362. if (!array_key_exists($field, $DML->fieldspec)) {
  7363. // it does not (like the SUBMIT button, for example), so remove it
  7364. unset ($fieldarray[$field]);
  7365. } // if
  7366. } // foreach
  7367.  
  7368. $array = $DML->insertRecord($this->dbname_server, $this->tablename, $fieldarray);
  7369.  
  7370. $this->errors = array_merge($this->errors, $DML->getErrors());
  7371. if (method_exists($DML, 'getMessages')) {
  7372. $this->messages = array_merge($this->messages, $DML->getMessages());
  7373. } // if
  7374. $this->numrows = $DML->numrows;
  7375. if ($this->numrows > 0) {
  7376. $this->insert_count = $this->numrows;
  7377. } else {
  7378. $this->unchanged_count = 1;
  7379. } // if
  7380.  
  7381. $this->query = $DML->query; // save this in case trigger_error() is called
  7382.  
  7383. $this->retry_on_duplicate_key = false;
  7384. $this->update_on_duplicate_key = false;
  7385. $this->allow_db_function = array();
  7386.  
  7387. return $array;
  7388.  
  7389. } // _dml_insertRecord
  7390.  
  7391. // ****************************************************************************
  7392. function _dml_multiQuery ($query)
  7393. // perform one or more SQL queries in a single step. (DEPRECATED)
  7394. {
  7395. $result = $this->executeQuery($query);
  7396.  
  7397. return $result;
  7398.  
  7399. } // _dml_multiQuery
  7400.  
  7401. // ****************************************************************************
  7402. function _dml_ReadBeforeUpdate ($where, $reuse_previous_select=false)
  7403. // Read a single record just before it is updated.
  7404. // The primary key should be supplied in $where.
  7405. {
  7406. $DML =& $this->_getDBMSengine($this->dbname);
  7407.  
  7408. $DML->fieldspec = $this->fieldspec;
  7409. $DML->pageno = 1;
  7410. $DML->rows_per_page = 0;
  7411. if (is_True($reuse_previous_select)) {
  7412. if (empty($this->sql_select)) {
  7413. // has not been constructed yet, so do it now
  7414. $where_array = where2array($where);
  7415. $where = $this->_cm_pre_getData ($where, $where_array, $this->fieldarray);
  7416. } // if
  7417. $having_array = array();
  7418. $where = qualifyWhere($where, $this->tablename, $this->fieldspec, $this->sql_from, null, null, $having_array);
  7419. // use previous SELECT statement
  7420. $DML->sql_select = $this->sql_select;
  7421. if (!empty($DML->sql_select)) {
  7422. // ensure this selects ALL fields from the primary table
  7423. if (!preg_match('/' .$this->tablename .'\.\*/', $DML->sql_select)) {
  7424. $DML->sql_select = $this->tablename .'.*, ' .$DML->sql_select;
  7425. } // if
  7426. } // if
  7427. $DML->sql_from = $this->sql_from;
  7428. $DML->sql_groupby = $this->sql_groupby;
  7429. $DML->sql_having = $this->sql_having;
  7430. $DML->sql_orderby = $this->getOrderBy();
  7431. $DML->sql_orderby_seq = $this->sql_orderby_seq;
  7432. } else {
  7433. // construct default SELECT statement
  7434. $DML->sql_select = NULL;
  7435. $DML->sql_from = NULL;
  7436. $DML->sql_groupby = NULL;
  7437. $DML->sql_having = NULL;
  7438. $DML->sql_orderby = NULL;
  7439. $DML->sql_orderby_seq = NULL;
  7440. } // if
  7441. $DML->setRowLocks('EX'); // lock this row (exclusive)
  7442.  
  7443. $array = $DML->getData($this->dbname_server, $this->tablename, $where);
  7444.  
  7445. $this->errors = array_merge($DML->getErrors(), $this->errors);
  7446. $this->numrows = $DML->getNumRows();
  7447.  
  7448. return $array;
  7449.  
  7450. } // _dml_ReadBeforeUpdate
  7451.  
  7452. // ****************************************************************************
  7453. function _dml_updateRecord ($fieldarray, $oldarray, $where=null)
  7454. // update the record contained in $fieldarray.
  7455. {
  7456. $DML =& $this->_getDBMSengine($this->dbname);
  7457.  
  7458. // use ORIGINAL, not CURRENT specifications for this database table
  7459. $DML->fieldspec = $this->getFieldSpec_original();
  7460. $DML->primary_key = $this->getPkeyNames();
  7461. $DML->unique_keys = $this->unique_keys;
  7462. $DML->audit_logging = $this->audit_logging;
  7463. $DML->allow_db_function = $this->allow_db_function;
  7464.  
  7465. // remove any non-database fields from input array
  7466. foreach ($fieldarray as $field => $fieldvalue) {
  7467. // check that $field exists in $fieldspec array
  7468. if (!array_key_exists($field, $DML->fieldspec)) {
  7469. // it does not (like the SUBMIT button, for example), so remove it
  7470. unset($fieldarray[$field]);
  7471. } elseif (isset($DML->fieldspec[$field]['noedit']) OR isset($DML->fieldspec[$field]['nodisplay'])) {
  7472. // this field is not editable, so do not update it
  7473. //unset($fieldarray[$field]);
  7474. } elseif (is_array($this->noedit_array) AND array_key_exists($field, $this->noedit_array)) {
  7475. // this field is not editable, so do not update it
  7476. unset($fieldarray[$field]);
  7477. } // if
  7478. } // foreach
  7479.  
  7480. $array = $DML->updateRecord($this->dbname_server, $this->tablename, $fieldarray, $oldarray, $where);
  7481.  
  7482. $this->errors = array_merge($this->errors, $DML->getErrors());
  7483. if (method_exists($DML, 'getMessages')) {
  7484. $this->messages = array_merge($this->messages, $DML->getMessages());
  7485. } // if
  7486. $this->numrows = $DML->getNumRows();
  7487.  
  7488. $this->query = $DML->query; // save this in case trigger_error() is called
  7489.  
  7490. $this->allow_db_function = array();
  7491.  
  7492. return $array;
  7493.  
  7494. } // _dml_updateRecord
  7495.  
  7496. // ****************************************************************************
  7497. function _dml_updateSelection ($selection, $replace, $limit=0)
  7498. // update a selection of records in a single operation.
  7499. {
  7500. $DML =& $this->_getDBMSengine($this->dbname);
  7501.  
  7502. $DML->fieldspec = $this->fieldspec;
  7503. $DML->audit_logging = $this->audit_logging;
  7504. $DML->allow_db_function = $this->allow_db_function;
  7505.  
  7506. if (!$this->audit_logging) {
  7507. // no audit logging, so update everything in one operation
  7508. $count = $DML->updateSelection($this->dbname_server, $this->tablename, $replace, $selection);
  7509. $this->errors = array_merge($this->errors, $DML->getErrors());
  7510. if (method_exists($DML, 'getMessages')) {
  7511. $this->messages = array_merge($this->messages, $DML->getMessages());
  7512. } // if
  7513. } else {
  7514. $this->sqlSelectInit();
  7515. $rows_per_page = $this->rows_per_page; // save
  7516. $this->setRowsPerPage($limit);
  7517. // audit logging is ON, so fetch everything and update one row at a time
  7518. $resource = $this->_dml_getData_serial($selection);
  7519. $this->setRowsPerPage($rows_per_page); // restore
  7520. $count = 0;
  7521. while ($row = $this->fetchRow($resource)) {
  7522. $update = where2array($replace);
  7523. $update = array_merge($row, $update);
  7524. // construct primary key for original record as this may be changed in this update
  7525. $where = array2where($row, $this->getPkeyNames());
  7526. $this->_dml_updateRecord($update, $row, $where);
  7527. if ($this->errors) {
  7528. break;
  7529. } // if
  7530. $count += $this->numrows;
  7531. } // while
  7532. } // if
  7533.  
  7534. $this->numrows = $count;
  7535.  
  7536. return $count;
  7537.  
  7538. } // _dml_updateSelection
  7539.  
  7540. // ****************************************************************************
  7541. function _examineWorkflow ($input)
  7542. // a task has just completed, so ...
  7543. // find out if this task/context starts a new workflow instance (case),
  7544. // or is a workitem within an existing workflow instance.
  7545. {
  7546. $this->errors = array();
  7547.  
  7548. if (is_array($input)) {
  7549. // context is the primary key of the current record
  7550. $context = array2where($input, $this->getPkeyNames(), false, true);
  7551. $fieldarray = $input;
  7552. } else {
  7553. $context = $input;
  7554. $fieldarray = where2array($context);
  7555. } // if
  7556.  
  7557. $wf_case_id = $this->wf_case_id;
  7558. $wf_workitem_id = $this->wf_workitem_id;
  7559. if (!empty($this->wf_context)) {
  7560. // replace current context with saved workitem context
  7561. $context = $this->wf_context;
  7562. } // if
  7563.  
  7564. if (empty($context)) {
  7565. return $this->errors;
  7566. } // if
  7567.  
  7568. // interface with the workflow engine
  7569. $workflow =& RDCsingleton::getInstance('workflow_engine');
  7570.  
  7571. // look to see if this task is a workitem within an existing workflow case
  7572. if (isset($wf_case_id) and isset($wf_workitem_id)) {
  7573. // yes it is, so mark it as finished
  7574. $workflow->finishWorkItem($wf_case_id, $wf_workitem_id, $context, $fieldarray);
  7575. if ($workflow->errors) {
  7576. $this->errors = array_merge($this->errors, $workflow->getErrors());
  7577. return $this->errors;
  7578. } // if
  7579. return;
  7580. } // if
  7581.  
  7582. // look to see if this task requires the starting of a new workflow case
  7583. $wf_case_id = $workflow->startWorkflowCase($GLOBALS['task_id'], $context);
  7584. if ($workflow->errors) {
  7585. $this->errors = array_merge($this->errors, $workflow->getErrors());
  7586. return $this->errors;
  7587. } // if
  7588.  
  7589. unset($workflow);
  7590.  
  7591. return $this->errors;
  7592.  
  7593. } // _examineWorkflow
  7594.  
  7595. // ****************************************************************************
  7596. function _examineWorkflowInstance ($where)
  7597. // a task has just started, so ...
  7598. // look to see if this task/context is a workitem within a workflow instance,
  7599. // and if it is then set the appropriate variables (for use in finishWorkItem())
  7600. {
  7601. if (empty($where)) {
  7602. return; // no context yet, so ignore
  7603. } // if
  7604.  
  7605. $this->errors = array();
  7606.  
  7607. // look for a workitem that matches this task_id and context
  7608. $dbworkitem =& RDCsingleton::getInstance('wf_workitem');
  7609.  
  7610. $context = addslashes(trim($where, ' ()'));
  7611. //$workitem_where = "task_id='{$GLOBALS['task_id']}' AND context='$context'";
  7612. // use 'LIKE' as the passed context may have been trimmed
  7613. $workitem_where = "task_id='{$GLOBALS['task_id']}' AND context LIKE '$context%'";
  7614. // if (isset($GLOBALS['batch']) AND is_True($GLOBALS['batch'])) {
  7615. // $workitem_where .= " AND workitem_status='IP'"; // 'in progress'
  7616. // } else {
  7617. // $workitem_where .= " AND workitem_status='EN'"; // 'enabled'
  7618. // } // if
  7619. $workitem_where .= " AND workitem_status IN ('EN','IP')"; // 'in progress' or 'enabled'
  7620. $workitem_data = $dbworkitem->getData($workitem_where);
  7621. if ($dbworkitem->errors) {
  7622. $this->errors = array_merge($this->errors, $dbworkitem->getErrors());
  7623. return;
  7624. } // if
  7625.  
  7626. // if nothing found exit now
  7627. if ($dbworkitem->numrows == 0) {
  7628. unset($dbworkitem);
  7629. return;
  7630. } // if
  7631.  
  7632. // use only first item
  7633. reset($workitem_data); // fix for version 4.4.1
  7634. $workitem_data = $workitem_data[key($workitem_data)];
  7635.  
  7636. if (isset($GLOBALS['batch']) AND is_True($GLOBALS['batch'] OR $workitem_data['workitem_status'] == 'IP')) {
  7637. // ignore next check
  7638. } else {
  7639. // check that workitem has been assigned to one of this user's roles
  7640. $role_list = explode(',', $_SESSION['role_list']);
  7641. //if ($workitem_data['role_id'] != $_SESSION['role_id']) {
  7642. if (!in_array("'{$workitem_data['role_id']}'", $role_list)) {
  7643. $result = $dbworkitem->rollback();
  7644. $workitem_data['user_id'] = null;
  7645. $workitem_data = $dbworkitem->updateRecord($workitem_data);
  7646. if ($dbworkitem->errors) {
  7647. $result = $dbworkitem->rollback();
  7648. } else {
  7649. $result = $dbworkitem->commit();
  7650. } // if
  7651. //scriptPrevious("This task has been assigned to role " .$workitem_data['role_id']);
  7652. $batch_errors = scriptPrevious($this->getLanguageText('sys0014', $workitem_data['role_id']));
  7653. return $batch_errors;
  7654. } // if
  7655.  
  7656. if (empty($workitem_data['user_id'])) {
  7657. // no user assigned to this workitem, so assign to this user
  7658. if (!empty($this->wf_user_id)) {
  7659. $workitem_data['user_id'] = $this->wf_user_id; // use specified value
  7660. } else {
  7661. $workitem_data['user_id'] = $_SESSION['logon_user_id'];
  7662. } // if
  7663. $workitem_data = $dbworkitem->updateRecord($workitem_data);
  7664. if ($dbworkitem->errors) {
  7665. $this->errors = array_merge($this->errors, $dbworkitem->getErrors());
  7666. return;
  7667. } // if
  7668. } else {
  7669. // check that workitem has been assigned to this user
  7670. if ($workitem_data['user_id'] != $_SESSION['logon_user_id']) {
  7671. //scriptPrevious("This task has been assigned to user " .$workitem_data['user_id']);
  7672. $batch_errors = scriptPrevious($this->getLanguageText('sys0015', $workitem_data['user_id']));
  7673. return $batch_errors;
  7674. } // if
  7675. } // if
  7676. } // if
  7677.  
  7678. // workitem exists, so store details
  7679. $this->wf_case_id = $workitem_data['case_id'];
  7680. $this->wf_workitem_id = $workitem_data['workitem_id'];
  7681.  
  7682. if ($workitem_data['context'] != stripslashes($context)) {
  7683. // current primary key does not match workitem context, so ...
  7684. // workitem context must be saved and carried forward
  7685. $this->wf_context = $workitem_data['context'];
  7686. } else {
  7687. $this->wf_context = null;
  7688. } // if
  7689.  
  7690. unset($dbworkitem);
  7691.  
  7692. return;
  7693.  
  7694. } // _examineWorkflowInstance
  7695.  
  7696. // ****************************************************************************
  7697. function _extract_custom_fields ($rowdata)
  7698. // look for $rowdata['custom_fields']['field'] = array('name' => 'x', 'value' => 'y')
  7699. // and extract entries to $rowdata['x'] => 'y'
  7700. // this will make it easier to process any extra fields in subsequent code.
  7701. {
  7702. if (isset($rowdata['custom_fields']) AND isset($rowdata['custom_fields']['field'])) {
  7703. if (is_string(key($rowdata['custom_fields']['field']))) {
  7704. // only one entry, so set it to undex zero
  7705. $array[] = $rowdata['custom_fields']['field'];
  7706. $rowdata['custom_fields']['field'] = $array;
  7707. } // if
  7708. foreach ($rowdata['custom_fields']['field'] as $index => $data) {
  7709. if (is_array($data)) {
  7710. if (array_key_exists('name', $data) AND array_key_exists('value', $data)) {
  7711. $rowdata[$data['name']] = $data['value'];
  7712. } // if
  7713. } // if
  7714. } // foreach
  7715. } // if
  7716.  
  7717. unset($rowdata['custom_fields']); // values have been extracted, so this is now redundant
  7718.  
  7719. return $rowdata;
  7720.  
  7721. } // _extract_custom_fields
  7722.  
  7723. // ****************************************************************************
  7724. function _getCustomProcessingObject ()
  7725. // look for an optional file containing code for custom processing.
  7726. // this exists in the 'custom-processing' directory with a 'cp_' prefix.
  7727. {
  7728. if (empty($GLOBALS['project_code'])) {
  7729. return; // identity of subfolder not defined, so exit
  7730. } // if
  7731.  
  7732. $dirname = dirname($this->dirname) ."/classes/custom-processing/{$GLOBALS['project_code']}/";
  7733. $fname = $dirname .'cp_' .get_class($this) .'.class.inc';
  7734. if (file_exists($fname)) {
  7735. // ** this code causes a hang in PHP 4 **
  7736. //$class_name = "custom-processing/{$GLOBALS['project_code']}/cp_" .get_class($this);
  7737. //$this->custom_processing_object =& RDCsingleton::getInstance($class_name);
  7738. // include reference to calling object in the custom object
  7739. //$this->custom_processing_object->calling_object =& $this;
  7740. // **
  7741.  
  7742. $class_name = 'cp_' .get_class($this);
  7743. if (!class_exists($class_name)) {
  7744. require_once($fname);
  7745. } // if
  7746. if (class_exists($class_name)) {
  7747. $cpo = new $class_name;
  7748.  
  7749. // make object variables available in custom object
  7750. $cpo->dirname =& $this->dirname;
  7751. $cpo->dirname_dict =& $this->dirname;
  7752. $cpo->dbname =& $this->dbname;
  7753. $cpo->dbname_server =& $this->dbname_server;
  7754. $cpo->tablename =& $this->tablename;
  7755. $cpo->fieldspec =& $this->fieldspec;
  7756. $cpo->primary_key =& $this->primary_key;
  7757. $cpo->unique_keys =& $this->unique_keys;
  7758. $cpo->child_relations =& $this->child_relations;
  7759. $cpo->parent_relations =& $this->parent_relations;
  7760. $cpo->audit_logging =& $this->audit_logging;
  7761. $cpo->default_orderby =& $this->default_orderby;
  7762. $cpo->alt_language_table =& $this->alt_language_table;
  7763. $cpo->alt_language_cols =& $this->alt_language_cols;
  7764. $cpo->nameof_start_date =& $this->nameof_start_date;
  7765. $cpo->nameof_end_date =& $this->nameof_end_date;
  7766. $cpo->sql_from =& $this->sql_from;
  7767. $cpo->sql_groupby =& $this->sql_groupby;
  7768. $cpo->sql_having =& $this->sql_having;
  7769. $cpo->sql_no_foreign_db =& $this->sql_no_foreign_db;
  7770. $cpo->sql_orderby =& $this->sql_orderby;
  7771. $cpo->sql_orderby_seq =& $this->sql_orderby_seq;
  7772. $cpo->sql_orderby_table =& $this->sql_orderby_table;
  7773. $cpo->sql_search =& $this->sql_search;
  7774. $cpo->sql_search_orig =& $this->sql_search_orig;
  7775. $cpo->sql_search_table =& $this->sql_search_table;
  7776. $cpo->sql_select =& $this->sql_select;
  7777. $cpo->sql_where =& $this->sql_where;
  7778. $cpo->sql_union =& $this->sql_union;
  7779. $cpo->initial_values =& $this->initial_values;
  7780. $cpo->lookup_data =& $this->lookup_data;
  7781. $cpo->rows_per_page =& $this->rows_per_page;
  7782. $cpo->pageno =& $this->pageno;
  7783. $cpo->numrows =& $this->numrows;
  7784. $cpo->initiated_from_controller =& $this->initiated_from_controller;
  7785. $cpo->skip_getdata =& $this->skip_getdata;
  7786. $cpo->errors =& $this->errors;
  7787. $cpo->messages =& $this->messages;
  7788. $cpo->custom_replaces_standard =& $this->custom_replaces_standard;
  7789. $cpo->zone =& $this->zone;
  7790. $cpo->no_display_count =& $this->no_display_count;
  7791. $cpo->unbuffered_query =& $this->unbuffered_query;
  7792. $cpo->xsl_params =& $this->xsl_params;
  7793. $cpo->wf_case_id =& $this->wf_case_id;
  7794. $cpo->wf_workitem_id =& $this->wf_workitem_id;
  7795. $cpo->wf_context =& $this->wf_context;
  7796. $cpo->wf_user_id =& $this->wf_user_id;
  7797.  
  7798. // include reference to calling object in the custom object
  7799. $cpo->calling_object =& $this;
  7800.  
  7801. $this->custom_processing_object =& $cpo;
  7802. } // if
  7803. } // if
  7804.  
  7805. return;
  7806.  
  7807. } // _getCustomProcessingObject
  7808.  
  7809. // ****************************************************************************
  7810. function &_getDBMSengine ($dbname=null, $unbuffered_query=false)
  7811. // obtain the object that deals with the database engine for this table.
  7812. {
  7813. $engine = null;
  7814. // check if database name has been changed in the config file
  7815. list($dbname2, $dbprefix, $dbms_engine) = findDBConfig($dbname);
  7816. $dbname3 = $dbprefix.$dbname2;
  7817. $args = array('dbname' => $dbname3);
  7818.  
  7819. if (!isset($GLOBALS['servers'])) {
  7820. // single server option
  7821. if (isset($GLOBALS['dbms'])) {
  7822. $engine =& $GLOBALS['dbms'];
  7823. } // if
  7824. if (isset($GLOBALS['dbhost'])) {
  7825. $args['dbhost'] =& $GLOBALS['dbhost'];
  7826. } // if
  7827. if (isset($GLOBALS['dbusername'])) {
  7828. $args['dbusername'] =& $GLOBALS['dbusername'];
  7829. } // if
  7830. if (isset($GLOBALS['dbuserpass'])) {
  7831. $args['dbuserpass'] =& $GLOBALS['dbuserpass'];
  7832. } // if
  7833. if (isset($GLOBALS['dbport'])) {
  7834. $args['dbport'] =& $GLOBALS['dbport'];
  7835. } // if
  7836. if (isset($GLOBALS['dbsocket'])) {
  7837. $args['dbsocket'] =& $GLOBALS['dbsocket'];
  7838. } // if
  7839. if (isset($GLOBALS['ssl_key'])) {
  7840. $args['ssl_key'] =& $GLOBALS['ssl_key'];
  7841. } // if
  7842. if (isset($GLOBALS['ssl_cert'])) {
  7843. $args['ssl_cert'] =& $GLOBALS['ssl_cert'];
  7844. } // if
  7845. if (isset($GLOBALS['ssl_ca'])) {
  7846. $args['ssl_ca'] =& $GLOBALS['ssl_ca'];
  7847. } // if
  7848. if (isset($GLOBALS['ssl_capath'])) {
  7849. $args['ssl_capath'] =& $GLOBALS['ssl_capath'];
  7850. } // if
  7851. if (isset($GLOBALS['ssl_cipher'])) {
  7852. $args['ssl_cipher'] =& $GLOBALS['ssl_cipher'];
  7853. } // if
  7854. // these are options for non-MySQL databases
  7855. if (isset($GLOBALS['PGSQL_dbname'])) {
  7856. $args['PGSQL_dbname'] =& $GLOBALS['PGSQL_dbname'];
  7857. } // if
  7858. if (isset($GLOBALS['SQLSRV_schema'])) {
  7859. $args['SQLSRV_schema'] =& $GLOBALS['SQLSRV_schema'];
  7860. } // if
  7861. if (isset($GLOBALS['serverName'])) {
  7862. $args['serverName'] =& $GLOBALS['serverName'];
  7863. } // if
  7864. if (isset($GLOBALS['connectionInfo'])) {
  7865. $args['connectionInfo'] =& $GLOBALS['connectionInfo'];
  7866. } // if
  7867. } else {
  7868. // multi-server option
  7869. // find out which server deals with this dbname
  7870. foreach ($GLOBALS['servers'] as $servernum => $server) {
  7871. if (empty($server['dbnames'])) {
  7872. // DBNAMES entry missing
  7873. trigger_error($this->getLanguageText('sys0170', 'DBNAMES'), E_USER_ERROR);
  7874. } else {
  7875. $dbname_array = explode(',', $server['dbnames']);
  7876. $dbname_array = array_map('trim', $dbname_array);
  7877. } // if
  7878. if ($server['dbnames'] == '*' OR in_array($dbname, $dbname_array)) {
  7879. if (!isset($server['dbengine'])) {
  7880. trigger_error($this->getLanguageText('sys0170', 'DBENGINE'), E_USER_ERROR);
  7881. } else {
  7882. $engine = $server['dbengine'];
  7883. } // if
  7884. if (!isset($server['dbhost'])) {
  7885. trigger_error($this->getLanguageText('sys0170', 'DBHOST'), E_USER_ERROR);
  7886. } else {
  7887. $args['dbhost'] = $server['dbhost'];
  7888. } // if
  7889. if (!isset($server['dbusername'])) {
  7890. trigger_error($this->getLanguageText('sys0170', 'DBUSERNAME'), E_USER_ERROR);
  7891. } else {
  7892. $args['dbusername'] = $server['dbusername'];
  7893. } // if
  7894. if (!isset($server['dbuserpass'])) {
  7895. trigger_error($this->getLanguageText('sys0170', 'DBUSERPASS'), E_USER_ERROR);
  7896. } else {
  7897. $args['dbuserpass'] = $server['dbuserpass'];
  7898. } // if
  7899. if (!empty($server['dbport'])) {
  7900. $args['dbport'] = $server['dbport'];
  7901. } // if
  7902. if (!empty($server['dbsocket'])) {
  7903. $args['dbsocket'] = $server['dbsocket'];
  7904. } // if
  7905. if (!empty($server['ssl_key'])) {
  7906. $args['ssl_key'] = $server['ssl_key'];
  7907. } // if
  7908. if (!empty($server['ssl_cert'])) {
  7909. $args['ssl_cert'] = $server['ssl_cert'];
  7910. } // if
  7911. if (!empty($server['ssl_ca'])) {
  7912. $args['ssl_ca'] = $server['ssl_ca'];
  7913. } // if
  7914. if (!empty($server['ssl_capath'])) {
  7915. $args['ssl_capath'] = $server['ssl_capath'];
  7916. } // if
  7917. if (!empty($server['ssl_cipher'])) {
  7918. $args['ssl_cipher'] = $server['ssl_cipher'];
  7919. } // if
  7920. // these are options for non-MySQL databases
  7921. if (isset($server['PGSQL_dbname'])) {
  7922. $args['PGSQL_dbname'] =& $server['PGSQL_dbname'];
  7923. } // if
  7924. if (isset($server['SQLSRV_schema'])) {
  7925. $args['SQLSRV_schema'] =& $server['SQLSRV_schema'];
  7926. } // if
  7927. if (isset($server['serverName'])) {
  7928. $args['serverName'] =& $server['serverName'];
  7929. } // if
  7930. if (isset($server['connectionInfo'])) {
  7931. $args['connectionInfo'] =& $server['connectionInfo'];
  7932. } // if
  7933. break; // so stop here
  7934. } // if
  7935. } // foreach
  7936. if (empty($engine)) {
  7937. // "entry missing for database 'X'"
  7938. trigger_error($this->getLanguageText('sys0171', $dbname), E_USER_ERROR);
  7939. } // if
  7940. } // if
  7941.  
  7942. if (empty($engine)) {
  7943. trigger_error("No value has been supplied for DBMS engine", E_USER_ERROR);
  7944. } // if
  7945.  
  7946. if (!class_exists($engine)) {
  7947. // load class definition for this database engine
  7948. if ($engine == 'mysql') {
  7949. if (extension_loaded('mysqli')) {
  7950. // use 'improved' mysql functions
  7951. require_once "dml.mysqli.class.inc";
  7952. } else {
  7953. // use standard mysql functions
  7954. require_once "dml.mysql.class.inc";
  7955. } // if
  7956. } elseif ($engine == 'oracle') {
  7957. if (version_compare(phpversion(), '5.0.0', '<')) {
  7958. // use old api's
  7959. require_once "dml.oracle.php4.class.inc";
  7960. } else {
  7961. // use new api's
  7962. require_once "dml.oracle.php5.class.inc";
  7963. } // if
  7964. } else {
  7965. require_once "dml.$engine.class.inc";
  7966. } // if
  7967. } // if
  7968.  
  7969. if (isset($servernum)) {
  7970. $DML =& RDCsingleton::getInstance('server__' .$servernum .'__' .$engine, $args, true, $unbuffered_query);
  7971. } else {
  7972. $DML =& RDCsingleton::getInstance($engine, $args, true, $unbuffered_query);
  7973. } // if
  7974.  
  7975. $DML->dbname = $args['dbname']; // save selected database name in this server instance
  7976.  
  7977. return $DML;
  7978.  
  7979. } // _getDBMSengine
  7980.  
  7981. // ****************************************************************************
  7982. function _getInitialValues ($task_id=null)
  7983. // look for any initial values on the MNU_INITIAL_VALUE_USER table.
  7984. // if none are found take a look on the MNU_INITIAL_VALUE_ROLE table.
  7985. {
  7986. $fieldarray = array();
  7987.  
  7988. if (preg_match('/^(workflow|audit)$/i', $this->dbname)) {
  7989. // ignore this code for those databases
  7990. return $fieldarray;
  7991. } // if
  7992.  
  7993. $user_id = $_SESSION['logon_user_id'];
  7994. $role_id = $_SESSION['role_id'];
  7995. $role_list =& $_SESSION['role_list'];
  7996. if (empty($role_list)) {
  7997. $role_list = "'$role_id'";
  7998. } // if
  7999. if (empty($task_id)) {
  8000. if (!empty($GLOBALS['initial_values_task_id'])) {
  8001. $task_id = $GLOBALS['initial_values_task_id'];
  8002. } else {
  8003. $task_id = $GLOBALS['task_id'];
  8004. } // if
  8005. } // if
  8006.  
  8007. // look for ROLE data
  8008. $dbobject =& RDCsingleton::getInstance('mnu_initial_value_role');
  8009. $dbobject->sql_select = 'field_id, initial_value, is_noedit';
  8010. //$role_data = $dbobject->getData_raw("role_id='$role_id' AND task_id='$task_id'");
  8011. $role_data = $dbobject->getData_raw("role_id IN ($role_list) AND task_id='$task_id'");
  8012. unset($dbobject);
  8013. foreach ($role_data as $rownum => $rowdata) {
  8014. // change into an array which is keyed by field_id
  8015. $field_id = strtolower($rowdata['field_id']);
  8016. $init_data[$field_id]['initial_value'] = $rowdata['initial_value'];
  8017. $init_data[$field_id]['is_noedit'] = $rowdata['is_noedit'];
  8018. } // foreach
  8019.  
  8020. // overwrite with USER data
  8021. $dbobject =& RDCsingleton::getInstance('mnu_initial_value_user');
  8022. $dbobject->sql_select = 'field_id, initial_value, is_noedit';
  8023. $user_data = $dbobject->getData_raw("user_id='$user_id' AND task_id='$task_id'");
  8024. unset($dbobject);
  8025. foreach ($user_data as $rownum => $rowdata) {
  8026. // change into an array which is keyed by field_id
  8027. $field_id = strtolower($rowdata['field_id']);
  8028. $init_data[$field_id]['initial_value'] = $rowdata['initial_value'];
  8029. $init_data[$field_id]['is_noedit'] = $rowdata['is_noedit'];
  8030. } // foreach
  8031.  
  8032. if (!empty($init_data)) {
  8033. // copy any values into this task's data area
  8034. foreach ($init_data as $field_id => $field_data) {
  8035. $fieldarray[$field_id] = $field_data['initial_value'];
  8036. if (is_True($field_data['is_noedit'])) {
  8037. if (array_key_exists($field_id, $this->fieldspec)) {
  8038. // this field cannot be modified by the user
  8039. $this->fieldspec[$field_id]['noedit'] = 'y';
  8040. } // if
  8041. } // if
  8042. } // foreach
  8043. } // if
  8044.  
  8045. return $fieldarray;
  8046.  
  8047. } // _getInitialValues
  8048.  
  8049. // ****************************************************************************
  8050. function _getInitialWhere ($where)
  8051. // merge $this->initial_values with $where.
  8052. {
  8053. $fieldarray = where2array($where, false, false);
  8054.  
  8055. if (!empty($this->initial_values)) {
  8056. foreach ($this->initial_values as $key => $value) {
  8057. if (empty($fieldarray[$key])) {
  8058. // current value is empty, so overwrite with initial value
  8059. $fieldarray[$key] = $value;
  8060. } // if
  8061. } // foreach
  8062. } // if
  8063.  
  8064. $where = array2where($fieldarray);
  8065.  
  8066. return $where;
  8067.  
  8068. } // _getInitialWhere
  8069.  
  8070. // ****************************************************************************
  8071. function _processInstruction ($fieldarray)
  8072. // process instructions contained within $this->instruction
  8073. // (as returned by a child script)
  8074. {
  8075. // look for a 'select' instruction
  8076. if (array_key_exists('select', $this->instruction)) {
  8077. // extract the key/value pair which has been selected
  8078. foreach ($this->instruction['select'] as $selectkey => $selectvalue) {
  8079. // find the row with the same key
  8080. foreach ($fieldarray as $row => $rowdata) {
  8081. if ($rowdata[$selectkey] == $selectvalue) {
  8082. // mark this row as selected
  8083. $fieldarray[$row]['selected'] = 'T';
  8084. } // if
  8085. } // foreach
  8086. } // foreach
  8087. // instruction has been processed, so remove it
  8088. unset($this->instruction['select']);
  8089. } // if
  8090.  
  8091. // if there are no more instructions left then clear this array
  8092. if (empty($this->instruction)) {
  8093. unset($this->instruction);
  8094. } // if
  8095.  
  8096. return $fieldarray;
  8097.  
  8098. } // _processInstruction
  8099.  
  8100. // ****************************************************************************
  8101. function _qualify_dbname ($target_db, $this_db)
  8102. // find out if the target database needs to be qualified - if it has been switched
  8103. // (refer to _switch_databases() method) to the source database then it does not.
  8104. {
  8105. // check if the name has been prefixed or switched in the config file.
  8106. // list($target_db_new, $target_dbprefix, $target_dbms_engine) = findDBConfig($target_db);
  8107. // $target_db_new = $target_dbprefix.$target_db_new;
  8108. //
  8109. // list($this_db_new, $this_dbprefix, $this_dbms_engine) = findDBConfig($this_db);
  8110. // $this_db_new = $this_dbprefix.$this_db_new;
  8111. //
  8112. // if ($target_db_new == $this_db_new) {
  8113. // // target dbname is the same, so does not need to be specified
  8114. // $output = '';
  8115. // } else {
  8116. // // target dbname needs to be specified and enclosed in double quotes
  8117. // $output = '"'.$target_db_new.'".';
  8118. // } // if
  8119.  
  8120. $output = findDBName($target_db, $this_db);
  8121.  
  8122. return $output;
  8123.  
  8124. } // _qualify_dbname
  8125.  
  8126. // ****************************************************************************
  8127. function _sqlAssembleWhere ($where, $where_array)
  8128. // assemble the $where clause from its component parts.
  8129. // ($where = string, $where_array = array)
  8130. {
  8131. if (is_True($this->is_link_table)) {
  8132. // this is for an outer-link-inner relationship
  8133. $where = $this->_sqlAssembleWhereLink($where, $where_array);
  8134. } else {
  8135. if (isset($this->fieldspec['rdcaccount_id'])) {
  8136. // this table is split by account, so account_id must be supplied in WHERE string
  8137. if (empty($where_array['rdcaccount_id'])) {
  8138. if (!empty($_SESSION['rdcaccount_id'])) {
  8139. $account_id = $_SESSION['rdcaccount_id'];
  8140. } else {
  8141. $account_id = null;
  8142. } // if
  8143. if (empty($account_id) AND preg_match('/(mnu_user|mnu_account)/', $this->tablename)) {
  8144. // no account id supplied, so read everything on these tables only
  8145. } else {
  8146. if (empty($account_id) OR $account_id == 1) {
  8147. $account_id_string = "$this->tablename.rdcaccount_id='1'";
  8148. } else {
  8149. $account_id_string = "$this->tablename.rdcaccount_id IN ('1', '$account_id')";
  8150. } // if
  8151. if (empty($this->sql_search)) {
  8152. $this->sql_search = $account_id_string;
  8153. } else {
  8154. if (substr_count($this->sql_search, $account_id_string) == 0) {
  8155. $this->sql_search .= " AND $account_id_string";
  8156. } // if
  8157. } // if
  8158. } // if
  8159. } // if
  8160. } // if
  8161. } // if
  8162.  
  8163. if ($this->checkPrimaryKey or empty($this->sql_from) or ($this->sql_from == $this->tablename)) {
  8164. // check that 'where' clause does not contain any fields that
  8165. // are not in this table, otherwise it will cause an error
  8166. $extra = array();
  8167. if (is_object($this->custom_processing_object)) {
  8168. if (method_exists($this->custom_processing_object, '_cm_filterWhere')) {
  8169. $extra = $this->custom_processing_object->_cm_filterWhere($extra);
  8170. } // if
  8171. } // if
  8172. $extra = $this->_cm_filterWhere($extra);
  8173. $where = filterWhere($where, $this->fieldspec, $this->tablename, $extra);
  8174. } // if
  8175.  
  8176. if (empty($this->sql_from)) {
  8177. // obtain fields from foreign tables via a JOIN, if necessary
  8178. $this->sql_from = $this->_sqlForeignJoin($this->sql_select, $this->sql_from, $this->parent_relations);
  8179. } // if
  8180.  
  8181. // remove any duplicated field names from the select string
  8182. $this->sql_select = removeDuplicateFromSelect($this->sql_select);
  8183.  
  8184. if (!empty($this->sql_search)) {
  8185. // turn 'current/historic/future' into a range of dates
  8186. $this->sql_search = $this->currentOrHistoric($this->sql_search, $this->nameof_start_date, $this->nameof_end_date);
  8187. // check that 'search' clause does not contain any fields that
  8188. // are not in this table, otherwise it will cause an error
  8189. if (empty($this->sql_from) OR $this->sql_from == $this->tablename) {
  8190. $extra = array();
  8191. if (is_object($this->custom_processing_object)) {
  8192. if (method_exists($this->custom_processing_object, '_cm_filterWhere')) {
  8193. $extra = $this->custom_processing_object->_cm_filterWhere($extra);
  8194. } // if
  8195. } // if
  8196. $extra = $this->_cm_filterWhere($extra);
  8197. $this->sql_search = filterWhere($this->sql_search, $this->fieldspec, $this->tablename, $extra);
  8198. } // if
  8199. // remove anything in $this->sql_search which is duplicated in $where
  8200. $this->sql_search = filterWhere1Where2($where, $this->sql_search, $this->tablename);
  8201. } // if
  8202.  
  8203. // extract entries from $sql_select which are in format 'expression AS alias'
  8204. $alias_array = extractAliasNames($this->sql_select);
  8205. // anything in WHERE which has an alias name will be moved to HAVING
  8206. $having_array = where2array($this->sql_having, false, false);
  8207.  
  8208. if (empty($this->sql_from)) {
  8209. $this->sql_from = $this->tablename;
  8210. } // if
  8211.  
  8212. // qualify each column name to avoid possible conflicts with other tables
  8213. $where = qualifyWhere($where, $this->tablename, $this->fieldspec, $this->sql_from, null, $alias_array, $having_array);
  8214. if (!empty($this->sql_where)) {
  8215. if (preg_match('/^(AND |OR )/i', $this->sql_where)) {
  8216. // begins with 'AND ' or 'OR ', so do not filter or qualify the contents
  8217. $where .= ' '.$this->sql_where;
  8218. } else {
  8219. // temporarily remove anything in $this->sql_where which is duplicated in $where
  8220. $sql_where = qualifyWhere($this->sql_where, $this->tablename, $this->fieldspec, $this->sql_from, null, $alias_array, $having_array);
  8221. $sql_where = filterWhere1Where2($where, $sql_where, $this->tablename);
  8222. if (!empty($sql_where)) {
  8223. // append optional 'sql_where' criteria to $where
  8224. if (!empty($where)) {
  8225. $where = mergeWhere($where, $sql_where);
  8226. } else {
  8227. $where = $sql_where;
  8228. } // if
  8229. } // if
  8230. } // if
  8231. } // if
  8232.  
  8233. if (!empty($this->sql_search)) {
  8234. $search_array = where2array($this->sql_search, false, false);
  8235. if (!empty($this->link_item)) {
  8236. if (isset($search_array['selected'])) {
  8237. // replace 'selected' with correct column name, testing for T/Y and F/N
  8238. $search_array['selected'] = stripOperators($search_array['selected']);
  8239. if (is_True($search_array['selected'])) {
  8240. $search_array[$this->link_item] = 'IS NOT NULL';
  8241. } else {
  8242. $search_array[$this->link_item] = 'IS NULL';
  8243. } // if
  8244. // ensure that 'selected' column is not specified in search criteria
  8245. unset($search_array['selected']);
  8246. $this->sql_search = array2where($search_array);
  8247. } // if
  8248. } // if
  8249.  
  8250. if (!empty($this->sql_search)) {
  8251. // qualify each column name to avoid conflict with other tables
  8252. $this->sql_search = qualifyWhere($this->sql_search, $this->tablename, $this->fieldspec, $this->sql_from, $this->sql_search_table, $alias_array, $having_array);
  8253. // merge $where with optional search criteria
  8254. if (strlen(trim($this->sql_search)) > 0) {
  8255. if (empty($where)) {
  8256. $where = $this->sql_search;
  8257. } else {
  8258. $where = "($where) AND $this->sql_search";
  8259. } // if
  8260. } // if
  8261. } // if
  8262. } // if
  8263.  
  8264. // array may have been modified, so convert back into a string
  8265. $this->sql_having = array2where($having_array);
  8266.  
  8267. if (!empty($this->sql_from)) {
  8268. // qualify $default_orderby using one of two possible table names
  8269. if (isset($this->sql_orderby_table)) {
  8270. $orderby_table = $this->sql_orderby_table;
  8271. } else {
  8272. $orderby_table = $this->tablename;
  8273. } // if
  8274. if ($orderby_table != $this->tablename) {
  8275. if (file_exists("classes/$orderby_table.class.inc")) {
  8276. require_once "classes/$orderby_table.class.inc";
  8277. $dbobject = new $orderby_table;
  8278. $fieldspec = $dbobject->fieldspec;
  8279. unset($dbobject);
  8280. } else {
  8281. // look for 'original AS alias' in sql_from string
  8282. $alias_tablename = getTableAlias1($orderby_table, $this->sql_from);
  8283. if ($alias_tablename) {
  8284. require_once "classes/$alias_tablename.class.inc";
  8285. $dbobject = new $alias_tablename;
  8286. $fieldspec = $dbobject->fieldspec;
  8287. unset($dbobject);
  8288. } else {
  8289. $fieldspec = array();
  8290. } // if
  8291. } // if
  8292. } else {
  8293. $fieldspec = $this->fieldspec;
  8294. } // if
  8295. if (empty($this->sql_orderby)) {
  8296. $this->sql_orderby = $this->default_orderby_task;
  8297. } // if
  8298. if (empty($this->sql_orderby)) {
  8299. $this->sql_orderby = $this->default_orderby;
  8300. } // if
  8301. if (!empty($this->sql_orderby)) {
  8302. if (is_True($this->is_link_table)) {
  8303. $this->sql_orderby = requalifyOrderby($this->sql_orderby, $this->sql_select, $this->tablename, $this->inner_table, $this->parent_relations);
  8304. } else {
  8305. $this->sql_orderby = qualifyOrderby($this->sql_orderby, $orderby_table, $fieldspec, $this->sql_select, $this->sql_from);
  8306. } // if
  8307. } // if
  8308. } // if
  8309.  
  8310. return $where;
  8311.  
  8312. } // _sqlAssembleWhere
  8313.  
  8314. // ****************************************************************************
  8315. function _sqlAssembleWhereLink ($where, $where_array)
  8316. // in a many-link-many relationship this will assemble the SQL commands for
  8317. // the middle (link) table.
  8318. {
  8319. if (isset($this->link_item)) {
  8320. // this has already been processed, so don't do it again
  8321. return $where;
  8322. } // if
  8323.  
  8324.  
  8325.  
  8326.  
  8327.  
  8328.  
  8329.  
  8330.  
  8331.  
  8332.  
  8333.  
  8334. reset($where_array); // fix for version 4.4.1
  8335. if (!is_string(key($where_array))) {
  8336. $where_array = indexed2assoc($where_array);
  8337. } // if
  8338.  
  8339. // step through $parent_relations until the OUTER entity is found
  8340. foreach ($this->parent_relations as $reldata) {
  8341. if ($reldata['parent'] == $this->outer_table) {
  8342. $outer_table = $reldata['parent'];
  8343. $outer_alias = '';
  8344. break;
  8345. } else if (isset($reldata['alias']) and $reldata['alias'] == $this->outer_table) {
  8346. $outer_table = $reldata['parent'];
  8347. $outer_alias = $reldata['alias'];
  8348. break;
  8349. } // if
  8350. } // foreach
  8351.  
  8352. // identify felds which join the OUTER table to the LINK table
  8353. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  8354. $outer_key[] = $outer_table .'.' .$fldparent;
  8355. $ix = count($outer_key) -1;
  8356.  
  8357.  
  8358.  
  8359.  
  8360. if ($fldchild == $fldparent) {
  8361. $outer_key_as[] = $outer_key[$ix];
  8362. } else {
  8363. $outer_key_as[] = $outer_key[$ix] .' AS ' .$fldchild;
  8364. } // if
  8365. $outer_link[] = $outer_key[$ix] .'=' .$this->tablename .'.' .$fldchild;
  8366. } // foreach
  8367.  
  8368. if (!isset($this->inner_table)) {
  8369. // if OUTER table is defined, then INNER must be as well
  8370. trigger_error($this->getLanguageText('sys0011'), E_USER_ERROR); // 'Definition of INNER_TABLE is missing'
  8371. } // if
  8372.  
  8373. if (empty($this->sql_search_table)) {
  8374. $this->sql_search_table = $this->inner_table;
  8375. } // if
  8376. $this->sql_orderby_table = $this->inner_table;
  8377.  
  8378. // step through $parent_relations until the INNER entity is found
  8379. foreach ($this->parent_relations as $reldata) {
  8380. if ($reldata['parent'] == $this->inner_table) {
  8381. $inner_table = $reldata['parent'];
  8382. $inner_alias = '';
  8383. break;
  8384. } elseif (isset($reldata['alias']) and $reldata['alias'] == $this->inner_table) {
  8385. $inner_table = $reldata['parent'];
  8386. $inner_alias = $reldata['alias'];
  8387. break;
  8388. } // if
  8389. } // foreach
  8390.  
  8391. // identify felds which join the INNER table to the LINK table
  8392. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  8393. if (empty($inner_alias)) {
  8394. $inner_key[] = $inner_table .'.' .$fldparent;
  8395. } else {
  8396. $inner_key[] = $inner_alias .'.' .$fldparent;
  8397. } // if
  8398. $ix = count($inner_key) -1;
  8399. if ($fldchild == $fldparent) {
  8400. $inner_key_as[] = $inner_key[$ix];
  8401. } else {
  8402. $inner_key_as[] = $inner_key[$ix] .' AS ' .$fldchild;
  8403. } // if
  8404. $inner_link[] = $inner_key[$ix] .'=' .$this->tablename .'.' .$fldchild;
  8405. } // foreach
  8406.  
  8407. $this->link_item = $this->tablename .'.' .$fldchild;
  8408.  
  8409. // assemble the sql SELECT clause
  8410. if (strlen($this->sql_select) > 0) {
  8411. $sql_select = $this->sql_select .', ';
  8412. } else {
  8413. $sql_select = '';
  8414. } // if
  8415. foreach ($outer_key_as as $field) {
  8416. $sql_select .= $field .', ';
  8417. } // foreach
  8418. foreach ($inner_key_as as $field) {
  8419. $sql_select .= $field .', ';
  8420. } // foreach
  8421. $sql_select = rtrim($sql_select, ', '); // remove trailing comma
  8422.  
  8423. // include field from parent entity, if defined
  8424. if (isset($reldata['parent_field'])) {
  8425. if (substr_count($reldata['parent_field'], '(') > 0) {
  8426. // field contains 'function(...)', so do not qualify it with table name
  8427. $sql_select .= ', ' .$reldata['parent_field'];
  8428. } else {
  8429. // fieldname to be qualified with either table or alias name
  8430. if (isset($reldata['alias'])) {
  8431. $sql_select .= ', ' .$reldata['alias'] .'.' .$reldata['parent_field'];
  8432. } else {
  8433. $sql_select .= ', ' .$reldata['parent'] .'.' .$reldata['parent_field'];
  8434. } // if
  8435. } // if
  8436. } // if
  8437.  
  8438. $sql_select .= ", CASE WHEN $this->link_item IS NULL THEN 'F' ELSE 'T' END AS selected";
  8439.  
  8440. // assemble the sql FROM clause
  8441. $sql_from = $outer_table .' CROSS JOIN ';
  8442. if (empty($inner_alias)) {
  8443. $sql_from .= $inner_table;
  8444. } else {
  8445. $sql_from .= $inner_table .' AS ' .$inner_alias;
  8446. } // if
  8447.  
  8448. // find out if the inner table contains the 'account_id' column
  8449. $dbobject =& RDCsingleton::getInstance($inner_table, null, false);
  8450. if (isset($dbobject->fieldspec['rdcaccount_id'])) {
  8451. if (empty($inner_alias)) {
  8452. $account_id_string = $inner_table;
  8453. } else {
  8454. $account_id_string = $inner_alias;
  8455. } // if
  8456. $account_id =& $_SESSION['rdcaccount_id'];
  8457. if (empty($account_id)) {
  8458. $account_id_string .= ".rdcaccount_id='1'";
  8459. } else {
  8460. $account_id_string .= ".rdcaccount_id IN ('1', '$account_id')";
  8461. } // if
  8462. $sql_from .= " ON ($account_id_string)";
  8463. } // if
  8464. unset($dbobject);
  8465.  
  8466. $sql_from .= ' LEFT JOIN ' .$this->tablename .' ON (';
  8467. foreach ($outer_link as $link) {
  8468. $sql_from .= $link .' AND ';
  8469. } // foreach
  8470. foreach ($inner_link as $link) {
  8471. $sql_from .= $link .' AND ';
  8472. } // foreach
  8473. // remove last 5 characters (' AND ')
  8474. $sql_from = substr($sql_from, 0, strlen($sql_from) - 5);
  8475. $sql_from .= ') ';
  8476.  
  8477. if (!empty($reldata['alt_language_table'])) {
  8478. $party_language = str_replace('_', '-', strtolower($GLOBALS['party_language']));
  8479. if ($party_language != $_SESSION['default_language']) {
  8480. // link to table which provides text in an alternative language
  8481. $pkey_array = $reldata['fields'];
  8482. $new_relation = array('parent' => $reldata['alt_language_table'],
  8483. 'parent_field' => $reldata['alt_language_cols'],
  8484. 'fields' => $pkey_array);
  8485. $new_relation['this'] = $inner_table;
  8486. $sql_select = $this->_sqlSelectAlternateLanguage($sql_select, $new_relation);
  8487. } // if
  8488. } // if
  8489.  
  8490. $this->sql_select = $sql_select;
  8491. $this->sql_from = $sql_from .' ' .$this->sql_from;
  8492.  
  8493. return $where;
  8494.  
  8495. } // _sqlAssembleWhereLink
  8496.  
  8497. // ****************************************************************************
  8498. function _sqlForeignJoin (&$select, $from, $parent_relations)
  8499. // if there are parent relations then construct a JOIN.
  8500. // Note that $select is passed by reference as it may be amended.
  8501. {
  8502. if (empty($parent_relations) AND empty($this->alt_language_table)) {
  8503. if (empty($select)) {
  8504. $select = $this->tablename .'.*';
  8505. } // if
  8506. if (empty($from)) {
  8507. $from = $this->tablename;
  8508. } // if
  8509. return $from;
  8510. } // if
  8511.  
  8512. if (empty($select)) {
  8513. if (empty($this->alt_language_table)) {
  8514. $select = $this->tablename .'.*';
  8515. } else {
  8516. // insert 'table.field' into SELECT for every field in this table
  8517. foreach ($this->fieldspec as $fieldname => $fieldspec) {
  8518. if (array_key_exists('nondb', $fieldspec)) {
  8519. // this is a non-database field, so ignore it
  8520. } else {
  8521. if (empty($select)) {
  8522. $select = $this->tablename .'.' .$fieldname;
  8523. } else {
  8524. $select .= ', ' .$this->tablename .'.' .$fieldname;
  8525. } // if
  8526. } // if
  8527. } // foreach
  8528. } // if
  8529. } else {
  8530. $select = qualifySelect($select, $this->tablename, $this->fieldspec);
  8531. } // if
  8532.  
  8533. if (empty($from)) {
  8534. $from = $this->tablename;
  8535. } // if
  8536.  
  8537. $alt_language_relations = array();
  8538. if (!empty($this->alt_language_table)) {
  8539. $party_language = str_replace('_', '-', strtolower($GLOBALS['party_language']));
  8540. if ($party_language != $_SESSION['default_language']) {
  8541. // add in a new relation for the alternative language table
  8542. $pkey_array = array();
  8543. foreach ($this->primary_key as $fieldname) {
  8544. $pkey_array[$fieldname] = $fieldname;
  8545. } // foreach
  8546. $temp_relation = array('parent' => $this->alt_language_table,
  8547. 'parent_field' => $this->alt_language_cols,
  8548. 'fields' => $pkey_array);
  8549. $temp_relation['this'] = $this->tablename;
  8550. $alt_language_relations[] = $temp_relation;
  8551. } // if
  8552. } // if
  8553.  
  8554. foreach ($parent_relations as $reldata) {
  8555. if (!isset($reldata['parent_field'])) {
  8556. // parent_field is not defined, so ignore this entry
  8557. } else {
  8558. $reldata['this'] = $this->tablename;
  8559. $from = $this->_sqlProcessJoin ($select, $from, $reldata, $alt_language_relations);
  8560. } // if
  8561. } // foreach
  8562.  
  8563. foreach ($alt_language_relations as $reldata) {
  8564. $select = $this->_sqlSelectAlternateLanguage($select, $reldata);
  8565. } // foreach
  8566.  
  8567. return $from;
  8568.  
  8569. } // _sqlForeignJoin
  8570.  
  8571. // ****************************************************************************
  8572. function _sqlProcessJoin (&$select, $from, $reldata, &$new_relations)
  8573. // construct a JOIN using relationship details in $reldata.
  8574. // Note that $select is passed by reference as it may be amended.
  8575. // Note that $new_relations is passed by reference as it may be amended.
  8576. {
  8577. $parent_table = $reldata['parent'];
  8578. $parent_field = $reldata['parent_field'];
  8579.  
  8580. // does this belong to another database/schema?
  8581. if (isset($reldata['dbname'])) {
  8582. if (is_True($this->sql_no_foreign_db)) {
  8583. // do NOT join to tables in different database
  8584. return $from;
  8585. } // if
  8586. } // if
  8587.  
  8588. // does this table have an alias?
  8589. if (isset($reldata['alias'])) {
  8590. $parent_alias = $reldata['alias'];
  8591. } else {
  8592. $parent_alias = '';
  8593. } // if
  8594.  
  8595. // obtain $fieldspec array for relevant table ($this or another)
  8596. if ($parent_table != $reldata['this']) {
  8597. // instantiate an object for this table
  8598. if (array_key_exists('subsys_dir', $reldata)) {
  8599. // get path to current subsystem directory
  8600. $dir = dirname($this->dirname);
  8601. // switch to other subsystem directory
  8602. $dir = dirname($dir) .'/' .$reldata['subsys_dir'] .'/';
  8603. } else {
  8604. $dir = NULL;
  8605. } // if
  8606. if (!class_exists($parent_table)) {
  8607. require_once $dir ."classes/$parent_table.class.inc";
  8608. } // if
  8609. $parentObj = new $parent_table;
  8610. if (isset($reldata['dbname'])) {
  8611. // find out if this database name has been altered in the config file
  8612. $dbname = findDBName($parentObj->dbname, $this->dbname);
  8613. } else {
  8614. $dbname = '';
  8615. } // if
  8616. $fieldspec = $parentObj->fieldspec;
  8617. $primary_key = $parentObj->primary_key;
  8618. if (empty($reldata['alt_language_cols']) AND !empty($parentObj->alt_language_cols)) {
  8619. $reldata['alt_language_table'] = $parentObj->alt_language_table;
  8620. $reldata['alt_language_cols'] = $parentObj->alt_language_cols;
  8621. } // if
  8622. unset($parentObj);
  8623. } else {
  8624. $dbname = '';
  8625. $fieldspec = $this->fieldspec;
  8626. $primary_key = $this->primary_key;
  8627. } // if
  8628.  
  8629. if (!empty($reldata['alt_language_cols'])) {
  8630. // find out if any column names have an alias
  8631. $parent_array = extractFieldNamesAssoc($parent_field);
  8632. $alt_array = extractFieldNamesAssoc($reldata['alt_language_cols']);
  8633. $alt_cols = '';
  8634. foreach ($parent_array as $field_alias => $fieldname) {
  8635. if (array_key_exists($fieldname, $alt_array)) {
  8636. if ($field_alias != $fieldname) {
  8637. $string = $fieldname .' AS ' .$field_alias;
  8638. } else {
  8639. $string = $fieldname;
  8640. } // if
  8641. if (empty($alt_cols)) {
  8642. $alt_cols = $string;
  8643. } else {
  8644. $alt_cols .= ', ' .$string;
  8645. } // if
  8646. } // if
  8647. } // foreach
  8648. $reldata['alt_language_cols'] = $alt_cols;
  8649. } // if
  8650.  
  8651. // get list of alias names used in current SELECT list
  8652. $select_aliases = extractAliasNames($select);
  8653. if (!empty($select_aliases)) {
  8654. // find out if any new field has an alias name
  8655. $parent_field_array = extractSelectList($parent_field);
  8656. foreach ($parent_field_array as $key => $field) {
  8657. list($fld_orig, $fld_alias) = getFieldAlias3($field);
  8658. if ($fld_orig != $fld_alias) {
  8659. while (array_key_exists($fld_alias, $select_aliases)) {
  8660. // this alias name is already used, so append an 'x' to make it unique
  8661. $fld_alias .= 'x';
  8662. } // while
  8663. $field = $fld_orig .' AS ' .$fld_alias;
  8664. $parent_field_array[$key] = $field;
  8665. } // if
  8666. } // foreach
  8667. $parent_field = implode(', ', $parent_field_array);
  8668. } // if
  8669.  
  8670. // put parent field(s) from foreign table into SELECT area
  8671. if (!empty($parent_alias)) {
  8672. $parent_field = qualifySelect($parent_field, $parent_alias, $fieldspec);
  8673. } else {
  8674. $parent_field = qualifySelect($parent_field, $parent_table, $fieldspec);
  8675. } // if
  8676. $select .= ', ' .$parent_field;
  8677.  
  8678. // build JOIN using supplied field names
  8679. if (!empty($parent_alias)) {
  8680. $from .= ' LEFT JOIN ' .$dbname .$reldata['parent'] .' AS ' .$parent_alias .' ON (';
  8681. } else {
  8682. $from .= ' LEFT JOIN ' .$dbname .$reldata['parent'] .' ON (';
  8683. } // if
  8684. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  8685. //if (strlen($fldchild) < 1) {
  8686. // // 'Name of child field missing in relationship with $parent_table'
  8687. // trigger_error($this->getLanguageText('sys0110', strtoupper($parent_table)), E_USER_ERROR);
  8688. //} // if
  8689. if (strlen($fldparent) < 1) {
  8690. // 'Name of parent field missing in relationship with $parent_table'
  8691. trigger_error($this->getLanguageText('sys0112', strtoupper($parent_table)), E_USER_ERROR);
  8692. } // if
  8693. if (!empty($fldchild)) {
  8694. if (!empty($parent_alias)) {
  8695. $from .= $parent_alias .'.' .$fldparent .'=' .$reldata['this'] .'.' .$fldchild .' AND ';
  8696. } else {
  8697. $from .= $parent_table .'.' .$fldparent .'=' .$reldata['this'] .'.' .$fldchild .' AND ';
  8698. } // if
  8699. } // if
  8700. } // foreach
  8701. // remove last 5 characters (' AND ')
  8702. $from = substr($from, 0, strlen($from) - 5);
  8703. $from .= ')';
  8704.  
  8705. if (!empty($reldata['alt_language_table'])) {
  8706. $party_language = str_replace('_', '-', strtolower($GLOBALS['party_language']));
  8707. if ($party_language != $_SESSION['default_language']) {
  8708. // add in a new relation for the alternative language table
  8709. $pkey_array = array();
  8710. foreach ($primary_key as $fieldname) {
  8711. $pkey_array[$fieldname] = $fieldname;
  8712. } // foreach
  8713. $temp_relation = array('parent' => $reldata['alt_language_table'],
  8714. 'parent_field' => $reldata['alt_language_cols'],
  8715. 'fields' => $pkey_array);
  8716. if (isset($reldata['alias'])) {
  8717. $temp_relation['this'] = $reldata['alias'];
  8718. } else {
  8719. $temp_relation['this'] = $reldata['parent'];
  8720. } // if
  8721. if (isset($reldata['dbname'])) {
  8722. $temp_relation['dbname'] = $reldata['dbname'];
  8723. } // if
  8724. $new_relations[] = $temp_relation;
  8725. } // if
  8726. } // if
  8727.  
  8728. return $from;
  8729.  
  8730. } // _sqlProcessJoin
  8731.  
  8732. // ****************************************************************************
  8733. function _sqlSelectAlternateLanguage ($sql_select, $reldata, $subquery=false)
  8734. // insert SELECT clause to obtain text from an alternative language table,
  8735. // (or the orginal text if alternative text is not found).
  8736. // if $subquery=true it means $fldchild was obtained from a subquery and need
  8737. // not be qualified with a table name.
  8738. {
  8739. // convert underscore to hyphen for database lookup
  8740. $party_language = str_replace('_', '-', strtolower($GLOBALS['party_language']));
  8741.  
  8742. list($this_table_orig, $this_table_alias) = getTableAlias3($reldata['this']);
  8743. if (empty($this_table_alias)) {
  8744. $this_table_orig = $reldata['this'];
  8745. $this_table_alias = $this_table_orig;
  8746. } // if
  8747.  
  8748. // extract all elements within current SELECT clause into an associative array
  8749. $select_array = extractSelectList($sql_select);
  8750.  
  8751. // look for names which have an alias
  8752. $select_alias = extractFieldNamesAssoc($select_array);
  8753.  
  8754. // create an array of field names (and possible alias names) which are to be added
  8755. $field_array = extractFieldNamesAssoc($reldata['parent_field']);
  8756.  
  8757. // each field requires a separate sub-select
  8758. foreach ($field_array as $field_alias => $field_name) {
  8759. if ($field_alias == $field_name) {
  8760. // check for alias name in $sql_select
  8761. $test = array_search($field_name, $select_alias);
  8762. if (empty($test)) {
  8763. // try using with a qualified name
  8764. $test = array_search("$this_table_alias.$field_name", $select_alias);
  8765. if ($test == $select_alias[$test]) {
  8766. // this is not a different value, so it is not an alias
  8767. $test = null;
  8768. } // if
  8769. } // if
  8770. if (!empty($test)) {
  8771. $field_alias = $test;
  8772. } // if
  8773. } // if
  8774.  
  8775. // remove any previous element which uses this name
  8776. if ($this_table_orig == $this_table_alias) {
  8777. $select_array = removeDuplicateNameFromSelect($select_array, $field_alias);
  8778. } elseif ($field_name != $field_alias) {
  8779. $select_array = removeDuplicateNameFromSelect($select_array, $field_alias);
  8780. } else {
  8781. $select_array = removeDuplicateNameFromSelect($select_array, "$this_table_alias.$field_alias");
  8782. } // if
  8783.  
  8784. // build new element for SELECT clause
  8785. $string = "\nCOALESCE((SELECT $field_name FROM ";
  8786. if (isset($reldata['dbname'])) {
  8787. $dbname = findDBName($reldata['dbname']);
  8788. } else {
  8789. $dbname = '';
  8790. } // if
  8791. $string .= $dbname.$reldata['parent']." WHERE ";
  8792. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  8793. if ($subquery == true) {
  8794. // field obtained from a subquery, so do not qualify it
  8795. $string .= "{$reldata['parent']}.$fldparent=$fldchild AND ";
  8796. } elseif (strpos($fldchild, '.') === false) {
  8797. // qualify $fldchild with this tablename
  8798. $string .= "{$reldata['parent']}.$fldparent=$this_table_alias.$fldchild AND ";
  8799. } else {
  8800. // $fldchild is already qualified, so use it 'as is'
  8801. $string .= "{$reldata['parent']}.$fldparent=$fldchild AND ";
  8802. } // if
  8803. } // foreach
  8804. $string .= "{$reldata['parent']}.language_id='$party_language'";
  8805. if ($subquery == true) {
  8806. $string .= "), (SELECT $field_name FROM ";
  8807. if (isset($reldata['dbname'])) {
  8808. // find out if this database name has been altered in the config file
  8809. $dbname = findDBName($reldata['dbname'], $this->dbname);
  8810. } else {
  8811. $dbname = '';
  8812. } // if
  8813. $string .= $dbname."$this_table_orig WHERE ";
  8814. foreach ($reldata['fields'] as $fldchild => $fldparent) {
  8815. $string .= "$this_table_orig.$fldparent=$fldchild AND ";
  8816. } // foreach
  8817. // remove final ' AND '
  8818. $string = substr($string, 0, -5);
  8819. $string .= ")";
  8820. } else {
  8821. $string .= "), $this_table_alias.$field_name";
  8822. } // if
  8823. $string .= ") AS $field_alias";
  8824.  
  8825. // append to current SELECT clause
  8826. $select_array[] = $string;
  8827. } // foreach
  8828.  
  8829. // convert array back into a string
  8830. $sql_select = implode(', ', $select_array);
  8831.  
  8832. return $sql_select;
  8833.  
  8834. } // _sqlSelectAlternateLanguage
  8835.  
  8836. // ****************************************************************************
  8837. function _switch_database ($tablename, $dbname)
  8838. // create an instance of a table class and switch the database name.
  8839. // $dbname will be different from the one inside the table class.
  8840. {
  8841. if (!class_exists($tablename)) {
  8842. require_once("$tablename.class.inc");
  8843. } // if
  8844.  
  8845. $dbobject = new $tablename();
  8846.  
  8847. $dbname_old = $dbobject->dbname;
  8848.  
  8849. // use this function just in case the name has been switched in the config file.
  8850. list($dbobject->dbname, $dbprefix, $dbms_engine) = findDBConfig($dbname);
  8851.  
  8852. // save the original dbname in case we have to delete child relations
  8853. $dbobject->dbname_old = $dbname_old;
  8854.  
  8855. return $dbobject;
  8856.  
  8857. } // _switch_database
  8858.  
  8859. // ****************************************************************************
  8860. function _validateInsert ($fieldarray)
  8861. // validate contents of $fieldarray prior to an INSERT
  8862. {
  8863. $validationobj =& RDCsingleton::getInstance('validation_class');
  8864.  
  8865. $array = $validationobj->validateInsert($fieldarray, $this->fieldspec, $this);
  8866.  
  8867. $this->errors = $validationobj->getErrors();
  8868.  
  8869. return $array;
  8870.  
  8871. } // _validateInsert
  8872.  
  8873. // ****************************************************************************
  8874. function _validateUpdate ($fieldarray)
  8875. // validate contents of $fieldarray prior to an UPDATE
  8876. {
  8877. $validationobj =& RDCsingleton::getInstance('validation_class');
  8878.  
  8879. $array = $validationobj->validateUpdate($fieldarray, $this->fieldspec, $this);
  8880.  
  8881. $this->errors = $validationobj->getErrors();
  8882.  
  8883. return $array;
  8884.  
  8885. } // _validateUpdate
  8886.  
  8887. // ****************************************************************************
  8888. function __call ($method, $arguments)
  8889. // magic method to satisfy method names which are not defined in a standard object,
  8890. // but which may be defined in a custom object.
  8891. {
  8892. if (is_object($this->custom_processing_object)) {
  8893. if (method_exists($this->custom_processing_object, $method)) {
  8894. $result = $this->custom_processing_object->$method($arguments[0]);
  8895. } else {
  8896. trigger_error("Method '$method' does not exist in custom object", E_USER_ERROR);
  8897. } // if
  8898. } else {
  8899. trigger_error("Method '$method' does not exist in standard object", E_USER_ERROR);
  8900. } // if
  8901.  
  8902. return $result;
  8903.  
  8904. } // __call
  8905.  
  8906. // ****************************************************************************
  8907. function __sleep ()
  8908. // perform object clean-up before serialization
  8909. {
  8910. // this causes an endless loop
  8911. // if (is_object(($this->custom_processing_object))) {
  8912. // $this->custom_processing_object_serial = serialize($this->custom_processing_object);
  8913. // unset($this->custom_processing_object);
  8914. // } // if
  8915.  
  8916. // get associative array of class variables
  8917. $object_vars = get_object_vars($this);
  8918.  
  8919. // remove/clear unwanted variables
  8920. $object_vars['errors'] = array();
  8921. $object_vars['messages'] = array();
  8922.  
  8923. $pattern_id = getPatternId();
  8924. if (preg_match('/^(UPD|ADD|MULTI|SRCH|LINK)/i', $pattern_id)) {
  8925. // do NOT shrink $this->fieldarray
  8926. } else {
  8927. // get list of primary key fields
  8928. $pkey_array = $this->getPkeyNames();
  8929. $pkey_array = $this->_cm_getPkeyNames($pkey_array, null, null);
  8930.  
  8931. if (is_string(key($this->fieldarray))) {
  8932. $this->fieldarray = array($this->fieldarray);
  8933. $array_is_associative = true;
  8934. } // if
  8935. foreach ($this->fieldarray as $rownum => &$rowdata) {
  8936. // remove all non-key fields from the stored data
  8937. $smalldata = array();
  8938. foreach ($pkey_array as $fieldname) {
  8939. if (array_key_exists($fieldname, $rowdata)) {
  8940. $smalldata[$fieldname] = $rowdata[$fieldname];
  8941. } // if
  8942. } // foreach
  8943. $rowdata = $smalldata;
  8944. } // foreach
  8945. if (isset($array_is_associative)) {
  8946. $this->fieldarray = $this->fieldarray[0];
  8947. } // if
  8948. } // if
  8949.  
  8950. // convert to indexed array
  8951. $object_vars = array_keys($object_vars);
  8952.  
  8953. return $object_vars;
  8954.  
  8955. } // __sleep
  8956.  
  8957. // ****************************************************************************
  8958. function __wakeup ()
  8959. // perform object initialisation after unserialization
  8960. {
  8961. // look for custom processing object
  8962. $this->_getCustomProcessingObject();
  8963.  
  8964. } // __wakeup
  8965.  
  8966. // ****************************************************************************
  8967. } // end class
  8968. // ****************************************************************************
  8969.  
  8970. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement