Completed
Branch master (380ad8)
by Pierre-Henry
33:44
created

Captcha::getFont()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 6
rs 9.4285
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 21 and the first side effect is on line 15.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * @title          Captcha Class
4
 * @desc           Generates a captcha and manages the display of the image.
5
 *
6
 * @author         Pierre-Henry Soria <[email protected]>
7
 * @copyright      (c) 2012-2018, Pierre-Henry Soria. All Rights Reserved.
8
 * @license        GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory.
9
 * @package        PH7 / Framework / Security / Spam / Captcha
10
 * @version        0.9
11
 */
12
13
namespace PH7\Framework\Security\Spam\Captcha;
14
15
defined('PH7') or exit('Restricted access');
16
17
use PH7\Framework\Navigation\Browser;
18
use PH7\Framework\Session\Session;
19
use PH7\Framework\Util\Various;
20
21
class Captcha
22
{
23
    /** @var Session */
24
    private $oSession;
25
26
    /** @var Str */
27
    private $sStr;
28
29
    /** @var string */
30
    private $sFont;
31
32
    /** @var int */
33
    private $iStringWidth;
34
35
    /** @var int */
36
    private $iHeight;
37
38
    /** @var int */
39
    private $iWidth;
40
41
    /** @var int */
42
    private $iSize = 36;
43
44
    /** @var int */
45
    private $iMargin = 25;
46
47
    /** @var array */
48
    private $aBox;
49
50
    /** @var array */
51
    private static $aMatrixBlur = [
52
        [1, 1, 1],
53
        [1, 1, 1],
54
        [1, 1, 1]
55
    ];
56
57
    /** @var array */
58
    private $aColor = [];
59
60
    /** @var resource */
61
    private $rImg;
62
63
    /** @var resource */
64
    private $rBlack;
65
66
    /** @var resource */
67
    private $rRed;
68
69
    /** @var resource */
70
    private $rWhite;
71
72
    public function __construct()
73
    {
74
        $this->oSession = new Session;
75
    }
76
77
    /**
78
     * Show the captcha image.
79
     *
80
     * @param int $iRandom
81
     *
82
     * @return void
83
     */
84
    public function show($iRandom = null)
85
    {
86
        if (!empty($iRandom)) {
87
            $this->sStr = Various::genRnd($iRandom, 5);
88
        } else {
89
            $this->sStr = Various::genRnd('pH7_Pierre-Henry_Soria_Sanz_González_captcha', 5);
90
        }
91
92
        $this->oSession->set('rand_code', $this->sStr);
93
94
        $this->sFont = $this->getFont();
95
        //$sBackground = PH7_PATH_DATA . 'background/' . mt_rand(1, 5) . '.png';
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
96
97
        $this->aBox = imagettfbbox($this->iSize, 0, $this->sFont, $this->sStr);
98
        $this->iWidth = $this->aBox[2] - $this->aBox[0];
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->aBox[2] - $this->aBox[0] can also be of type double. However, the property $iWidth is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
99
        $this->iHeight = $this->aBox[1] - $this->aBox[7];
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->aBox[1] - $this->aBox[7] can also be of type double. However, the property $iHeight is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
100
        unset($this->aBox);
101
102
        $this->iStringWidth = round($this->iWidth / strlen($this->sStr));
0 ignored issues
show
Documentation Bug introduced by
The property $iStringWidth was declared of type integer, but round($this->iWidth / strlen($this->sStr)) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
103
104
        //$this->rImg = imagecreatefrompng($sBackground);
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
105
        $this->rImg = imagecreate($this->iWidth + $this->iMargin, $this->iHeight + $this->iMargin);
106
        $this->aColor = [
107
            imagecolorallocate($this->rImg, 0x99, 0x00, 0x66),
108
            imagecolorallocate($this->rImg, 0xCC, 0x00, 0x00),
109
            imagecolorallocate($this->rImg, 0x00, 0x00, 0xCC),
110
            imagecolorallocate($this->rImg, 0x00, 0x00, 0xCC),
111
            imagecolorallocate($this->rImg, 0xBB, 0x88, 0x77)
112
        ];
113
114
        $this->rBlack = imagecolorallocate($this->rImg, 0, 0, 0);
0 ignored issues
show
Documentation Bug introduced by
It seems like imagecolorallocate($this->rImg, 0, 0, 0) of type integer is incompatible with the declared type resource of property $rBlack.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
115
        $this->rRed = imagecolorallocate($this->rImg, 200, 100, 90);
0 ignored issues
show
Documentation Bug introduced by
It seems like imagecolorallocate($this->rImg, 200, 100, 90) of type integer is incompatible with the declared type resource of property $rRed.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
116
        $this->rWhite = imagecolorallocate($this->rImg, 255, 255, 255);
0 ignored issues
show
Documentation Bug introduced by
It seems like imagecolorallocate($this->rImg, 255, 255, 255) of type integer is incompatible with the declared type resource of property $rWhite.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
117
118
        imagefilledrectangle($this->rImg, 0, 0, 399, 99, $this->rWhite);
119
120
        $this->mixing();
121
122
        imageline($this->rImg, mt_rand(2, $this->iWidth + $this->iMargin), mt_rand(1, $this->iWidth + $this->iMargin), mt_rand(1, $this->iHeight + $this->iMargin), mt_rand(2, $this->iWidth + $this->iMargin), $this->rBlack);
123
        imageline($this->rImg, mt_rand(2, $this->iHeight + $this->iMargin), mt_rand(1, $this->iHeight + $this->iMargin), mt_rand(1, $this->iWidth + $this->iMargin), mt_rand(2, $this->iHeight + $this->iMargin), $this->rRed);
124
        imageline($this->rImg, mt_rand(2, $this->iHeight + $this->iMargin), mt_rand(1, $this->iWidth + $this->iMargin), mt_rand(1, $this->iWidth + $this->iMargin), mt_rand(2, $this->iHeight + $this->iMargin), $this->aColor[array_rand($this->aColor)]);
125
        unset($this->rBlack, $this->rRed, $this->rWhite);
126
127
128
        imageconvolution($this->rImg, self::$aMatrixBlur, 9, 0);
129
        imageconvolution($this->rImg, self::$aMatrixBlur, 9, 0);
130
131
        (new Browser)->noCache();
132
        header('Content-type: image/png');
133
        imagepng($this->rImg);
134
        imagedestroy($this->rImg);
135
    }
136
137
    /**
138
     * @param string $sCode The random code.
139
     *
140
     * @return bool
141
     */
142
    public function check($sCode)
143
    {
144
        if ($sCode === null) {
145
            return false;
146
        }
147
148
        if ($sCode === $this->oSession->get('rand_code')) {
149
            return true;
150
        }
151
152
        return false;
153
    }
154
155
    /**
156
     * The HTML code for displaying the captcha.
157
     *
158
     * @return void
159
     */
160
    public function display()
161
    {
162
        // Md5 parameter in the img tag to the captcha that the browser does not cache the captcha
163
        echo // The captcha stylesheet that is now in the file form.css
164
        '<div class="center">
165
           <img class="border captcha" src="', PH7_URL_ROOT, 'asset/file/captcha/?r=', md5(time()), '" id="captcha" alt="Captcha Image" />
166
           <a class="captcha_button" href="#" onclick="document.getElementById(\'captcha\').src =\'', PH7_URL_ROOT, 'asset/file/captcha/?r=\' + Math.random(); return false"><img src="', PH7_URL_STATIC, PH7_IMG, 'icon/reload.png" onclick="this.blur()" id="refresh" alt="Refresh Image" title="Refresh Image" /></a>
167
         </div>';
168
    }
169
170
    /**
171
     * @return void
172
     */
173
    private function mixing()
174
    {
175
        for ($i = 0, $iLength = strlen($this->sStr); $i < $iLength; ++$i) {
176
            $sText = $this->sStr[$i]; // A string can be seen as an array
177
            $iAngle = mt_rand(-70, 70);
178
179
            imagettftext(
180
                $this->rImg,
181
                mt_rand($this->iSize / 2, $this->iSize),
182
                $iAngle,
183
                ($i * $this->iStringWidth) + $this->iMargin,
184
                $this->iHeight + mt_rand(1, $this->iMargin / 2),
185
                $this->aColor[array_rand($this->aColor)],
186
                $this->sFont,
187
                $sText
188
            );
189
        }
190
    }
191
192
    /**
193
     * @return string The font path of captcha.
194
     */
195
    private function getFont()
196
    {
197
        //$count = count(glob(PH7_PATH_DATA . '/font/*.ttf'));
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
198
        //return PH7_PATH_DATA . '/font/' . mt_rand(1,$count) . '.ttf';
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
199
        return PH7_PATH_DATA . '/font/4.ttf';
200
    }
201
}
202