/protected/components/ezcomponents/AuthenticationDatabaseTiein/src/filters/database/database_filter.php

https://github.com/kamarulismail/kamarul-playground · PHP · 308 lines · 121 code · 20 blank · 167 comment · 7 complexity · 6b43e62e8b0be1fca4b21d2ebb5aa69a MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcAuthenticationDatabaseFilter class.
  4. *
  5. * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
  6. * @license http://ez.no/licenses/new_bsd New BSD License
  7. * @filesource
  8. * @package AuthenticationDatabaseTiein
  9. * @version 1.1
  10. */
  11. /**
  12. * Filter to authenticate against a database.
  13. *
  14. * The database instance to use is specified using a ezcAuthenticationDatabaseInfo
  15. * structure. Table name and field names are specified in the same structure.
  16. *
  17. * Example:
  18. * <code>
  19. * $credentials = new ezcAuthenticationPasswordCredentials( 'jan.modaal', 'b1b3773a05c0ed0176787a4f1574ff0075f7521e' );
  20. * $database = new ezcAuthenticationDatabaseInfo( ezcDbInstance::get(), 'users', array( 'user', 'password' ) );
  21. * $authentication = new ezcAuthentication( $credentials );
  22. * $authentication->addFilter( new ezcAuthenticationDatabaseFilter( $database ) );
  23. * if ( !$authentication->run() )
  24. * {
  25. * // authentication did not succeed, so inform the user
  26. * $status = $authentication->getStatus();
  27. * $err = array(
  28. * 'ezcAuthenticationDatabaseFilter' => array(
  29. * ezcAuthenticationDatabaseFilter::STATUS_USERNAME_INCORRECT => 'Incorrect username',
  30. * ezcAuthenticationDatabaseFilter::STATUS_PASSWORD_INCORRECT => 'Incorrect password'
  31. * )
  32. * );
  33. * foreach ( $status as $line )
  34. * {
  35. * list( $key, $value ) = each( $line );
  36. * echo $err[$key][$value] . "\n";
  37. * }
  38. * }
  39. * else
  40. * {
  41. * // authentication succeeded, so allow the user to see his content
  42. * }
  43. * </code>
  44. *
  45. * Extra data can be fetched from the database during the authentication process,
  46. * by registering the data to be fetched before calling run(). Example:
  47. * <code>
  48. * // $filter is an ezcAuthenticationDatabaseFilter object
  49. * $filter->registerFetchData( array( 'name', 'country' ) );
  50. *
  51. * // after run()
  52. * $data = $filter->fetchData();
  53. * </code>
  54. *
  55. * The $data array will be something like:
  56. * <code>
  57. * array( 'name' => array( 'John Doe' ),
  58. * 'country' => array( 'US' )
  59. * );
  60. * </code>
  61. *
  62. * @property ezcAuthenticationDatabaseInfo $database
  63. * Structure which holds a database instance, table name and fields
  64. * which are used for authentication.
  65. *
  66. * @package AuthenticationDatabaseTiein
  67. * @version 1.1
  68. * @mainclass
  69. */
  70. class ezcAuthenticationDatabaseFilter extends ezcAuthenticationFilter implements ezcAuthenticationDataFetch
  71. {
  72. /**
  73. * Username is not found in the database.
  74. */
  75. const STATUS_USERNAME_INCORRECT = 1;
  76. /**
  77. * Password is incorrect.
  78. */
  79. const STATUS_PASSWORD_INCORRECT = 2;
  80. /**
  81. * Holds the attributes which will be requested during the authentication
  82. * process.
  83. *
  84. * Usually it has this structure:
  85. * <code>
  86. * array( 'fullname', 'gender', 'country', 'language' );
  87. * </code>
  88. *
  89. * @var array(string)
  90. */
  91. protected $requestedData = array();
  92. /**
  93. * Holds the extra data fetched during the authentication process.
  94. *
  95. * Usually it has this structure:
  96. * <code>
  97. * array( 'name' => array( 'John Doe' ),
  98. * 'country' => array( 'US' )
  99. * );
  100. * </code>
  101. *
  102. * @var array(string=>mixed)
  103. */
  104. protected $data = array();
  105. /**
  106. * Holds the properties of this class.
  107. *
  108. * @var array(string=>mixed)
  109. */
  110. private $properties = array();
  111. /**
  112. * Creates a new object of this class.
  113. *
  114. * @param ezcAuthenticationDatabaseInfo $database Database to use in authentication
  115. * @param ezcAuthenticationDatabaseOptions $options Options for this class
  116. */
  117. public function __construct( ezcAuthenticationDatabaseInfo $database, ezcAuthenticationDatabaseOptions $options = null )
  118. {
  119. $this->options = ( $options === null ) ? new ezcAuthenticationDatabaseOptions() : $options;
  120. $this->database = $database;
  121. }
  122. /**
  123. * Sets the property $name to $value.
  124. *
  125. * @throws ezcBasePropertyNotFoundException
  126. * if the property $name does not exist
  127. * @throws ezcBaseValueException
  128. * if $value is not correct for the property $name
  129. * @param string $name The name of the property to set
  130. * @param mixed $value The new value of the property
  131. * @ignore
  132. */
  133. public function __set( $name, $value )
  134. {
  135. switch ( $name )
  136. {
  137. case 'database':
  138. if ( $value instanceof ezcAuthenticationDatabaseInfo )
  139. {
  140. $this->properties[$name] = $value;
  141. }
  142. else
  143. {
  144. throw new ezcBaseValueException( $name, $value, 'ezcAuthenticationDatabaseInfo' );
  145. }
  146. break;
  147. default:
  148. throw new ezcBasePropertyNotFoundException( $name );
  149. }
  150. }
  151. /**
  152. * Returns the value of the property $name.
  153. *
  154. * @throws ezcBasePropertyNotFoundException
  155. * if the property $name does not exist
  156. * @param string $name The name of the property for which to return the value
  157. * @return mixed
  158. * @ignore
  159. */
  160. public function __get( $name )
  161. {
  162. switch ( $name )
  163. {
  164. case 'database':
  165. return $this->properties[$name];
  166. default:
  167. throw new ezcBasePropertyNotFoundException( $name );
  168. }
  169. }
  170. /**
  171. * Returns true if the property $name is set, otherwise false.
  172. *
  173. * @param string $name The name of the property to test if it is set
  174. * @return bool
  175. * @ignore
  176. */
  177. public function __isset( $name )
  178. {
  179. switch ( $name )
  180. {
  181. case 'database':
  182. return isset( $this->properties[$name] );
  183. default:
  184. return false;
  185. }
  186. }
  187. /**
  188. * Runs the filter and returns a status code when finished.
  189. *
  190. * @param ezcAuthenticationPasswordCredentials $credentials Authentication credentials
  191. * @return int
  192. */
  193. public function run( $credentials )
  194. {
  195. $db = $this->database;
  196. // see if username exists
  197. $query = new ezcQuerySelect( $db->instance );
  198. $e = $query->expr;
  199. $query->select( 'COUNT( ' . $db->instance->quoteIdentifier( $db->fields[0] ) . ' )' )
  200. ->from( $db->instance->quoteIdentifier( $db->table ) )
  201. ->where(
  202. $e->eq( $db->instance->quoteIdentifier( $db->fields[0] ), $query->bindValue( $credentials->id ) )
  203. );
  204. $rows = $query->prepare();
  205. $rows->execute();
  206. $count = (int)$rows->fetchColumn( 0 );
  207. if ( $count === 0 )
  208. {
  209. return self::STATUS_USERNAME_INCORRECT;
  210. }
  211. $rows->closeCursor();
  212. // see if username has the specified password
  213. $query = new ezcQuerySelect( $db->instance );
  214. $e = $query->expr;
  215. $query->select( 'COUNT( ' . $db->instance->quoteIdentifier( $db->fields[0] ) . ' )' )
  216. ->from( $db->instance->quoteIdentifier( $db->table ) )
  217. ->where( $e->lAnd(
  218. $e->eq( $db->instance->quoteIdentifier( $db->fields[0] ), $query->bindValue( $credentials->id ) ),
  219. $e->eq( $db->instance->quoteIdentifier( $db->fields[1] ), $query->bindValue( $credentials->password ) )
  220. ) );
  221. $rows = $query->prepare();
  222. $rows->execute();
  223. $count = (int)$rows->fetchColumn( 0 );
  224. if ( $count === 0 )
  225. {
  226. return self::STATUS_PASSWORD_INCORRECT;
  227. }
  228. $rows->closeCursor();
  229. if ( count( $this->requestedData ) > 0 )
  230. {
  231. // fetch extra data from the database
  232. $query = new ezcQuerySelect( $db->instance );
  233. $e = $query->expr;
  234. $params = array();
  235. foreach ( $this->requestedData as $param )
  236. {
  237. $params[] = $db->instance->quoteIdentifier( $param );
  238. }
  239. $query->select( implode( ', ', $params ) )
  240. ->from( $db->instance->quoteIdentifier( $db->table ) )
  241. ->where( $e->lAnd(
  242. $e->eq( $db->instance->quoteIdentifier( $db->fields[0] ), $query->bindValue( $credentials->id ) ),
  243. $e->eq( $db->instance->quoteIdentifier( $db->fields[1] ), $query->bindValue( $credentials->password ) )
  244. ) );
  245. $rows = $query->prepare();
  246. $rows->execute();
  247. $data = $rows->fetchAll();
  248. $data = $data[0];
  249. foreach ( $this->requestedData as $attribute )
  250. {
  251. $this->data[$attribute] = array( $data[$attribute] );
  252. }
  253. }
  254. return self::STATUS_OK;
  255. }
  256. /**
  257. * Registers the extra data which will be fetched by the filter during the
  258. * authentication process.
  259. *
  260. * The input $data should be an array of attributes, for example:
  261. * <code>
  262. * array( 'name', 'country' );
  263. * </code>
  264. *
  265. * @param array(string) $data The extra data to fetch during authentication
  266. */
  267. public function registerFetchData( array $data = array() )
  268. {
  269. $this->requestedData = $data;
  270. }
  271. /**
  272. * Returns the extra data which was fetched during the authentication process.
  273. *
  274. * Example of returned array:
  275. * <code>
  276. * array( 'name' => array( 'John Doe' ),
  277. * 'country' => array( 'US' )
  278. * );
  279. * </code>
  280. *
  281. * @return array(string=>mixed)
  282. */
  283. public function fetchData()
  284. {
  285. return $this->data;
  286. }
  287. }
  288. ?>