1: <?php
2: /**
3: * Session-based FormState handler. Uses PHP Sessions to store the form state.
4: *
5: * Stores the variables in the following format:
6: * $_SESSION['qformstate'][form_uniquid][state#]
7: * where the form_uniquid is a unique id that sticks with the window that the
8: * form is on, and state# is the formstate associated with that window. Multiple
9: * formstates need to be saved to support the browser back button.
10: *
11: * If requested by QForm, the index will be encrypted.
12: *
13: * This incorporates a system of garbage collection that will allow for at most BackButtonMax
14: * formstates to be saved in the session.
15: *
16: * This handler is compatible with asynchronous ajax calls.
17: *
18: */
19: class QSessionFormStateHandler extends QBaseClass {
20:
21: public static $BackButtonMax = 20; // maximum number of back button states we remember
22:
23: public static function Save($strFormState, $blnBackButtonFlag) {
24: // Compress (if available)
25: if (function_exists('gzcompress'))
26: $strFormState = gzcompress($strFormState, 9);
27:
28: if (empty($_POST['Qform__FormState'])) {
29: // no prior form state, so create a new one.
30: $strFormInstance = uniqid();
31: $intFormStateIndex = 1;
32: } else {
33: $strPriorState = $_POST['Qform__FormState'];
34:
35: if (!is_null(QForm::$EncryptionKey)) {
36: // Use QCryptography to Decrypt
37: $objCrypto = new QCryptography(QForm::$EncryptionKey, true);
38: $strPriorState = $objCrypto->Decrypt($strPriorState);
39: }
40:
41: $a = explode ('_', $strPriorState);
42: if (count ($a) == 2 &&
43: is_numeric ($a[1]) &&
44: !empty($_SESSION['qformstate'][$a[0]]['index'])) {
45: $strFormInstance = $a[0];
46: $intFormStateIndex = $_SESSION['qformstate'][$a[0]]['index'];
47: if ($blnBackButtonFlag) { // can we reuse current state info?
48: $intFormStateIndex ++; // nope
49:
50: // try to garbage collect
51: if (count($_SESSION['qformstate'][$a[0]]) > self::$BackButtonMax) {
52: foreach ($_SESSION['qformstate'][$a[0]] as $key=>$val) {
53: if (is_numeric($key) && $key < $_SESSION['qformstate'][$a[0]]['index'] - self::$BackButtonMax) {
54: unset ($_SESSION['qformstate'][$a[0]][$key]);
55: }
56: }
57: }
58: }
59: } else {
60: // couldn't find old session variables, so create new one
61: $strFormInstance = uniqid();
62: $intFormStateIndex = 1;
63: }
64: }
65:
66: // Setup current state variable
67: if (empty($_SESSION['qformstate'])) {
68: $_SESSION['qformstate'] = array();
69: }
70: if (empty($_SESSION['qformstate'][$strFormInstance])) {
71: $_SESSION['qformstate'][$strFormInstance] = array();
72: }
73:
74: $_SESSION['qformstate'][$strFormInstance]['index'] = $intFormStateIndex;
75: $_SESSION['qformstate'][$strFormInstance][$intFormStateIndex] = $strFormState;
76:
77: $strPostDataState = $strFormInstance . '_' . $intFormStateIndex;
78:
79: // Return StateIndex
80: if (!is_null(QForm::$EncryptionKey)) {
81: // Use QCryptography to Encrypt
82: $objCrypto = new QCryptography(QForm::$EncryptionKey, true);
83: return $objCrypto->Encrypt($strPostDataState);
84: } else
85: return $strPostDataState;
86: }
87:
88: public static function Load($strPostDataState) {
89: // Pull Out intStateIndex
90: if (!is_null(QForm::$EncryptionKey)) {
91: // Use QCryptography to Decrypt
92: $objCrypto = new QCryptography(QForm::$EncryptionKey, true);
93: $strPostDataState = $objCrypto->Decrypt($strPostDataState);
94: }
95:
96: $a = explode ('_', $strPostDataState);
97: if (count ($a) == 2 &&
98: is_numeric ($a[1]) &&
99: !empty($_SESSION['qformstate'][$a[0]][$a[1]])) {
100: $strSerializedForm = $_SESSION['qformstate'][$a[0]][$a[1]];
101: } else {
102: return null;
103: }
104:
105: // Uncompress (if available)
106: // NOTE: if gzcompress is used, we are restoring the *BINARY* data stream of the compressed formstate
107: // In theory, this SHOULD work. But if there is a webserver/os/php version that doesn't like
108: // binary session streams, you can first base64_decode before restoring from session (see note above).
109: if (function_exists('gzcompress')) {
110: $strSerializedForm = gzuncompress($strSerializedForm);
111: }
112:
113: return $strSerializedForm;
114: }
115: }