source: trunk/lib/PageSequence.inc.php @ 141

Last change on this file since 141 was 141, checked in by scdev, 18 years ago

Q - Changed <strong> to <em> in raiseMsg() calls.

File size: 12.3 KB
Line 
1<?php
2/**
3 * PageSequence.inc.php
4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 *
6 * The PageSequence class provides an interface to simplify the creation of a multi-step form.
7 *
8 * @requires  This class requires Prefs.inc.php
9 * @author    Quinn Comendant <quinn@strangecode.com>
10 * @version   1.01
11 */
12
13require_once dirname(__FILE__) . '/Prefs.inc.php';
14
15class PageSequence
16{
17    var $current_step_id = 0;
18    var $start_url;
19    var $sequence_title = '';
20    var $seq = '_sequence_';
21    var $idle_timeout;
22
23    /**
24     * Constructor. Sets the title of this sequence and initializes session variables.
25     *
26     * @param  array $params   An associative array of PageSequence parameters.
27     * @access public
28     */
29    function PageSequence($params)
30    {
31        if (isset($params['sequence_title'])) {
32            $this->sequence_title = $params['sequence_title'];
33            $this->seq .= $params['sequence_title'];
34        }
35
36        // How long before resetting session? 60 minutes.
37        $this->idle_timeout = isset($params['idle_timeout']) ? $params['idle_timeout'] : 3600;
38
39        // Where is user to be redirected after startOver function call?
40        $this->start_url = isset($params['start_url']) ? $params['start_url'] : $_SERVER['PHP_SELF'];
41
42        // Initialize vars if not set.
43        if (!isset($_SESSION[$this->seq]['steps'])) {
44            $_SESSION[$this->seq]['steps'] = array();
45        }
46        if (!isset($_SESSION[$this->seq]['data'])) {
47            $_SESSION[$this->seq]['data'] = array();
48        }
49        if (!isset($_SESSION[$this->seq]['defaults'])) {
50            $_SESSION[$this->seq]['defaults'] = array();
51        }
52
53        // Manage timeout.
54        $this->_auto_timeout();
55    }
56
57    /**
58     * Create a new step at the end (or specified position) of the $steps array.
59     *
60     * @param  string $step_id      Uniqie identifyer for this step.
61     * @param  array  $params       Values for the creation of the step.
62     *
63     * @return boolean    Success of the addition
64     * @access public
65     */
66    function addStep($step_id, $params)
67    {
68        // Keys for the steps array cannot be numeric.
69        if (is_numeric($step_id)) {
70            trigger_error('Step ID for function addStep cannot be numeric.', E_USER_WARNING);
71        }
72        // This step ID already exists.
73        if (!is_null($this->getPosition($step_id))) {
74            return false;
75        }
76        $_SESSION[$this->seq]['steps'][] = array(
77            'id'        => $step_id,
78            'title'     => isset($params['title'])     ? $params['title']     : '',
79            'active'    => isset($params['active'])    ? $params['active']    : false,
80            'form_tpl'  => isset($params['form_tpl'])  ? $params['form_tpl']  : '',
81            'disp_tpl'  => isset($params['disp_tpl'])  ? $params['disp_tpl']  : '',
82            'required'  => isset($params['required'])  ? $params['required']  : false,
83            'completed' => isset($params['completed']) ? $params['completed'] : false,
84            'editable'  => isset($params['editable'])  ? $params['editable']  : true,
85        );
86    }
87
88    /**
89     * Set the features of a step. Current step if step_id not specified.
90     *
91     * @param  string $page_id    ID of page. Leave null if modifying current step features.
92     * @param  array  $feature    Array of feature keys and values to set.
93     *
94     * @return bool true on success, false on failure
95     */
96    function setFeature($step_id=null, $features)
97    {
98        $pos = isset($step_id) ? $this->getPosition($step_id) : $this->getPosition();
99
100        if (isset($features) && is_array($features) && isset($_SESSION[$this->seq]['steps'][$pos])) {
101            $_SESSION[$this->seq]['steps'][$pos] = array_merge($_SESSION[$this->seq]['steps'][$pos], $features);
102        }
103    }
104
105    /**
106     * Returns a specified value from a registered step.
107     *
108     * @access public
109     *
110     * @param string $step_id  Id of step with feature to return.
111     * @param string $key      Which value to return.
112     * @param mixed  $default  Value to return if key not found in user_data.
113     *
114     * @return mixed          Value stored in session.
115     */
116    function getFeature($step_id, $key, $default='')
117    {
118        $pos = isset($step_id) ? $this->getPosition($step_id) : $this->getPosition();
119        if (isset($_SESSION[$this->seq]['steps'][$pos][$key])) {
120            return $_SESSION[$this->seq]['steps'][$pos][$key];
121        } else {
122            return $default;
123        }
124    }
125
126    /**
127     * Set the current step id. Which step are we on?
128     *
129     * @param  string $step_id      ID or number of current step.
130     * @return string    Actual step ID
131     * @access public
132     */
133    function setCurrent($step_id)
134    {
135        $app =& App::getInstance();
136
137        if (false !== ($pos = $this->getPosition($step_id))) {
138            // Specified step exists (even if numeric).
139            $this->current_step_id = $this->getID($pos);
140        } else {
141            // Step with specified key does not exist.
142            $app->logMsg(sprintf('Step %s not defined in sequence %s', $step_id, $this->sequence_title), LOG_INFO, __FILE__, __LINE__);
143            return false;
144        }
145    }
146
147    /**
148     * Get the current step id.
149     *
150     * @return int $pos    Actual step poisition
151     * @access public
152     */
153    function getID($pos=null)
154    {
155        if (isset($pos)) {
156            return $_SESSION[$this->seq]['steps'][$pos]['id'];
157        } else {
158            return $this->current_step_id;
159        }
160    }
161
162    /**
163     * Get the current step number.
164     *
165     * @param  string $step_id      ID or number of step to convert to position.
166     *
167     * @return string               Actual step number
168     * @access public
169     */
170    function getPosition($step_id=null)
171    {
172        // Get current step id if step not provided.
173        if (!isset($step_id)) {
174            $step_id = $this->current_step_id;
175        }
176        if (is_numeric($step_id) && isset($_SESSION[$this->seq]['steps'][$step_id])) {
177            // Step ID provided is a number...go directly to key.
178            return $step_id;
179        } else {
180            // Step ID is a string. Loop through searching for match.
181            foreach ($_SESSION[$this->seq]['steps'] as $pos=>$step) {
182                if ($step['id'] == $step_id) {
183                    return $pos;
184                }
185            }
186            // Step not found matching ID.
187            return null;
188        }
189    }
190
191    /**
192     * Returns the ID of the step with required=true and completed=false
193     * and active=true that falls before specified step_id.
194     *
195     * @param  string $curr_step_id ID or number of current step.
196     * @return string               Prerequisite step ID or false if none.
197     * @access public
198     */
199    function getRequiredID($curr_step_id)
200    {
201        if ('' === $curr_step_id) {
202            return $this->current_step_id;
203        }
204        foreach ($_SESSION[$this->seq]['steps'] as $pos=>$step) {
205            if (is_numeric($curr_step_id) && $pos == $curr_step_id && $step['active']) {
206                return $curr_step_id;
207            } else if ($step['id'] == $curr_step_id && $step['active']) {
208                return $curr_step_id;
209            }
210            if ($step['active'] && $step['required'] && !$step['completed']) {
211                return $step['id'];
212            }
213        }
214        return $curr_step_id;
215    }
216
217    /**
218     * Returns the next step in the steps array or the first active required
219     * uncompleted step.
220     *
221     * @return string  Step identifyer of the next step.
222     * @access public
223     */
224    function getNextID()
225    {
226        // Loop through all steps.
227        foreach ($_SESSION[$this->seq]['steps'] as $pos=>$step) {
228            // If a step is found that is active, required, and not completed, we must do that one.
229            if ($step['active'] && $step['required'] && !$step['completed']) {
230                return $step['id'];
231            }
232            // Otherwise do the first step after the current one that is active.
233            if ($step['active'] && $pos > $this->getPosition()) {
234                return $step['id'];
235            }
236        }
237        return null;
238    }
239
240    /**
241     * To set a set as 'completed'.
242     * @return string  Step identifyer of the next step.
243     * @access public
244     */
245    function complete($step_id=null)
246    {
247        $pos = isset($step_id) ? $this->getPosition($step_id) : $this->getPosition();
248        $_SESSION[$this->seq]['steps'][$pos]['completed'] = true;
249    }
250
251    /**
252     * Prints the a link that returns to the form for a step.
253     *
254     * @param  string $form_type  'form' or 'disp'.
255     * @param  string $step_id    ID of step.
256     * @return string             Filename of template.
257     * @access public
258     */
259    function printEditLink($step_id=null)
260    {
261        $app =& App::getInstance();
262
263        $pos = isset($step_id) ? $this->getPosition($step_id) : $this->getPosition();
264        if ($_SESSION[$this->seq]['steps'][$pos]['editable']) {
265            printf('[<a href="%s">%s</a>]', $app->oHREF($_SERVER['PHP_SELF'] . '?step=' . $pos . '&boomerang=confirmation'), _("edit"));
266        }
267    }
268
269    /**
270     * Saves given $step_data (usually coming from $_POST) into $_SESSION
271     * array with the $step_id as the key.
272     *
273     * @param  string $step_id   ID of current step.
274     * @param  mixed  $step_data Data to place into session storage.
275     * @return string  Step identifyer of the next step.
276     * @access public
277     */
278    function setDataDefault($data_key, $data_val)
279    {
280        if (!isset($_SESSION[$this->seq]['data'][$data_key])) {
281            $_SESSION[$this->seq]['data'][$data_key] = $data_val;
282            $_SESSION[$this->seq]['defaults'][$data_key] = $data_val;
283        }
284    }
285
286    /**
287     * Returns the value saved in $_SESSION for a specific data key.
288     *
289     * @param  mixed  $data_key  Key of data to return from session data.
290     * @access public
291     */
292    function getData($data_key=null)
293    {
294        if (!isset($data_key)) {
295            return $_SESSION[$this->seq]['data'];
296        }
297        if (isset($_SESSION[$this->seq]['data'][$data_key])) {
298            return $_SESSION[$this->seq]['data'][$data_key];
299        } else {
300            return null;
301        }
302    }
303
304    /**
305     * Deletes all data saved in $_SESSION.
306     *
307     * @param  mixed  $data_key  Key of data to return from session data.
308     * @access public
309     */
310    function clearData($data_key=null)
311    {
312        if (isset($data_key)) {
313            // Clear a specific key.
314            $_SESSION[$this->seq]['data'][$key] = array();
315        } else {
316            // Clear the whole thing.
317            $_SESSION[$this->seq]['data'] = array();
318        }
319    }
320
321    /**
322     * Delete's all data that are older than auto_timeout. Set current time if not not expired or not set.
323     */
324    function _auto_timeout()
325    {
326        $app =& App::getInstance();
327
328        if (isset($_SESSION[$this->seq]['last_access_time'])
329        && $_SESSION[$this->seq]['last_access_time'] < time() - $this->idle_timeout) {
330            // Session has expired, flush all vars to start over.
331            $this->startOver();
332            $app->dieURL($this->start_url);
333        } else {
334            // Set timer.
335            $_SESSION[$this->seq]['last_access_time'] = time();
336        }
337    }
338
339    /**
340     * Saves given array (usually coming from $_POST) into $_SESSION
341     *
342     * @param  mixed  $step_data  Array of data to merge with session data.
343     * @access public
344     */
345    function registerData($step_data)
346    {
347        $_SESSION[$this->seq]['data'] = array_merge($_SESSION[$this->seq]['data'], $step_data);
348    }
349
350    /**
351     * Reset all vars.
352     *
353     */
354    function startOver()
355    {
356        $this->current_step_id = 0;
357        $_SESSION[$this->seq]['steps'] = array();
358        $_SESSION[$this->seq]['data'] = array();
359        $_SESSION[$this->seq]['defaults'] = array();
360        $_SESSION[$this->seq]['last_access_time'] = time();
361    }
362
363    /**
364     * Template function to be extended with custom SQL code.
365     *
366     * @return int  Unique DB identifyer for saved record.
367     * @access public
368     */
369    function saveData()
370    {
371        return false;
372    }
373
374    /**
375     * Template function to be extended with custom SQL code.
376     *
377     * @return mixed  Data stored in DB.
378     * @access public
379     */
380    function loadData()
381    {
382        return false;
383    }
384
385
386} // END CLASS
387
388?>
Note: See TracBrowser for help on using the repository browser.