Commit: 35218a282579109bb365f0ae5da42c983487b688
Author: Peter Kokot <[email protected]> Mon, 3 Dec 2018 03:08:45
+0100
Parents: 83d6860af9a4554a234177d1d38f37907fcb4b4f
Branches: master
Link:
http://git.php.net/?p=web/bugs.git;a=commitdiff;h=35218a282579109bb365f0ae5da42c983487b688
Log:
Refactor numerical Captcha package into class
The Text_CAPTCHA_Numeral can be integrated in the project source code
instead of using a separate unmaintained dependency.
This patch also adds a simple unit test.
Changed paths:
M .gitignore
M README.md
M composer.json
M composer.lock
A phpunit.xml.dist
A src/Utils/Captcha.php
M templates/addghpull.php
M templates/addpatch.php
A tests/Utils/CaptchaTest.php
M www/bug-pwd-finder.php
M www/bug.php
M www/gh-pull-add.php
M www/patch-add.php
M www/report.php
diff --git a/.gitignore b/.gitignore
index 56b323f..6c2d011 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,8 @@
# Configuration file
/local_config.php
+# Local specific PHPUnit configuration
+/phpunit.xml
+
# Generated by Composer
/vendor/
diff --git a/README.md b/README.md
index 5170796..564aa47 100644
--- a/README.md
+++ b/README.md
@@ -21,10 +21,19 @@ composer install
```bash
pear channel-update pear.php.net
-pear install --alldeps Text_CAPTCHA_Numeral Text_Diff HTTP_Upload-1.0.0b4
+pear install --alldeps Text_Diff HTTP_Upload-1.0.0b4
```
* Database:
Create a new database using `sql/database.sql`, create database schema
`sql/schema.sql` and insert fixtures using `sql/fixtures.sql`.
+
+## Tests
+
+Application unit tests can be executed in development environment after
+installing dependencies by running `phpunit`:
+
+```bash
+phpunit
+```
diff --git a/composer.json b/composer.json
index 3063851..ddb3fa3 100644
--- a/composer.json
+++ b/composer.json
@@ -27,5 +27,18 @@
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-session": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.4"
+ },
+ "autoload": {
+ "psr-4": {
+ "App\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "App\\Tests\\": "tests/"
+ }
}
}
diff --git a/composer.lock b/composer.lock
index 4405657..b0475da 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,9 +4,1418 @@
"Read more about it at
https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ec56b1b2037ec16e6e8fd80f4c1b8f1a",
+ "content-hash": "bb74d235e97b99c5049cfbbdbb6a3654",
"packages": [],
- "packages-dev": [],
+ "packages-dev": [
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "^6.2.3",
+ "squizlabs/php_codesniffer": "^3.0.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "[email protected]",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate
objects in PHP without invoking their constructors",
+ "homepage": "https://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2017-07-22T11:58:36+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
+ "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "replace": {
+ "myclabs/deep-copy": "self.version"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.0",
+ "doctrine/common": "^2.6",
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ },
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "time": "2018-06-11T23:09:50+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-phar": "*",
+ "phar-io/version": "^2.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "[email protected]",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "[email protected]",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information
from a PHP Archive (PHAR)",
+ "time": "2018-07-08T19:23:20+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "[email protected]",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "[email protected]",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and
constraints",
+ "time": "2018-07-08T19:19:57+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+ "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": [
+ "src"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Common reflection classes used by phpdocumentor to
reflect the code structure",
+ "homepage": "http://www.phpdoc.org",
+ "keywords": [
+ "FQSEN",
+ "phpDocumentor",
+ "phpdoc",
+ "reflection",
+ "static analysis"
+ ],
+ "time": "2017-09-11T18:02:19+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "4.3.0",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "94fd0001232e47129dd3504189fa1c7225010d08"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
+ "reference": "94fd0001232e47129dd3504189fa1c7225010d08",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "phpdocumentor/reflection-common": "^1.0.0",
+ "phpdocumentor/type-resolver": "^0.4.0",
+ "webmozart/assert": "^1.0"
+ },
+ "require-dev": {
+ "doctrine/instantiator": "~1.0.5",
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^6.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "With this component, a library can provide support
for annotations via DocBlocks or otherwise retrieve information that is
embedded in a DocBlock.",
+ "time": "2017-11-30T07:14:17+00:00"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "0.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
+ "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5 || ^7.0",
+ "phpdocumentor/reflection-common": "^1.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^0.9.4",
+ "phpunit/phpunit": "^5.2||^4.8.24"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "[email protected]"
+ }
+ ],
+ "time": "2017-07-14T14:27:02+00:00"
+ },
+ {
+ "name": "phpspec/prophecy",
+ "version": "1.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/prophecy.git",
+ "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
+ "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": "^5.3|^7.0",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
+ "sebastian/comparator": "^1.1|^2.0|^3.0",
+ "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "^2.5|^3.2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Prophecy\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "[email protected]",
+ "homepage": "http://everzet.com"
+ },
+ {
+ "name": "Marcello Duarte",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
+ "homepage": "https://github.com/phpspec/prophecy",
+ "keywords": [
+ "Double",
+ "Dummy",
+ "fake",
+ "mock",
+ "spy",
+ "stub"
+ ],
+ "time": "2018-08-05T17:53:17+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "6.1.4",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.1",
+ "phpunit/php-file-iterator": "^2.0",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-token-stream": "^3.0",
+ "sebastian/code-unit-reverse-lookup": "^1.0.1",
+ "sebastian/environment": "^3.1 || ^4.0",
+ "sebastian/version": "^2.0.1",
+ "theseer/tokenizer": "^1.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "suggest": {
+ "ext-xdebug": "^2.6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and
rendering functionality for PHP code coverage information.",
+ "homepage":
"https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "time": "2018-10-31T16:06:48+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files
based on a list of suffixes.",
+ "homepage":
"https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "time": "2018-09-13T20:33:42+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage":
"https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "time": "2015-06-21T13:50:34+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f",
+ "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2018-02-01T13:07:23+00:00"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
+ "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Wrapper around PHP's tokenizer extension.",
+ "homepage":
"https://github.com/sebastianbergmann/php-token-stream/",
+ "keywords": [
+ "tokenizer"
+ ],
+ "time": "2018-10-30T05:52:18+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "7.4.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
+ "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.1",
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "myclabs/deep-copy": "^1.7",
+ "phar-io/manifest": "^1.0.2",
+ "phar-io/version": "^2.0",
+ "php": "^7.1",
+ "phpspec/prophecy": "^1.7",
+ "phpunit/php-code-coverage": "^6.0.7",
+ "phpunit/php-file-iterator": "^2.0.1",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-timer": "^2.0",
+ "sebastian/comparator": "^3.0",
+ "sebastian/diff": "^3.0",
+ "sebastian/environment": "^3.1 || ^4.0",
+ "sebastian/exporter": "^3.1",
+ "sebastian/global-state": "^2.0",
+ "sebastian/object-enumerator": "^3.0.3",
+ "sebastian/resource-operations": "^2.0",
+ "sebastian/version": "^2.0.1"
+ },
+ "conflict": {
+ "phpunit/phpunit-mock-objects": "*"
+ },
+ "require-dev": {
+ "ext-pdo": "*"
+ },
+ "suggest": {
+ "ext-soap": "*",
+ "ext-xdebug": "*",
+ "phpunit/php-invoker": "^2.0"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2018-11-14T16:52:02+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+ "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7 || ^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Looks up which function or method a line of code
belongs to",
+ "homepage":
"https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "time": "2017-03-04T06:30:41+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1",
+ "sebastian/diff": "^3.0",
+ "sebastian/exporter": "^3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values
for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2018-07-12T15:12:46+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "366541b989927187c4ca70490a35615d3fef2dce"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce",
+ "reference": "366541b989927187c4ca70490a35615d3fef2dce",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0",
+ "symfony/process": "^2 || ^3.3 || ^4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "time": "2018-06-10T07:54:39+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f",
+ "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP
environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "time": "2018-11-25T09:31:21+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
+ "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "sebastian/recursion-context": "^3.0"
+ },
+ "require-dev": {
+ "ext-mbstring": "*",
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables
for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2017-04-03T13:19:02+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "time": "2017-04-27T15:39:26+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "sebastian/object-reflector": "^1.1.1",
+ "sebastian/recursion-context": "^3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to
enumerate all referenced objects",
+ "homepage":
"https://github.com/sebastianbergmann/object-enumerator/",
+ "time": "2017-08-03T12:35:26+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including
inherited and non-public ones",
+ "homepage":
"https://github.com/sebastianbergmann/object-reflector/",
+ "time": "2017-03-29T09:07:27+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+ "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP
variables",
+ "homepage":
"http://www.github.com/sebastianbergmann/recursion-context",
+ "time": "2017-03-03T06:23:57+00:00"
+ },
+ {
+ "name": "sebastian/resource-operations",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url":
"https://github.com/sebastianbergmann/resource-operations.git",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Provides a list of PHP built-in functions that
operate on resources",
+ "homepage":
"https://www.github.com/sebastianbergmann/resource-operations",
+ "time": "2018-10-04T04:07:39+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
+ "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "[email protected]",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version
number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "time": "2016-10-03T07:35:21+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "[email protected]",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP
source code into XML and potentially other formats",
+ "time": "2017-04-07T12:08:54+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozart/assert.git",
+ "reference": "0df1908962e7a3071564e857d86874dad1ef204a"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
+ "reference": "0df1908962e7a3071564e857d86874dad1ef204a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.3 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.6",
+ "sebastian/version": "^1.0.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "[email protected]"
+ }
+ ],
+ "description": "Assertions to validate method input/output with
nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "time": "2018-01-29T19:49:41+00:00"
+ }
+ ],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..a793290
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
+<phpunit
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.4/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php">
+ <php>
+ <ini name="error_reporting" value="-1" />
+ <ini name="date.timezone" value="UTC" />
+ </php>
+
+ <testsuites>
+ <testsuite name="The PHP bugtracking system test suite">
+ <directory>tests/</directory>
+ </testsuite>
+ </testsuites>
+</phpunit>
diff --git a/src/Utils/Captcha.php b/src/Utils/Captcha.php
new file mode 100644
index 0000000..01377aa
--- /dev/null
+++ b/src/Utils/Captcha.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace App\Utils;
+
+/**
+ * Captcha utility class for providing a simple math question with additions or
+ * subtractions to prevent spam.
+ */
+class Captcha
+{
+ /**
+ * First operand.
+ */
+ private $first;
+
+ /**
+ * Last operand.
+ */
+ private $last;
+
+ /**
+ * Highest possible operands value for randomization at initialization.
+ */
+ const MAX = 50;
+
+ /**
+ * Supported equation operations. Keys are operation symbols and values are
+ * class method names to execute.
+ */
+ const OPERATIONS = [
+ '+' => 'addition',
+ '-' => 'subtraction',
+ ];
+
+ /**
+ * Current operation.
+ */
+ private $operation;
+
+ /**
+ * Class constructor where operands random values and operation are set.
+ */
+ public function __construct()
+ {
+ $this->randomize();
+ }
+
+ /**
+ * Set random operands values and operation.
+ */
+ public function randomize()
+ {
+ $this->setFirst(rand(1, self::MAX));
+ $this->setLast(rand(1, self::MAX));
+ $this->setOperation(self::OPERATIONS[array_rand(self::OPERATIONS)]);
+ }
+
+ /**
+ * First operand number setter to override default random pick. Defined as
a
+ * separate method for convenience when unit testing.
+ */
+ public function setFirst($number)
+ {
+ $this->first = $number;
+ }
+
+ /**
+ * Last operand number setter to override default random pick. Defined as a
+ * separate method for convenience when unit testing.
+ */
+ public function setLast($number)
+ {
+ $this->last = $number;
+ }
+
+ /**
+ * Set the operation. If provided operation is invalid it falls back to
addition.
+ */
+ public function setOperation($operation)
+ {
+ $this->operation = in_array($operation, self::OPERATIONS) ? $operation
: 'addition';
+ }
+
+ /**
+ * Get current question equation string for displaying it to the user.
+ */
+ public function getQuestion()
+ {
+ $this->sortOperands();
+
+ $symbol = array_search($this->operation, self::OPERATIONS);
+ $symbol = $symbol === false ? '+' : $symbol;
+
+ return $this->first.' '.$symbol.' '.$this->last.' = ?';
+ }
+
+ /**
+ * The correct current answer of the given equation question.
+ */
+ public function getAnswer()
+ {
+ $this->sortOperands();
+
+ return \call_user_func([Captcha::class, $this->operation],
$this->first, $this->last);
+ }
+
+ /**
+ * When the current operation is subtraction, sort operands to have a
bigger
+ * operand first. With this, negative results are omitted for simplicity
and
+ * possible better user experience.
+ */
+ private function sortOperands()
+ {
+ $first = $this->first;
+ $last = $this->last;
+
+ if ($this->operation === 'subtraction') {
+ $this->first = $first > $last ? $first : $last;
+ $this->last = $first > $last ? $last : $first;
+ }
+ }
+
+ /**
+ * Addition of two operands.
+ */
+ private function addition($first, $last)
+ {
+ return $first + $last;
+ }
+
+ /**
+ * Subtraction of two operands.
+ */
+ private function subtraction($first, $last)
+ {
+ return $first - $last;
+ }
+}
diff --git a/templates/addghpull.php b/templates/addghpull.php
index 9884a4a..fb06dd1 100644
--- a/templates/addghpull.php
+++ b/templates/addghpull.php
@@ -23,8 +23,7 @@ if (!empty($errors)) {
<table>
<?php
if (!$logged_in) {
- $captcha = $numeralCaptcha->getOperation();
- $_SESSION['answer'] = $numeralCaptcha->getAnswer();
+ $_SESSION['answer'] = $captcha->getAnswer();
?>
<tr>
<th class="form-label_left">
@@ -35,7 +34,7 @@ if (!$logged_in) {
</td>
</tr>
<tr>
- <th>Solve the problem:<br><?php echo $captcha; ?> = ?</th>
+ <th>Solve the problem:<br><?php echo $captcha->getQuestion(); ?></th>
<td class="form-input"><input type="text" name="captcha"></td>
</tr>
<?php } ?>
diff --git a/templates/addpatch.php b/templates/addpatch.php
index 6e0a7f6..5285789 100644
--- a/templates/addpatch.php
+++ b/templates/addpatch.php
@@ -21,8 +21,7 @@ if (!empty($errors)) {
<table>
<?php
if (!$logged_in) {
- $captcha = $numeralCaptcha->getOperation();
- $_SESSION['answer'] = $numeralCaptcha->getAnswer();
+ $_SESSION['answer'] = $captcha->getAnswer();
?>
<tr>
<th class="form-label_left">
@@ -33,7 +32,7 @@ if (!$logged_in) {
</td>
</tr>
<tr>
- <th>Solve the problem:<br><?php echo $captcha; ?> = ?</th>
+ <th>Solve the problem:<br><?php echo $captcha->getQuestion(); ?></th>
<td class="form-input"><input type="text" name="captcha"></td>
</tr>
<?php } ?>
diff --git a/tests/Utils/CaptchaTest.php b/tests/Utils/CaptchaTest.php
new file mode 100644
index 0000000..681da7a
--- /dev/null
+++ b/tests/Utils/CaptchaTest.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Tests\Utils;
+
+use PHPUnit\Framework\TestCase;
+use App\Utils\Captcha;
+
+class CaptchaTest extends TestCase
+{
+ private $captcha;
+
+ public function setUp()
+ {
+ $this->captcha = new Captcha();
+ }
+
+ /**
+ * @dataProvider mathProvider
+ */
+ public function testGetQuestion($first, $last, $operation, $question,
$expected)
+ {
+ $this->captcha->setFirst($first);
+ $this->captcha->setLast($last);
+ $this->captcha->setOperation($operation);
+
+ $this->assertEquals($question, $this->captcha->getQuestion());
+ $this->assertEquals($expected, $this->captcha->getAnswer());
+ }
+
+ public function mathProvider()
+ {
+ return [
+ [1, 2, 'addition', '1 + 2 = ?', 3],
+ [10, 50, 'subtraction', '50 - 10 = ?', 40],
+ [90, 50, 'subtraction', '90 - 50 = ?', 40],
+ [14, 14, 'subtraction', '14 - 14 = ?', 0],
+ [10, 5, 'multiplication', '10 + 5 = ?', 15],
+ [12, 2, 'foo', '12 + 2 = ?', 14],
+ ];
+ }
+}
diff --git a/www/bug-pwd-finder.php b/www/bug-pwd-finder.php
index 08a0fea..023597a 100644
--- a/www/bug-pwd-finder.php
+++ b/www/bug-pwd-finder.php
@@ -2,11 +2,14 @@
/* Procedure for emailing a password reminder to a user */
+use App\Utils\Captcha;
+
+require_once __DIR__.'/../src/Utils/Captcha.php';
+
// Start session (for captcha!)
session_start();
-require_once 'Text/CAPTCHA/Numeral.php';
-$numeralCaptcha = new Text_CAPTCHA_Numeral();
+$captcha = new Captcha();
// Obtain common includes
require_once '../include/prepend.php';
@@ -72,8 +75,7 @@ if ($success) {
display_bug_success($success);
}
-$captcha = $numeralCaptcha->getOperation();
-$_SESSION['answer'] = $numeralCaptcha->getAnswer();
+$_SESSION['answer'] = $captcha->getAnswer();
?>
@@ -90,7 +92,7 @@ in the bug report.
<form method="post" action="bug-pwd-finder.php">
<p><b>Bug Report ID:</b> #<input type="text" size="20" name="id" value="<?php
echo $bug_id; ?>">
-<p><b>Solve the problem:<br><?php echo $captcha; ?> = ? <input type="text"
name="captcha"></p>
+<p><b>Solve the problem:<br><?php echo $captcha->getQuestion(); ?> <input
type="text" name="captcha"></p>
<input type="submit" value="Send"></p>
</form>
diff --git a/www/bug.php b/www/bug.php
index 26183b1..46b5854 100644
--- a/www/bug.php
+++ b/www/bug.php
@@ -1,6 +1,8 @@
<?php
/* User interface for viewing and editing bug details */
+use App\Utils\Captcha;
+
// Obtain common includes
require_once '../include/prepend.php';
@@ -113,8 +115,8 @@ if ($edit == 1 && $is_trusted_developer &&
isset($_GET['delete_comment'])) {
// captcha is not necessary if the user is logged in
if (!$logged_in) {
- require_once 'Text/CAPTCHA/Numeral.php';
- $numeralCaptcha = new Text_CAPTCHA_Numeral();
+ require_once __DIR__.'/../src/Utils/Captcha.php';
+ $captcha = new Captcha();
}
$trytoforce = isset($_POST['trytoforce']) ? (int) $_POST['trytoforce'] : 0;
@@ -995,8 +997,7 @@ if ($edit == 1 || $edit == 2) { ?>
echo $preview;
if (!$logged_in) {
- $captcha = $numeralCaptcha->getOperation();
- $_SESSION['answer'] = $numeralCaptcha->getAnswer();
+ $_SESSION['answer'] = $captcha->getAnswer();
?>
<table>
<tr>
@@ -1006,7 +1007,7 @@ if (!$logged_in) {
</td>
</tr>
<tr>
- <th>Solve the problem:<br><?php echo
htmlspecialchars($captcha); ?> = ?</th>
+ <th>Solve the problem:<br><?php echo
htmlspecialchars($captcha->getQuestion()); ?></th>
<td class="form-input"><input type="text"
name="captcha"></td>
</tr>
<tr>
diff --git a/www/gh-pull-add.php b/www/gh-pull-add.php
index 616dda5..7dc2965 100644
--- a/www/gh-pull-add.php
+++ b/www/gh-pull-add.php
@@ -1,5 +1,7 @@
<?php
+use App\Utils\Captcha;
+
// Obtain common includes
require_once '../include/prepend.php';
require_once 'PEAR.php';
@@ -37,8 +39,8 @@ $is_trusted_developer = ($user_flags & BUGS_TRUSTED_DEV);
// captcha is not necessary if the user is logged in
if (!$logged_in) {
- require_once 'Text/CAPTCHA/Numeral.php';
- $numeralCaptcha = new Text_CAPTCHA_Numeral();
+ require_once __DIR__.'/../src/Utils/Captcha.php';
+ $captcha = new Captcha();
}
$show_bug_info = bugs_has_access($bug_id, $buginfo, $pw, $user_flags);
diff --git a/www/patch-add.php b/www/patch-add.php
index 368ce70..6fd7035 100644
--- a/www/patch-add.php
+++ b/www/patch-add.php
@@ -1,5 +1,7 @@
<?php
+use App\Utils\Captcha;
+
// Obtain common includes
require_once '../include/prepend.php';
@@ -36,8 +38,8 @@ $is_trusted_developer = ($user_flags & BUGS_TRUSTED_DEV);
// captcha is not necessary if the user is logged in
if (!$logged_in) {
- require_once 'Text/CAPTCHA/Numeral.php';
- $numeralCaptcha = new Text_CAPTCHA_Numeral();
+ require_once __DIR__.'/../src/Utils/Captcha.php';
+ $captcha = new Captcha();
}
$show_bug_info = bugs_has_access($bug_id, $buginfo, $pw, $user_flags);
diff --git a/www/report.php b/www/report.php
index a840b5f..542bf87 100644
--- a/www/report.php
+++ b/www/report.php
@@ -1,5 +1,7 @@
<?php
+use App\Utils\Captcha;
+
// Obtain common includes
require_once '../include/prepend.php';
@@ -23,8 +25,8 @@ require "{$ROOT_DIR}/include/php_versions.php";
// captcha is not necessary if the user is logged in
if (!$logged_in) {
- require_once 'Text/CAPTCHA/Numeral.php';
- $numeralCaptcha = new Text_CAPTCHA_Numeral();
+ require_once __DIR__.'/../src/Utils/Captcha.php';
+ $captcha = new Captcha();
}
$packageAffectedScript = <<<SCRIPT
@@ -532,8 +534,8 @@ display_bug_error($errors);
</tr>
<?php if (!$logged_in) {
- $captcha = $numeralCaptcha->getOperation();
- $_SESSION['answer'] = $numeralCaptcha->getAnswer();
+ $_SESSION['answer'] = $captcha->getAnswer();
+
if (!empty($_POST['captcha']) && empty($ok_to_submit_report)) {
$captcha_label = '<strong>Solve this <em>new</em>
problem:</strong>';
} else {
@@ -541,7 +543,7 @@ display_bug_error($errors);
}
?>
<tr>
- <th><?php echo $captcha_label; ?><br><?php echo
htmlspecialchars($captcha); ?> = ?</th>
+ <th><?php echo $captcha_label; ?><br><?php echo
htmlspecialchars($captcha->getQuestion()); ?></th>
<td class="form-input"><input type="text"
name="captcha" autocomplete="off"></td>
</tr>
<?php } ?>
--
PHP Webmaster List Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php