PageRenderTime 96ms CodeModel.GetById 46ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Session/SaveHandler/DbTable.php

https://bitbucket.org/hamidrezas/melobit
PHP | 591 lines | 270 code | 73 blank | 248 comment | 42 complexity | c5d56c6456909d8504bc54b4c11114b1 MD5 | raw file
Possible License(s): AGPL-1.0
  1<?php
  2
  3/**
  4 * Zend Framework
  5 *
  6 * LICENSE
  7 *
  8 * This source file is subject to the new BSD license that is bundled
  9 * with this package in the file LICENSE.txt.
 10 * It is also available through the world-wide-webat this URL:
 11 * http://framework.zend.com/license/new-bsd
 12 * If you did not receive a copy of the license and are unable to
 13 * obtain it through the world-wide-web, please send an email
 14 * to license@zend.com so we can send you a copy immediately.
 15 *
 16 * @category   Zend
 17 * @package    Zend_Session
 18 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 20 * @version    $Id: DbTable.php 24594 2012-01-05 21:27:01Z matthew $
 21 */
 22
 23/**
 24 * @see Zend_Session
 25 */
 26require_once 'Zend/Session.php';
 27
 28/**
 29 * @see Zend_Db_Table_Abstract
 30 */
 31require_once 'Zend/Db/Table/Abstract.php';
 32
 33/**
 34 * @see Zend_Db_Table_Row_Abstract
 35 */
 36require_once 'Zend/Db/Table/Row/Abstract.php';
 37
 38/**
 39 * @see Zend_Config
 40 */
 41require_once 'Zend/Config.php';
 42
 43/**
 44 * Zend_Session_SaveHandler_DbTable
 45 *
 46 * @category   Zend
 47 * @package    Zend_Session
 48 * @subpackage SaveHandler
 49 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 50 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 51 */
 52class Zend_Session_SaveHandler_DbTable
 53    extends Zend_Db_Table_Abstract
 54    implements Zend_Session_SaveHandler_Interface
 55{
 56    const PRIMARY_ASSIGNMENT                   = 'primaryAssignment';
 57    const PRIMARY_ASSIGNMENT_SESSION_SAVE_PATH = 'sessionSavePath';
 58    const PRIMARY_ASSIGNMENT_SESSION_NAME      = 'sessionName';
 59    const PRIMARY_ASSIGNMENT_SESSION_ID        = 'sessionId';
 60
 61    const MODIFIED_COLUMN   = 'modifiedColumn';
 62    const LIFETIME_COLUMN   = 'lifetimeColumn';
 63    const DATA_COLUMN       = 'dataColumn';
 64
 65    const LIFETIME          = 'lifetime';
 66    const OVERRIDE_LIFETIME = 'overrideLifetime';
 67
 68    const PRIMARY_TYPE_NUM         = 'PRIMARY_TYPE_NUM';
 69    const PRIMARY_TYPE_PRIMARYNUM  = 'PRIMARY_TYPE_PRIMARYNUM';
 70    const PRIMARY_TYPE_ASSOC       = 'PRIMARY_TYPE_ASSOC';
 71    const PRIMARY_TYPE_WHERECLAUSE = 'PRIMARY_TYPE_WHERECLAUSE';
 72
 73    /**
 74     * Session table primary key value assignment
 75     *
 76     * @var array
 77     */
 78    protected $_primaryAssignment = null;
 79
 80    /**
 81     * Session table last modification time column
 82     *
 83     * @var string
 84     */
 85    protected $_modifiedColumn = null;
 86
 87    /**
 88     * Session table lifetime column
 89     *
 90     * @var string
 91     */
 92    protected $_lifetimeColumn = null;
 93
 94    /**
 95     * Session table data column
 96     *
 97     * @var string
 98     */
 99    protected $_dataColumn = null;
100
101    /**
102     * Session lifetime
103     *
104     * @var int
105     */
106    protected $_lifetime = false;
107
108    /**
109     * Whether or not the lifetime of an existing session should be overridden
110     *
111     * @var boolean
112     */
113    protected $_overrideLifetime = false;
114
115    /**
116     * Session save path
117     *
118     * @var string
119     */
120    protected $_sessionSavePath;
121
122    /**
123     * Session name
124     *
125     * @var string
126     */
127    protected $_sessionName;
128
129    /**
130     * Constructor
131     *
132     * $config is an instance of Zend_Config or an array of key/value pairs containing configuration options for
133     * Zend_Session_SaveHandler_DbTable and Zend_Db_Table_Abstract. These are the configuration options for
134     * Zend_Session_SaveHandler_DbTable:
135     *
136     * primaryAssignment => (string|array) Session table primary key value assignment
137     *      (optional; default: 1 => sessionId) You have to assign a value to each primary key of your session table.
138     *      The value of this configuration option is either a string if you have only one primary key or an array if
139     *      you have multiple primary keys. The array consists of numeric keys starting at 1 and string values. There
140     *      are some values which will be replaced by session information:
141     *
142     *      sessionId       => The id of the current session
143     *      sessionName     => The name of the current session
144     *      sessionSavePath => The save path of the current session
145     *
146     *      NOTE: One of your assignments MUST contain 'sessionId' as value!
147     *
148     * modifiedColumn    => (string) Session table last modification time column
149     *
150     * lifetimeColumn    => (string) Session table lifetime column
151     *
152     * dataColumn        => (string) Session table data column
153     *
154     * lifetime          => (integer) Session lifetime (optional; default: ini_get('session.gc_maxlifetime'))
155     *
156     * overrideLifetime  => (boolean) Whether or not the lifetime of an existing session should be overridden
157     *      (optional; default: false)
158     *
159     * @param  Zend_Config|array $config      User-provided configuration
160     * @return void
161     * @throws Zend_Session_SaveHandler_Exception
162     */
163    public function __construct($config)
164    {
165        if ($config instanceof Zend_Config) {
166            $config = $config->toArray();
167        } else if (!is_array($config)) {
168            /**
169             * @see Zend_Session_SaveHandler_Exception
170             */
171            require_once 'Zend/Session/SaveHandler/Exception.php';
172
173            throw new Zend_Session_SaveHandler_Exception(
174                '$config must be an instance of Zend_Config or array of key/value pairs containing '
175              . 'configuration options for Zend_Session_SaveHandler_DbTable and Zend_Db_Table_Abstract.');
176        }
177
178        foreach ($config as $key => $value) {
179            do {
180                switch ($key) {
181                    case self::PRIMARY_ASSIGNMENT:
182                        $this->_primaryAssignment = $value;
183                        break;
184                    case self::MODIFIED_COLUMN:
185                        $this->_modifiedColumn = (string) $value;
186                        break;
187                    case self::LIFETIME_COLUMN:
188                        $this->_lifetimeColumn = (string) $value;
189                        break;
190                    case self::DATA_COLUMN:
191                        $this->_dataColumn = (string) $value;
192                        break;
193                    case self::LIFETIME:
194                        $this->setLifetime($value);
195                        break;
196                    case self::OVERRIDE_LIFETIME:
197                        $this->setOverrideLifetime($value);
198                        break;
199                    default:
200                        // unrecognized options passed to parent::__construct()
201                        break 2;
202                }
203                unset($config[$key]);
204            } while (false);
205        }
206
207        parent::__construct($config);
208    }
209
210    /**
211     * Destructor
212     *
213     * @return void
214     */
215    public function __destruct()
216    {
217        Zend_Session::writeClose();
218    }
219
220    /**
221     * Set session lifetime and optional whether or not the lifetime of an existing session should be overridden
222     *
223     * $lifetime === false resets lifetime to session.gc_maxlifetime
224     *
225     * @param int $lifetime
226     * @param boolean $overrideLifetime (optional)
227     * @return Zend_Session_SaveHandler_DbTable
228     */
229    public function setLifetime($lifetime, $overrideLifetime = null)
230    {
231        if ($lifetime < 0) {
232            /**
233             * @see Zend_Session_SaveHandler_Exception
234             */
235            require_once 'Zend/Session/SaveHandler/Exception.php';
236            throw new Zend_Session_SaveHandler_Exception();
237        } else if (empty($lifetime)) {
238            $this->_lifetime = (int) ini_get('session.gc_maxlifetime');
239        } else {
240            $this->_lifetime = (int) $lifetime;
241        }
242
243        if ($overrideLifetime != null) {
244            $this->setOverrideLifetime($overrideLifetime);
245        }
246
247        return $this;
248    }
249
250    /**
251     * Retrieve session lifetime
252     *
253     * @return int
254     */
255    public function getLifetime()
256    {
257        return $this->_lifetime;
258    }
259
260    /**
261     * Set whether or not the lifetime of an existing session should be overridden
262     *
263     * @param boolean $overrideLifetime
264     * @return Zend_Session_SaveHandler_DbTable
265     */
266    public function setOverrideLifetime($overrideLifetime)
267    {
268        $this->_overrideLifetime = (boolean) $overrideLifetime;
269
270        return $this;
271    }
272
273    /**
274     * Retrieve whether or not the lifetime of an existing session should be overridden
275     *
276     * @return boolean
277     */
278    public function getOverrideLifetime()
279    {
280        return $this->_overrideLifetime;
281    }
282
283    /**
284     * Open Session
285     *
286     * @param string $save_path
287     * @param string $name
288     * @return boolean
289     */
290    public function open($save_path, $name)
291    {
292        $this->_sessionSavePath = $save_path;
293        $this->_sessionName     = $name;
294
295        return true;
296    }
297
298    /**
299     * Close session
300     *
301     * @return boolean
302     */
303    public function close()
304    {
305        return true;
306    }
307
308    /**
309     * Read session data
310     *
311     * @param string $id
312     * @return string
313     */
314    public function read($id)
315    {
316        $return = '';
317
318        $rows = call_user_func_array(array(&$this, 'find'), $this->_getPrimary($id));
319
320        if (count($rows)) {
321            if ($this->_getExpirationTime($row = $rows->current()) > time()) {
322                $return = $row->{$this->_dataColumn};
323            } else {
324                $this->destroy($id);
325            }
326        }
327
328        return $return;
329    }
330
331    /**
332     * Write session data
333     *
334     * @param string $id
335     * @param string $data
336     * @return boolean
337     */
338    public function write($id, $data)
339    {
340        $return = false;
341
342        $data = array($this->_modifiedColumn => time(),
343                      $this->_dataColumn     => (string) $data);
344
345        $rows = call_user_func_array(array(&$this, 'find'), $this->_getPrimary($id));
346
347        if (count($rows)) {
348            $data[$this->_lifetimeColumn] = $this->_getLifetime($rows->current());
349
350            if ($this->update($data, $this->_getPrimary($id, self::PRIMARY_TYPE_WHERECLAUSE))) {
351                $return = true;
352            }
353        } else {
354            $data[$this->_lifetimeColumn] = $this->_lifetime;
355
356            if ($this->insert(array_merge($this->_getPrimary($id, self::PRIMARY_TYPE_ASSOC), $data))) {
357                $return = true;
358            }
359        }
360
361        return $return;
362    }
363
364    /**
365     * Destroy session
366     *
367     * @param string $id
368     * @return boolean
369     */
370    public function destroy($id)
371    {
372        $return = false;
373
374        if ($this->delete($this->_getPrimary($id, self::PRIMARY_TYPE_WHERECLAUSE))) {
375            $return = true;
376        }
377
378        return $return;
379    }
380
381    /**
382     * Garbage Collection
383     *
384     * @param int $maxlifetime
385     * @return true
386     */
387    public function gc($maxlifetime)
388    {
389        $this->delete($this->getAdapter()->quoteIdentifier($this->_modifiedColumn, true) . ' + '
390                    . $this->getAdapter()->quoteIdentifier($this->_lifetimeColumn, true) . ' < '
391                    . $this->getAdapter()->quote(time()));
392
393        return true;
394    }
395
396    /**
397     * Calls other protected methods for individual setup tasks and requirement checks
398     *
399     * @return void
400     */
401    protected function _setup()
402    {
403        parent::_setup();
404
405        $this->_setupPrimaryAssignment();
406        $this->setLifetime($this->_lifetime);
407
408        $this->_checkRequiredColumns();
409    }
410
411    /**
412     * Initialize table and schema names
413     *
414     * @return void
415     * @throws Zend_Session_SaveHandler_Exception
416     */
417    protected function _setupTableName()
418    {
419        if (empty($this->_name) && basename(($this->_name = session_save_path())) != $this->_name) {
420            /**
421             * @see Zend_Session_SaveHandler_Exception
422             */
423            require_once 'Zend/Session/SaveHandler/Exception.php';
424
425            throw new Zend_Session_SaveHandler_Exception('session.save_path is a path and not a table name.');
426        }
427
428        if (strpos($this->_name, '.')) {
429            list($this->_schema, $this->_name) = explode('.', $this->_name);
430        }
431    }
432
433    /**
434     * Initialize session table primary key value assignment
435     *
436     * @return void
437     * @throws Zend_Session_SaveHandler_Exception
438     */
439    protected function _setupPrimaryAssignment()
440    {
441        if ($this->_primaryAssignment === null) {
442            $this->_primaryAssignment = array(1 => self::PRIMARY_ASSIGNMENT_SESSION_ID);
443        } else if (!is_array($this->_primaryAssignment)) {
444            $this->_primaryAssignment = array(1 => (string) $this->_primaryAssignment);
445        } else if (isset($this->_primaryAssignment[0])) {
446            array_unshift($this->_primaryAssignment, null);
447
448            unset($this->_primaryAssignment[0]);
449        }
450
451        if (count($this->_primaryAssignment) !== count($this->_primary)) {
452            /**
453             * @see Zend_Session_SaveHandler_Exception
454             */
455            require_once 'Zend/Session/SaveHandler/Exception.php';
456
457            throw new Zend_Session_SaveHandler_Exception(
458                "Value for configuration option '" . self::PRIMARY_ASSIGNMENT . "' must have an assignment "
459              . "for each session table primary key.");
460        } else if (!in_array(self::PRIMARY_ASSIGNMENT_SESSION_ID, $this->_primaryAssignment)) {
461            /**
462             * @see Zend_Session_SaveHandler_Exception
463             */
464            require_once 'Zend/Session/SaveHandler/Exception.php';
465
466            throw new Zend_Session_SaveHandler_Exception(
467                "Value for configuration option '" . self::PRIMARY_ASSIGNMENT . "' must have an assignment "
468              . "for the session id ('" . self::PRIMARY_ASSIGNMENT_SESSION_ID . "').");
469        }
470    }
471
472    /**
473     * Check for required session table columns
474     *
475     * @return void
476     * @throws Zend_Session_SaveHandler_Exception
477     */
478    protected function _checkRequiredColumns()
479    {
480        if ($this->_modifiedColumn === null) {
481            /**
482             * @see Zend_Session_SaveHandler_Exception
483             */
484            require_once 'Zend/Session/SaveHandler/Exception.php';
485
486            throw new Zend_Session_SaveHandler_Exception(
487                "Configuration must define '" . self::MODIFIED_COLUMN . "' which names the "
488              . "session table last modification time column.");
489        } else if ($this->_lifetimeColumn === null) {
490            /**
491             * @see Zend_Session_SaveHandler_Exception
492             */
493            require_once 'Zend/Session/SaveHandler/Exception.php';
494
495            throw new Zend_Session_SaveHandler_Exception(
496                "Configuration must define '" . self::LIFETIME_COLUMN . "' which names the "
497              . "session table lifetime column.");
498        } else if ($this->_dataColumn === null) {
499            /**
500             * @see Zend_Session_SaveHandler_Exception
501             */
502            require_once 'Zend/Session/SaveHandler/Exception.php';
503
504            throw new Zend_Session_SaveHandler_Exception(
505                "Configuration must define '" . self::DATA_COLUMN . "' which names the "
506              . "session table data column.");
507        }
508    }
509
510    /**
511     * Retrieve session table primary key values
512     *
513     * @param string $id
514     * @param string $type (optional; default: self::PRIMARY_TYPE_NUM)
515     * @return array
516     */
517    protected function _getPrimary($id, $type = null)
518    {
519        $this->_setupPrimaryKey();
520
521        if ($type === null) {
522            $type = self::PRIMARY_TYPE_NUM;
523        }
524
525        $primaryArray = array();
526
527        foreach ($this->_primary as $index => $primary) {
528            switch ($this->_primaryAssignment[$index]) {
529                case self::PRIMARY_ASSIGNMENT_SESSION_SAVE_PATH:
530                    $value = $this->_sessionSavePath;
531                    break;
532                case self::PRIMARY_ASSIGNMENT_SESSION_NAME:
533                    $value = $this->_sessionName;
534                    break;
535                case self::PRIMARY_ASSIGNMENT_SESSION_ID:
536                    $value = (string) $id;
537                    break;
538                default:
539                    $value = (string) $this->_primaryAssignment[$index];
540                    break;
541            }
542
543            switch ((string) $type) {
544                case self::PRIMARY_TYPE_PRIMARYNUM:
545                    $primaryArray[$index] = $value;
546                    break;
547                case self::PRIMARY_TYPE_ASSOC:
548                    $primaryArray[$primary] = $value;
549                    break;
550                case self::PRIMARY_TYPE_WHERECLAUSE:
551                    $primaryArray[] = $this->getAdapter()->quoteIdentifier($primary, true) . ' = '
552                                    . $this->getAdapter()->quote($value);
553                    break;
554                case self::PRIMARY_TYPE_NUM:
555                default:
556                    $primaryArray[] = $value;
557                    break;
558            }
559        }
560
561        return $primaryArray;
562    }
563
564    /**
565     * Retrieve session lifetime considering Zend_Session_SaveHandler_DbTable::OVERRIDE_LIFETIME
566     *
567     * @param Zend_Db_Table_Row_Abstract $row
568     * @return int
569     */
570    protected function _getLifetime(Zend_Db_Table_Row_Abstract $row)
571    {
572        $return = $this->_lifetime;
573
574        if (!$this->_overrideLifetime) {
575            $return = (int) $row->{$this->_lifetimeColumn};
576        }
577
578        return $return;
579    }
580
581    /**
582     * Retrieve session expiration time
583     *
584     * @param Zend_Db_Table_Row_Abstract $row
585     * @return int
586     */
587    protected function _getExpirationTime(Zend_Db_Table_Row_Abstract $row)
588    {
589        return (int) $row->{$this->_modifiedColumn} + $this->_getLifetime($row);
590    }
591}