Captcha.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\captcha;
  8. use Yii;
  9. use yii\base\InvalidConfigException;
  10. use yii\helpers\Html;
  11. use yii\helpers\Json;
  12. use yii\widgets\InputWidget;
  13. /**
  14. * Captcha renders a CAPTCHA image and an input field that takes user-entered verification code.
  15. *
  16. * Captcha is used together with [[CaptchaAction]] provide [CAPTCHA](http://en.wikipedia.org/wiki/Captcha)
  17. * - a way of preventing Website spamming.
  18. *
  19. * The image element rendered by Captcha will display a CAPTCHA image generated by
  20. * an action whose route is specified by [[captchaAction]]. This action must be an instance of [[CaptchaAction]].
  21. *
  22. * When the user clicks on the CAPTCHA image, it will cause the CAPTCHA image
  23. * to be refreshed with a new CAPTCHA.
  24. *
  25. * You may use [[\yii\validators\CaptchaValidator]] to validate the user input matches
  26. * the current CAPTCHA verification code.
  27. *
  28. * @author Qiang Xue <[email protected]>
  29. * @since 2.0
  30. */
  31. class Captcha extends InputWidget
  32. {
  33. /**
  34. * @var string the route of the action that generates the CAPTCHA images.
  35. * The action represented by this route must be an action of [[CaptchaAction]].
  36. */
  37. public $captchaAction = 'site/captcha';
  38. /**
  39. * @var array HTML attributes to be applied to the CAPTCHA image tag.
  40. */
  41. public $imageOptions = [];
  42. /**
  43. * @var string the template for arranging the CAPTCHA image tag and the text input tag.
  44. * In this template, the token `{image}` will be replaced with the actual image tag,
  45. * while `{input}` will be replaced with the text input tag.
  46. */
  47. public $template = '{image} {input}';
  48. /**
  49. * @var array the HTML attributes for the input tag.
  50. */
  51. public $options = ['class' => 'form-control'];
  52. /**
  53. * Initializes the widget.
  54. */
  55. public function init()
  56. {
  57. parent::init();
  58. $this->checkRequirements();
  59. if (!isset($this->imageOptions['id'])) {
  60. $this->imageOptions['id'] = $this->options['id'] . '-image';
  61. }
  62. }
  63. /**
  64. * Renders the widget.
  65. */
  66. public function run()
  67. {
  68. $this->registerClientScript();
  69. if ($this->hasModel()) {
  70. $input = Html::activeTextInput($this->model, $this->attribute, $this->options);
  71. } else {
  72. $input = Html::textInput($this->name, $this->value, $this->options);
  73. }
  74. $url = Yii::$app->getUrlManager()->createUrl($this->captchaAction, ['v' => uniqid()]);
  75. $image = Html::img($url, $this->imageOptions);
  76. echo strtr($this->template, [
  77. '{input}' => $input,
  78. '{image}' => $image,
  79. ]);
  80. }
  81. /**
  82. * Registers the needed JavaScript.
  83. */
  84. public function registerClientScript()
  85. {
  86. $options = $this->getClientOptions();
  87. $options = empty($options) ? '' : Json::encode($options);
  88. $id = $this->imageOptions['id'];
  89. $view = $this->getView();
  90. CaptchaAsset::register($view);
  91. $view->registerJs("jQuery('#$id').yiiCaptcha($options);");
  92. }
  93. /**
  94. * Returns the options for the captcha JS widget.
  95. * @return array the options
  96. */
  97. protected function getClientOptions()
  98. {
  99. $options = [
  100. 'refreshUrl' => Html::url(['/' . $this->captchaAction, CaptchaAction::REFRESH_GET_VAR => 1]),
  101. 'hashKey' => "yiiCaptcha/{$this->captchaAction}",
  102. ];
  103. return $options;
  104. }
  105. /**
  106. * Checks if there is graphic extension available to generate CAPTCHA images.
  107. * This method will check the existence of ImageMagick and GD extensions.
  108. * @return string the name of the graphic extension, either "imagick" or "gd".
  109. * @throws InvalidConfigException if neither ImageMagick nor GD is installed.
  110. */
  111. public static function checkRequirements()
  112. {
  113. if (extension_loaded('imagick')) {
  114. $imagick = new \Imagick();
  115. $imagickFormats = $imagick->queryFormats('PNG');
  116. if (in_array('PNG', $imagickFormats)) {
  117. return 'imagick';
  118. }
  119. }
  120. if (extension_loaded('gd')) {
  121. $gdInfo = gd_info();
  122. if (!empty($gdInfo['FreeType Support'])) {
  123. return 'gd';
  124. }
  125. }
  126. throw new InvalidConfigException('GD with FreeType or ImageMagick PHP extensions are required.');
  127. }
  128. }