1 <?php defined('SYSPATH') OR die('No direct access allowed.');
5 * $Id: Captcha.php 4072 2009-03-13 17:20:38Z jheathco $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
15 protected static $instance;
17 // Style-dependent Captcha driver
21 public static $config = array
34 * Singleton instance of Captcha.
38 public static function instance()
40 // Create the instance if it does not exist
41 empty(Captcha::$instance) and new Captcha;
43 return Captcha::$instance;
47 * Constructs and returns a new Captcha object.
49 * @param string config group name
52 public static function factory($group = NULL)
54 return new Captcha($group);
58 * Constructs a new Captcha object.
60 * @throws Kohana_Exception
61 * @param string config group name
64 public function __construct($group = NULL)
66 // Create a singleton instance once
67 empty(Captcha::$instance) and Captcha::$instance = $this;
69 // No config group name given
70 if ( ! is_string($group))
75 // Load and validate config group
76 if ( ! is_array($config = Kohana::config('captcha.'.$group)))
77 throw new Kohana_Exception('captcha.undefined_group', $group);
79 // All captcha config groups inherit default config group
80 if ($group !== 'default')
82 // Load and validate default config group
83 if ( ! is_array($default = Kohana::config('captcha.default')))
84 throw new Kohana_Exception('captcha.undefined_group', 'default');
86 // Merge config group with default config group
90 // Assign config values to the object
91 foreach ($config as $key => $value)
93 if (array_key_exists($key, Captcha::$config))
95 Captcha::$config[$key] = $value;
99 // Store the config group name as well, so the drivers can access it
100 Captcha::$config['group'] = $group;
102 // If using a background image, check if it exists
103 if ( ! empty($config['background']))
105 Captcha::$config['background'] = str_replace('\\', '/', realpath($config['background']));
107 if ( ! is_file(Captcha::$config['background']))
108 throw new Kohana_Exception('captcha.file_not_found', Captcha::$config['background']);
111 // If using any fonts, check if they exist
112 if ( ! empty($config['fonts']))
114 Captcha::$config['fontpath'] = str_replace('\\', '/', realpath($config['fontpath'])).'/';
116 foreach ($config['fonts'] as $font)
118 if ( ! is_file(Captcha::$config['fontpath'].$font))
119 throw new Kohana_Exception('captcha.file_not_found', Captcha::$config['fontpath'].$font);
124 $driver = 'Captcha_'.ucfirst($config['style']).'_Driver';
127 if ( ! Kohana::auto_load($driver))
128 throw new Kohana_Exception('core.driver_not_found', $config['style'], get_class($this));
130 // Initialize the driver
131 $this->driver = new $driver;
133 // Validate the driver
134 if ( ! ($this->driver instanceof Captcha_Driver))
135 throw new Kohana_Exception('core.driver_implements', $config['style'], get_class($this), 'Captcha_Driver');
137 Kohana::log('debug', 'Captcha Library initialized');
141 * Validates a Captcha response and updates response counter.
143 * @param string captcha response
146 public static function valid($response)
148 // Maximum one count per page load
151 // User has been promoted, always TRUE and don't count anymore
152 if (Captcha::instance()->promoted())
156 $result = (bool) Captcha::instance()->driver->valid($response);
158 // Increment response counter
159 if ($counted !== TRUE)
164 if ($result === TRUE)
166 Captcha::instance()->valid_count(Session::instance()->get('captcha_valid_count') + 1);
171 Captcha::instance()->invalid_count(Session::instance()->get('captcha_invalid_count') + 1);
179 * Gets or sets the number of valid Captcha responses for this session.
181 * @param integer new counter value
182 * @param boolean trigger invalid counter (for internal use only)
183 * @return integer counter value
185 public function valid_count($new_count = NULL, $invalid = FALSE)
187 // Pick the right session to use
188 $session = ($invalid === TRUE) ? 'captcha_invalid_count' : 'captcha_valid_count';
191 if ($new_count !== NULL)
193 $new_count = (int) $new_count;
195 // Reset counter = delete session
198 Session::instance()->delete($session);
200 // Set counter to new value
203 Session::instance()->set($session, (int) $new_count);
207 return (int) $new_count;
210 // Return current count
211 return (int) Session::instance()->get($session);
215 * Gets or sets the number of invalid Captcha responses for this session.
217 * @param integer new counter value
218 * @return integer counter value
220 public function invalid_count($new_count = NULL)
222 return $this->valid_count($new_count, TRUE);
226 * Resets the Captcha response counters and removes the count sessions.
230 public function reset_count()
232 $this->valid_count(0);
233 $this->valid_count(0, TRUE);
237 * Checks whether user has been promoted after having given enough valid responses.
239 * @param integer valid response count threshold
242 public function promoted($threshold = NULL)
244 // Promotion has been disabled
245 if (Captcha::$config['promote'] === FALSE)
248 // Use the config threshold
249 if ($threshold === NULL)
251 $threshold = Captcha::$config['promote'];
254 // Compare the valid response count to the threshold
255 return ($this->valid_count() >= $threshold);
259 * Returns or outputs the Captcha challenge.
261 * @param boolean TRUE to output html, e.g. <img src="#" />
262 * @return mixed html string or void
264 public function render($html = TRUE)
266 return $this->driver->render($html);
270 * Magically outputs the Captcha challenge.
274 public function __toString()
276 return $this->render();
279 } // End Captcha Class