@@ -8,27 +8,42 @@ class BasicCaptcha
88{
99 protected $ session = null ;
1010 protected $ key = 'basic_captcha_value ' ;
11+ protected $ typeKey = 'basic_captcha_type ' ;
12+ protected $ config = null ;
1113
12- public function __construct ()
14+ public function __construct ($ fieldConfig = null )
1315 {
1416 $ this ->session = Grav::instance ()['session ' ];
17+
18+ // Load global configuration
19+ $ globalConfig = Grav::instance ()['config ' ]->get ('plugins.form.basic_captcha ' , []);
20+
21+ // Merge field-specific config with global config
22+ if ($ fieldConfig && is_array ($ fieldConfig )) {
23+ $ this ->config = array_replace_recursive ($ globalConfig , $ fieldConfig );
24+ } else {
25+ $ this ->config = $ globalConfig ;
26+ }
1527 }
1628
1729 public function getCaptchaCode ($ length = null ): string
1830 {
19- $ config = Grav::instance ()['config ' ]->get ('plugins.form.basic_captcha ' );
20- $ type = $ config ['type ' ] ?? 'characters ' ;
31+ // Support both 'type' (from global config) and 'captcha_type' (from field config)
32+ $ type = $ this ->config ['captcha_type ' ] ?? $ this ->config ['type ' ] ?? 'characters ' ;
33+
34+ // Store the captcha type in session for validation
35+ $ this ->setSession ($ this ->typeKey , $ type );
2136
2237 switch ($ type ) {
2338 case 'dotcount ' :
24- return $ this ->getDotCountCaptcha ($ config );
39+ return $ this ->getDotCountCaptcha ($ this -> config );
2540 case 'position ' :
26- return $ this ->getPositionCaptcha ($ config );
41+ return $ this ->getPositionCaptcha ($ this -> config );
2742 case 'math ' :
28- return $ this ->getMathCaptcha ($ config );
43+ return $ this ->getMathCaptcha ($ this -> config );
2944 case 'characters ' :
3045 default :
31- return $ this ->getCharactersCaptcha ($ config , $ length );
46+ return $ this ->getCharactersCaptcha ($ this -> config , $ length );
3247 }
3348 }
3449
@@ -158,15 +173,37 @@ public function getSession($key = null): ?string
158173 */
159174 public function createCaptchaImage ($ captcha_code )
160175 {
161- $ config = Grav::instance ()['config ' ]->get ('plugins.form.basic_captcha ' );
162- $ width = $ config ['image ' ]['width ' ] ?? 135 ;
163- $ height = $ config ['image ' ]['height ' ] ?? 40 ;
176+ // Determine image dimensions based on type
177+ $ isCharacterCaptcha = false ;
178+ if (strpos ($ captcha_code , '| ' ) === false && !preg_match ('/[\+\-x]/ ' , $ captcha_code )) {
179+ $ isCharacterCaptcha = true ;
180+ }
181+
182+ // Use box_width/box_height for character captchas if specified, otherwise use default image dimensions
183+ if ($ isCharacterCaptcha && isset ($ this ->config ['chars ' ]['box_width ' ])) {
184+ $ width = $ this ->config ['chars ' ]['box_width ' ];
185+ } else {
186+ $ width = $ this ->config ['image ' ]['width ' ] ?? 135 ;
187+ }
188+
189+ if ($ isCharacterCaptcha && isset ($ this ->config ['chars ' ]['box_height ' ])) {
190+ $ height = $ this ->config ['chars ' ]['box_height ' ];
191+ } else {
192+ $ height = $ this ->config ['image ' ]['height ' ] ?? 40 ;
193+ }
164194
165195 // Create a blank image
166196 $ image = imagecreatetruecolor ($ width , $ height );
167197
168- // Set background color
169- $ bg = $ this ->hexToRgb ($ config ['image ' ]['bg ' ] ?? '#ffffff ' );
198+ // Set background color (support both image.bg and chars.bg for character captchas)
199+ $ bgColor = '#ffffff ' ;
200+ if ($ isCharacterCaptcha && isset ($ this ->config ['chars ' ]['bg ' ])) {
201+ $ bgColor = $ this ->config ['chars ' ]['bg ' ];
202+ } elseif (isset ($ this ->config ['image ' ]['bg ' ])) {
203+ $ bgColor = $ this ->config ['image ' ]['bg ' ];
204+ }
205+
206+ $ bg = $ this ->hexToRgb ($ bgColor );
170207 $ backgroundColor = imagecolorallocate ($ image , $ bg [0 ], $ bg [1 ], $ bg [2 ]);
171208 imagefill ($ image , 0 , 0 , $ backgroundColor );
172209
@@ -177,16 +214,16 @@ public function createCaptchaImage($captcha_code)
177214
178215 switch ($ type ) {
179216 case 'count_dots ' :
180- return $ this ->createDotCountImage ($ image , $ parts , $ config );
217+ return $ this ->createDotCountImage ($ image , $ parts , $ this -> config );
181218 case 'position ' :
182- return $ this ->createPositionImage ($ image , $ parts , $ config );
219+ return $ this ->createPositionImage ($ image , $ parts , $ this -> config );
183220 }
184221 } else {
185222 // Assume it's a character or math captcha if no type indicator
186223 if (preg_match ('/[\+\-x]/ ' , $ captcha_code )) {
187- return $ this ->createMathImage ($ image , $ captcha_code , $ config );
224+ return $ this ->createMathImage ($ image , $ captcha_code , $ this -> config );
188225 } else {
189- return $ this ->createCharacterImage ($ image , $ captcha_code , $ config );
226+ return $ this ->createCharacterImage ($ image , $ captcha_code , $ this -> config );
190227 }
191228 }
192229
@@ -408,21 +445,28 @@ protected function createCharacterImage($image, $captcha_code, $config)
408445 $ width = imagesx ($ image );
409446 $ height = imagesy ($ image );
410447
411- // Get font settings
448+ // Get font settings with support for custom box dimensions, position, and colors
412449 $ fontPath = __DIR__ .'/../../fonts/ ' .($ config ['chars ' ]['font ' ] ?? 'zxx-xed.ttf ' );
413450 $ fontSize = $ config ['chars ' ]['size ' ] ?? 16 ;
414- $ textColor = imagecolorallocate ($ image , 0 , 0 , 0 );
451+
452+ // Support custom text color (defaults to black)
453+ $ textColorHex = $ config ['chars ' ]['text ' ] ?? '#000000 ' ;
454+ $ textRgb = $ this ->hexToRgb ($ textColorHex );
455+ $ textColor = imagecolorallocate ($ image , $ textRgb [0 ], $ textRgb [1 ], $ textRgb [2 ]);
456+
457+ // Support custom start position (useful for fine-tuning text placement)
458+ $ startX = $ config ['chars ' ]['start_x ' ] ?? ($ width / (strlen ($ captcha_code ) + 2 ));
459+ $ baseY = $ config ['chars ' ]['start_y ' ] ?? ($ height / 2 + 5 );
415460
416461 // Draw each character with random rotation and position
417462 $ charWidth = $ width / (strlen ($ captcha_code ) + 2 );
418- $ startX = $ charWidth ; // Leave some space at the beginning
419463
420464 for ($ i = 0 ; $ i < strlen ($ captcha_code ); $ i ++) {
421465 $ char = $ captcha_code [$ i ];
422466 $ angle = mt_rand (-15 , 15 ); // Random rotation
423467
424- // Random vertical position
425- $ y = mt_rand ( $ height / 2 - 5 , $ height / 2 + 5 );
468+ // Random vertical position with custom base Y
469+ $ y = $ baseY + mt_rand (- 5 , 5 );
426470
427471 imagettftext ($ image , $ fontSize , $ angle , $ startX , $ y , $ textColor , $ fontPath , $ char );
428472
0 commit comments