source: tags/2.1.5/lib/PageSequence.inc.php

Last change on this file was 377, checked in by quinn, 14 years ago

Releasing trunk as stable version 2.1.5

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