Source for file recmaint-defs.php

Documentation is available at recmaint-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: recmaint-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for record maintenance in the browser. */
  24. /* */
  25. /* This class provides a convenient way of encapsulating the required */
  26. /* javascript and hiddne fields to enable in-browser maintenance of a */
  27. /* recordset. */
  28. /* */
  29. /* The concept is that you will have a combo/select form element which */
  30. /* is a list of record keys called the 'keycombo' below, together with */
  31. /* a set of additional form fields of whatever type, to maintain the */
  32. /* fields in the record. */
  33. /* */
  34. /* When you create an object of 'recmaintainer' class, you specify the */
  35. /* name of the form containing your keycombo and also pass the actual */
  36. /* keycombo object (as a reference). After that, you associate your */
  37. /* form field objects using the register_field() method, and special */
  38. /* buttons with the register_button() method. NOTE: you *must* give */
  39. /* your form fields names which are the same as the DB field names of */
  40. /* the fields they are maintaining! */
  41. /* */
  42. /* The record data is then added using add_record(). This takes an */
  43. /* associative array of fields as a parameter and these fields should */
  44. /* obviously match your form fields in naming. Also make sure that */
  45. /* the order you add the records is the same as the order of the keys */
  46. /* in your keycombo select box. */
  47. /* */
  48. /* Somewhere at the bottom of the aforementioned form, you then call */
  49. /* the render() method. This puts the Javascript into the page, and */
  50. /* some hidden fields for when you save data and POST it. */
  51. /* */
  52. /* POST processing: when the form gets posted, some special form fields */
  53. /* are sent and these are as follows.. */
  54. /* _recmaintpost_form: contains the posted form name */
  55. /* _recmaintpost_flds: contains a list of field names in each record */
  56. /* _recmaintpost_data: contains all changed records data */
  57. /* _recmaintpost_dels: contains keys of deleted records, if any */
  58. /* _recmaintpost_order: contains keys in order (but only if reordered) */
  59. /* */
  60. /* Lists are sent back as a string delimited by the special ASCII chars */
  61. /* shown in the definitions below this comment block. The exception is */
  62. /* the recmaintpost_flds which uses commas as the delimiter. */
  63. /* */
  64. /* One additional point regarding the naming of the above vars. We */
  65. /* provide for multiple of these forms on a single page, by allowing */
  66. /* a prefix. The above names have no prefix, which is the default */
  67. /* option, but if more than one recmaint was present a prefix would be */
  68. /* added in front of the underscore, to differentiate the vars. */
  69. /* */
  70. /* ******************************************************************** */
  71. /** @package recmaint */// Anything which uses recmaint has to have this record maintenance
  72. // module Javascript in the page. If you are not using Axyl's
  73. // RESPONSE object, then make sure you insert this into your page..
  74.  
  75. if (isset($RESPONSE)) {
  76. $RESPONSE->head->add_script(
  77. "var keyfield = new Array();\n"
  78. . "var curid = new Array();\n"
  79. . "var newid = new Array();\n"
  80. );
  81. $RESPONSE->head->add_scriptsrc("$LIBDIR/js/recmaint.js");
  82. }
  83. /**
  84. * The record maintainer class.
  85. * @package recmaint
  86. */
  87. class recmaintainer extends RenderableObject {
  88. // Public
  89. // Private
  90. /** Name of the form containing maintained fields
  91. @access private */
  92. var $formname;
  93. /** Prefix to differentiate one set of records from anther
  94. @access private */
  95. var $prefix = "";
  96. /** If true, maintainer will be displayed with fields disabled
  97. @access private */
  98. var $start_disabled = false;
  99. /** Pointer to the key combo/select box
  100. @access private */
  101. var $keycombo;
  102. /** Internal array of field names being maintained
  103. @access private */
  104. var $fields = array();
  105. /** Record data to maintain
  106. @access private */
  107. var $records = array();
  108. /** Field defaults for new records
  109. @access private */
  110. var $defaults = array();
  111. /** Value, if defined, of the record to focus to on initialisation
  112. @access private */
  113. var $initial_record_value;
  114. // ....................................................................
  115. /**
  116. * Define a record maintainer object.
  117. * The form name, key combo (select) box, and the list of fields
  118. * it will be maintaining must be specified.
  119. * @param string $formname Name of the form containing maintenance fields
  120. * @param object $keycombo The form_combofield object containing record keys
  121. * @param string $fieldlist The name sof all fields being maintained
  122. * @param string $prefix Prefix to identify multiple recmaintainers uniquely
  123. */
  124. function recmaintainer($formname, &$keycombo, $prefix="_") {
  125. $this->formname = $formname;
  126. $this->keycombo = $keycombo;
  127. $this->prefix = $prefix;
  128. $keycombo->set_onchange("changeRecord('$formname',this,'$this->prefix')");
  129. } // recmaintainer
  130. // ....................................................................
  131. /**
  132. * Register a button.
  133. * This assigns the proper onclick event so that the button will do the
  134. * right thing when clicked. There are several types of button recognised:
  135. * "up", "down", "save", "reset" and "del".
  136. * NB: If the button in question already has an onclick script attached to
  137. * it then this is preserved, and will be executed after the new script
  138. * we attach here.
  139. * @param string $type Type of button being registered
  140. * @param object The button object to be registered
  141. */
  142. function register_button($type, &$button) {
  143. $new_onclick = "";
  144. switch ($type) {
  145. // Move record up one place in listbox..
  146. case "up":
  147. $new_onclick = "comboMove('$this->formname','" . $this->keycombo->name . "','up')";
  148. break;
  149. // Move record down one place in listbox..
  150. case "down":
  151. $new_onclick = "comboMove('$this->formname','" . $this->keycombo->name . "','down')";
  152. break;
  153. // Delete record from the maintainer..
  154. case "del":
  155. case "delete":
  156. $new_onclick = "deleteRecord('$this->formname','$this->prefix')";
  157. break;
  158. // Add a new record to the maintainer..
  159. case "add":
  160. $new_onclick = "addRecord('$this->formname','$this->prefix')";
  161. break;
  162. // General-purpose save-data and submit form button..
  163. case "save":
  164. $new_onclick = "saveRecords('$this->formname','$this->prefix')";
  165. break;
  166. // Special-case store-only button, for when custom behviour reqd..
  167. case "store":
  168. $new_onclick = "storeRecords('$this->formname','$this->prefix')";
  169. break;
  170. // Reset the form..
  171. case "reset":
  172. $new_onclick = "document.$this->formname.reset()";
  173. break;
  174. } // switch
  175. // Set new onclick script..
  176. $button->set_onclick($new_onclick, SCRIPT_APPEND);
  177. } // register_button
  178. // ....................................................................
  179. /**
  180. * Register a form field in the maintainer.
  181. * The object passed should be a normal Axyl form object such as a
  182. * form_textfield, form_checkbox or whatever. Add all of the form
  183. * objects that you have in your maintenance screen.
  184. * @param object $field A form element eg: a form_textfield object
  185. * @param string $fieldid HTML id attribute to assign to form element
  186. */
  187. function register_field(&$field, $fieldid="fdata") {
  188. $this->fields[] = $field->name;
  189. $field->set_onchange("changedValue('$this->formname',this,'$this->prefix')");
  190. $field->setid($this->keycombo->name . "_" . $fieldid);
  191. } // register_field
  192. // ....................................................................
  193. /**
  194. * Add a record of data to the maintainer.
  195. * The record is passed as an associative array, which is directory
  196. * compatible with the rows returned by get_next() etc. in normal
  197. * database queries. The array is therefore expected to contain the
  198. * normal fieldname=>data pairs. The ordering of adding these records
  199. * should be identical to the ordering of the records in the keycombo.
  200. * @param array $record An associative arrray containing a record of data
  201. */
  202. function add_record($keyval, $record) {
  203. $this->records[$keyval] = $record;
  204. } // add_record
  205. // ....................................................................
  206. /**
  207. * Add an array of default values for each field.
  208. * The array is a key=>value associative array, with the key = fieldname,
  209. * and the value = default value for field.
  210. * @param array $defaults An associative arrray containing field defaults
  211. */
  212. function add_defaults($defaults) {
  213. $this->defaults = $defaults;
  214. } // add_defaults
  215. // ....................................................................
  216. /**
  217. * Cause the maintainer to be displayed initially diabled. All form fields
  218. * which are part of the maintainer will be readonly/disabled.
  219. */
  220. function display_disabled() {
  221. $this->start_disabled = true;
  222. } // display_disabled
  223. // ....................................................................
  224. /**
  225. * Tell the record maintainer to focus the keycombo to the record with
  226. * the given value, when it first initialises.
  227. */
  228. function initial_record($value) {
  229. $this->initial_record_value = $value;
  230. } // initial_record
  231. // ....................................................................
  232. /**
  233. * Return the HTML for this maintainer. This consists of Javascript
  234. * objects to contain the data, and hidden form fields which will be
  235. * used to POST changes etc. This should be rendered inside your
  236. * main form element.
  237. * @param string $prefix A prefix to use in field-naming for uniqueness
  238. */
  239. function html() {
  240. global $RESPONSE;
  241.  
  242. $dat_pfx = $this->prefix . "dat_";
  243. $new_pfx = $this->prefix . "new_";
  244. $rec_pfx = $this->prefix . "rec_";
  245.  
  246. $fieldlist = implode(",", $this->fields);
  247. $s = "";
  248. $keyvals = array();
  249. $data_js = "function $rec_pfx$this->formname($fieldlist) {\n";
  250. foreach ($this->fields as $fieldname) {
  251. $data_js .= "this.$fieldname=$fieldname;\n";
  252. }
  253. $data_js .= "}\n";
  254. $data_js .= "function $new_pfx$this->formname(id) {\n";
  255. $data_js .= "$dat_pfx$this->formname[id] = new datarec(id,";
  256. $data_js .= "new $rec_pfx$this->formname(";
  257. $args = array();
  258. foreach ($this->fields as $fieldname) {
  259. $args[] = "'" . rawurlencode($this->defaults[$fieldname]) . "'";
  260. }
  261. $data_js .= implode(",", $args);
  262. $data_js .= "),'$this->prefix');\n";
  263. $data_js .= "$dat_pfx$this->formname[id].changed=true;\n";
  264. $data_js .= "}\n";
  265. $data_js .= "var $dat_pfx$this->formname = new Object();\n";
  266. foreach ($this->records as $keyval => $rec) {
  267. $data_js .= "$dat_pfx$this->formname['$keyval'] = new datarec('$keyval',";
  268. $data_js .= "new $rec_pfx$this->formname(";
  269. $args = array();
  270. foreach ($this->fields as $fieldname) {
  271. $fldval = $rec[$fieldname];
  272. if (isset($RESPONSE) && $RESPONSE->multilang && function_exists("utf8_encode")) {
  273. //debugbr("block recmaint: field $fieldname MULTILANG");
  274. $fldval = utf8_ensure($fldval);
  275. $patts = array("/[\n]/", "/[']/", "/[\012\015]/");
  276. $repls = array("%0d%0a", "%27", "");
  277. $fldval = preg_replace($patts, $repls, $fldval);
  278. $fldval = utf8RawUrlEncode($fldval);
  279. $args[] = "'$fldval'";
  280. }
  281. else {
  282. //debugbr("block recmaint: field $fieldname NOT MULTILANG");
  283. $fldval = rawurlencode($fldval);
  284. $args[] = "'$fldval'";
  285. }
  286. }
  287. $data_js .= implode(",", $args);
  288. $data_js .= "),'$this->prefix');\n";
  289. } // foreach
  290. // This contains the posted form name..
  291. $hid = new form_hiddenfield($this->prefix . "recmaintpost_form", $this->formname);
  292. $s .= $hid->render();
  293. // This contains the field names in each record..
  294. $hid = new form_hiddenfield($this->prefix . "recmaintpost_flds", $fieldlist);
  295. $s .= $hid->render();
  296. // This field is posted with data of changed records..
  297. $hid = new form_hiddenfield($this->prefix . "recmaintpost_data");
  298. $s .= $hid->render();
  299. // This field is posted with keys of deleted records..
  300. $hid = new form_hiddenfield($this->prefix . "recmaintpost_dels");
  301. $s .= $hid->render();
  302. // This field is posted with keys in new order if changed..
  303. $hid = new form_hiddenfield($this->prefix . "recmaintpost_order");
  304. $s .= $hid->render();
  305.  
  306. // Inject the Javascript to the page..
  307. if (isset($RESPONSE)) {
  308. $RESPONSE->body->add_script(
  309. "keyfield['$this->prefix']='" . $this->keycombo->name . "';\n"
  310. . "curid['$this->prefix']=-1;\n"
  311. . "newid['$this->prefix']=10000;\n"
  312. . "$data_js"
  313. );
  314. if ($this->start_disabled || count($this->records) == 0) {
  315. $RESPONSE->foot->add_script(
  316. "disable('$this->formname',true,'" . $this->keycombo->name . "');\n"
  317. );
  318. }
  319. else {
  320. if (isset($this->initial_record_value)) {
  321. foreach ($this->records as $keyval => $rec) {
  322. if ($keyval == $this->initial_record_value)
  323. break;
  324. }
  325. $RESPONSE->foot->add_script(
  326. "focusRecordByValue('$this->formname','$this->prefix','$this->initial_record_value');\n"
  327. );
  328. }
  329. else {
  330. foreach ($this->records as $keyval => $rec) { break; }
  331. $RESPONSE->foot->add_script(
  332. "firstRecord('$this->formname','$this->prefix');\n"
  333. );
  334. }
  335. }
  336. }
  337. else {
  338. $s .= "<script language=\"javascript\">\n";
  339. $s .= "keyfield['$this->prefix']='" . $this->keycombo->name . "';\n";
  340. $s .= "curid['$this->prefix']=-1;\n";
  341. $s .= "newid['$this->prefix']=10000;\n";
  342. $s .= $data_js;
  343. if ($this->start_disabled || count($this->records) == 0) {
  344. $s .= "disable('$this->formname',true,'" . $this->keycombo->name . "');\n";
  345. }
  346. else {
  347. if (isset($this->initial_record_value)) {
  348. foreach ($this->records as $keyval => $rec) {
  349. if ($keyval == $this->initial_record_value)
  350. break;
  351. }
  352. $s .= "focusRecordByValue('$this->formname','$this->prefix','$this->initial_record_value');\n";
  353. }
  354. else {
  355. foreach ($this->records as $keyval => $rec) { break; }
  356. $s .= "firstRecord('$this->formname','$this->prefix');\n";
  357. }
  358. }
  359. $s .= "</script>\n";
  360. }
  361. // Return the other page content..
  362. return $s;
  363. } // html
  364.  
  365. } // class recmaintainer
  366. // ----------------------------------------------------------------------
  367.  
  368. /**
  369. * Utility function. Returns the value of the named field. Returns the
  370. * value of the named field which is in the data array $rec. Uses the
  371. * array $fields to determine the position of the named field in the
  372. * data record.
  373. * @param string $fldname Name of field to fetch value of.
  374. * @param array $fields Array of fields in the record.
  375. * @param array $rec Array of data
  376. */
  377. function get_recmaintfield($fldname, $fields, $rec) {
  378. $val = "";
  379. $ix = 0;
  380. foreach ($fields as $fld) {
  381. if ($fld == $fldname) {
  382. $val = $rec[$ix];
  383. break;
  384. }
  385. $ix += 1;
  386. }
  387. return $val;
  388. } // get_recmaintfield
  389. // ----------------------------------------------------------------------
  390.  
  391. ?>

Documentation generated by phpDocumentor 1.3.0RC3