From 92d84f31935d6016c10ecefa2f6ad8334d66c965 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:05:26 +0200 Subject: [PATCH 1/8] Install PHPUnit for UnitTesting --- app/tests/Framadate/FramaTestCase.php | 23 + .../Services/MailServiceUnitTest.php | 15 + app/tests/bootstrap.php | 3 + composer.json | 4 + composer.lock | 972 +++++++++++++++++- phpunit.bat | 1 + phpunit.sh | 1 + 7 files changed, 1012 insertions(+), 7 deletions(-) create mode 100644 app/tests/Framadate/FramaTestCase.php create mode 100644 app/tests/Framadate/Services/MailServiceUnitTest.php create mode 100644 app/tests/bootstrap.php create mode 100644 phpunit.bat create mode 100644 phpunit.sh diff --git a/app/tests/Framadate/FramaTestCase.php b/app/tests/Framadate/FramaTestCase.php new file mode 100644 index 0000000..b2f6e14 --- /dev/null +++ b/app/tests/Framadate/FramaTestCase.php @@ -0,0 +1,23 @@ +getTestResourcePath($resourcepath)); + } + + protected function invoke(&$object, $methodName) { + $reflectionClass = new \ReflectionClass($object); + $reflectionMethod = $reflectionClass->getMethod($methodName); + $reflectionMethod->setAccessible(true); + + $params = array_slice(func_get_args(), 2); // get all the parameters after $methodName + return $reflectionMethod->invokeArgs($object, $params); + } + +} diff --git a/app/tests/Framadate/Services/MailServiceUnitTest.php b/app/tests/Framadate/Services/MailServiceUnitTest.php new file mode 100644 index 0000000..70e99c6 --- /dev/null +++ b/app/tests/Framadate/Services/MailServiceUnitTest.php @@ -0,0 +1,15 @@ +assertEquals('a', 'a'); + } + +} diff --git a/app/tests/bootstrap.php b/app/tests/bootstrap.php new file mode 100644 index 0000000..9d4b65e --- /dev/null +++ b/app/tests/bootstrap.php @@ -0,0 +1,3 @@ +addPsr4('Framadate\\', __DIR__.'/Framadate'); diff --git a/composer.json b/composer.json index 620b1c0..c8f208e 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,10 @@ "o80/i18n": "dev-develop" }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, + "autoload": { "psr-4": { "Framadate\\": "app/classes/Framadate/" diff --git a/composer.lock b/composer.lock index aa3f492..b9eb05f 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "35bdfd24b481ad94a99b6fd67499aba9", + "hash": "0850a63e18c972e762c563d3d4971ea0", "packages": [ { "name": "o80/i18n", @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/olivierperez/o80-i18n.git", - "reference": "27ad49063797169878605e310d42d2de618ff695" + "reference": "9b57197b395add3afc62fd674b03926230819b97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/olivierperez/o80-i18n/zipball/27ad49063797169878605e310d42d2de618ff695", - "reference": "27ad49063797169878605e310d42d2de618ff695", + "url": "https://api.github.com/repos/olivierperez/o80-i18n/zipball/9b57197b395add3afc62fd674b03926230819b97", + "reference": "9b57197b395add3afc62fd674b03926230819b97", "shasum": "" }, "require": { @@ -50,7 +50,7 @@ "internationalization", "php" ], - "time": "2015-04-11 20:55:50" + "time": "2015-05-09 22:08:09" }, { "name": "smarty/smarty", @@ -108,7 +108,965 @@ "time": "2014-10-31 04:22:20" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "2.0.*@ALPHA" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Instantiator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "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": "2014-10-13 12:58:55" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-04-27 22:15:08" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.0.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "c4e8e7725e351184a76544634855b8a9c405a6e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c4e8e7725e351184a76544634855b8a9c405a6e3", + "reference": "c4e8e7725e351184a76544634855b8a9c405a6e3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "~1.0", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "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": "sb@sebastian-bergmann.de", + "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": "2015-05-25 05:11:59" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "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": "2015-04-02 05:19:05" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2014-01-30 17:20:04" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-08-02 07:42:54" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "eab81d02569310739373308137284e0158424330" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", + "reference": "eab81d02569310739373308137284e0158424330", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-04-08 04:46:07" + }, + { + "name": "phpunit/phpunit", + "version": "4.6.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "816d12536a7a032adc3b68737f82cfbbf98b79c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/816d12536a7a032adc3b68737f82cfbbf98b79c1", + "reference": "816d12536a7a032adc3b68737f82cfbbf98b79c1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "~1.3,>=1.3.1", + "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.6.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2015-05-29 06:00:03" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "253c005852591fd547fc18cd5b7b43a1ec82d8f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/253c005852591fd547fc18cd5b7b43a1ec82d8f7", + "reference": "253c005852591fd547fc18cd5b7b43a1ec82d8f7", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "~1.0,>=1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-05-29 05:19:18" + }, + { + "name": "sebastian/comparator", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-01-29 16:28:08" + }, + { + "name": "sebastian/diff", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-01-01 10:01:08" + }, + { + "name": "sebastian/exporter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "84839970d05254c73cde183a721c7af13aede943" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-01-27 07:23:06" + }, + { + "name": "sebastian/global-state", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2014-10-06 09:23:50" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "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": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-01-24 09:48:32" + }, + { + "name": "sebastian/version", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-02-24 06:35:25" + }, + { + "name": "symfony/yaml", + "version": "v2.6.8", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" + } + ], "aliases": [], "minimum-stability": "stable", "stability-flags": { diff --git a/phpunit.bat b/phpunit.bat new file mode 100644 index 0000000..7691614 --- /dev/null +++ b/phpunit.bat @@ -0,0 +1 @@ +vendor\bin\phpunit.bat --bootstrap app\tests\bootstrap.php app/tests \ No newline at end of file diff --git a/phpunit.sh b/phpunit.sh new file mode 100644 index 0000000..ce4446f --- /dev/null +++ b/phpunit.sh @@ -0,0 +1 @@ +vendor\bin\phpunit --bootstrap app\tests\bootstrap.php app/tests \ No newline at end of file From be155aa2a1e11e847a77892683a4c6ca5126b020 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:06:03 +0200 Subject: [PATCH 2/8] MailService now manage the anti-flood system --- .../Framadate/Services/MailService.php | 29 +++++++++++++++++-- .../Services/MailServiceUnitTest.php | 28 ++++++++++++++++-- studs.php | 7 ++--- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/app/classes/Framadate/Services/MailService.php b/app/classes/Framadate/Services/MailService.php index 2b7dd66..51d343d 100644 --- a/app/classes/Framadate/Services/MailService.php +++ b/app/classes/Framadate/Services/MailService.php @@ -5,6 +5,10 @@ class MailService { private $smtp_allowed; + const DELAY_BEFORE_RESEND = 300; + + const MAILSERVICE_KEY = 'mailservice'; + function __construct($smtp_allowed) { $this->smtp_allowed = $smtp_allowed; } @@ -13,10 +17,12 @@ class MailService { return filter_var($email, FILTER_VALIDATE_EMAIL); } - function send($to, $subject, $body, $param = '') { - if ($this->smtp_allowed == true) { + function send($to, $subject, $body, $param = '', $msgKey = null) { + if ($this->smtp_allowed == true && $this->canSendMsg($msgKey)) { mb_internal_encoding('UTF-8'); + // Build headers + $subject = mb_encode_mimeheader(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'), 'UTF-8', 'B', "\n", 9); $encoded_app = mb_encode_mimeheader(NOMAPPLICATION, 'UTF-8', 'B', "\n", 6); @@ -39,11 +45,30 @@ class MailService { $headers .= "Auto-Submitted:auto-generated\n"; $headers .= 'Return-Path: <>'; + // Build body + $body = $body . '

' . __('Mail', 'Thanks for your trust.') . '
' . NOMAPPLICATION . '
' . __('Mail', 'FOOTER'); + // Send mail + mail($to, $subject, $body, $headers, $param); + + // Set date before resend in sessions + + $_SESSION[self::MAILSERVICE_KEY][$msgKey] = time() + self::DELAY_BEFORE_RESEND; } } + function canSendMsg($msgKey) { + if ($msgKey == null) { + return true; + } + + if (!isset($_SESSION[self::MAILSERVICE_KEY])) { + $_SESSION[self::MAILSERVICE_KEY] = []; + } + return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || $_SESSION[self::MAILSERVICE_KEY][$msgKey] < time(); + } + } \ No newline at end of file diff --git a/app/tests/Framadate/Services/MailServiceUnitTest.php b/app/tests/Framadate/Services/MailServiceUnitTest.php index 70e99c6..fe22ebe 100644 --- a/app/tests/Framadate/Services/MailServiceUnitTest.php +++ b/app/tests/Framadate/Services/MailServiceUnitTest.php @@ -4,12 +4,36 @@ namespace Framadate\Services; use Framadate\FramaTestCase; class MailServiceUnitTest extends FramaTestCase { + const MSG_KEY = '666'; /** * @test */ - function cconstruct() { - $this->assertEquals('a', 'a'); + function should_send_a_2nd_mail_after_a_good_interval() { + // Given + $mailService = new MailService(true); + $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() - 500]; + + // When + $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); + + // Then + $this->assertEquals(true, $canSendMsg); + } + + /** + * @test + */ + function should_not_send_2_mails_in_a_short_interval() { + // Given + $mailService = new MailService(true); + $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() + 500]; + + // When + $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); + + // Then + $this->assertEquals(false, $canSendMsg); } } diff --git a/studs.php b/studs.php index 0bcf460..bab6141 100644 --- a/studs.php +++ b/studs.php @@ -64,7 +64,7 @@ function sendUpdateNotification($poll, $mailService, $name, $type) { $_SESSION['mail_sent'] = []; } - if ($poll->receiveNewVotes && (!isset($_SESSION['mail_sent'][$poll->id]) || $_SESSION['mail_sent'][$poll->id] !== true)) { + if ($poll->receiveNewVotes) { $subject = '[' . NOMAPPLICATION . '] ' . __('Mail', 'Poll\'s participation') . ' : ' . $poll->title; @@ -82,9 +82,8 @@ function sendUpdateNotification($poll, $mailService, $name, $type) { } $message .= Utils::getUrlSondage($poll->admin_id, true) . "\n\n"; - $mailService->send($poll->admin_mail, $subject, $message); - - $_SESSION['mail_sent'][$poll->id] = true; + $messageTypeKey = $type . '-' . $poll->id; + $mailService->send($messageTypeKey, $poll->admin_mail, $subject, $message); } } From 8313b9345d9936c4848f597c9d2a7ab0b42ec3d0 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:12:47 +0200 Subject: [PATCH 3/8] Fix after update o80-i18n --- app/inc/i18n.php | 2 +- create_classic_poll.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/inc/i18n.php b/app/inc/i18n.php index 257ac18..2257286 100644 --- a/app/inc/i18n.php +++ b/app/inc/i18n.php @@ -28,7 +28,7 @@ if (isset($_POST['lang']) && is_string($_POST['lang']) && in_array($_POST['lang' } /* */ -$i18n->get('Something, just to load the dictionary'); +$i18n->get('', 'Something, just to load the dictionary'); $locale = $i18n->getLoadedLang(); /* Date Format */ diff --git a/create_classic_poll.php b/create_classic_poll.php index e2b87c4..1b989e8 100644 --- a/create_classic_poll.php +++ b/create_classic_poll.php @@ -198,7 +198,7 @@ if (empty($_SESSION['form']->title) || empty($_SESSION['form']->admin_name) || (
- +
' . __('Date', 'dd/mm/yyyy') . ' From 278e478d1ac5e375599925b1bb08264f059d95c4 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:41:50 +0200 Subject: [PATCH 4/8] Write log when send a mail --- .../Framadate/Services/MailService.php | 23 ++++++++++++++----- .../Services/MailServiceUnitTest.php | 4 ++-- studs.php | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/app/classes/Framadate/Services/MailService.php b/app/classes/Framadate/Services/MailService.php index 51d343d..1f87d6e 100644 --- a/app/classes/Framadate/Services/MailService.php +++ b/app/classes/Framadate/Services/MailService.php @@ -9,7 +9,10 @@ class MailService { const MAILSERVICE_KEY = 'mailservice'; + private $logService; + function __construct($smtp_allowed) { + $this->logService = new LogService(); $this->smtp_allowed = $smtp_allowed; } @@ -51,11 +54,7 @@ class MailService { // Send mail - mail($to, $subject, $body, $headers, $param); - - // Set date before resend in sessions - - $_SESSION[self::MAILSERVICE_KEY][$msgKey] = time() + self::DELAY_BEFORE_RESEND; + $this->sendMail($to, $subject, $body, $param, $msgKey, $headers); } } @@ -67,7 +66,19 @@ class MailService { if (!isset($_SESSION[self::MAILSERVICE_KEY])) { $_SESSION[self::MAILSERVICE_KEY] = []; } - return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || $_SESSION[self::MAILSERVICE_KEY][$msgKey] < time(); + return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || time() - $_SESSION[self::MAILSERVICE_KEY][$msgKey] > self::DELAY_BEFORE_RESEND; + } + + private function sendMail($to, $subject, $body, $param, $msgKey, $headers) { + mail($to, $subject, $body, $headers, $param); + + // Log + + $this->logService->log('MAIL', 'Mail sent to: ' . $to . ', key: ' . $msgKey); + + // Store the mail sending date + + $_SESSION[self::MAILSERVICE_KEY][$msgKey] = time(); } } diff --git a/app/tests/Framadate/Services/MailServiceUnitTest.php b/app/tests/Framadate/Services/MailServiceUnitTest.php index fe22ebe..b4045f2 100644 --- a/app/tests/Framadate/Services/MailServiceUnitTest.php +++ b/app/tests/Framadate/Services/MailServiceUnitTest.php @@ -12,7 +12,7 @@ class MailServiceUnitTest extends FramaTestCase { function should_send_a_2nd_mail_after_a_good_interval() { // Given $mailService = new MailService(true); - $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() - 500]; + $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() - 1000]; // When $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); @@ -27,7 +27,7 @@ class MailServiceUnitTest extends FramaTestCase { function should_not_send_2_mails_in_a_short_interval() { // Given $mailService = new MailService(true); - $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() + 500]; + $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time()]; // When $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); diff --git a/studs.php b/studs.php index bab6141..26d7b23 100644 --- a/studs.php +++ b/studs.php @@ -83,7 +83,7 @@ function sendUpdateNotification($poll, $mailService, $name, $type) { $message .= Utils::getUrlSondage($poll->admin_id, true) . "\n\n"; $messageTypeKey = $type . '-' . $poll->id; - $mailService->send($messageTypeKey, $poll->admin_mail, $subject, $message); + $mailService->send($poll->admin_mail, $subject, $message, '', $messageTypeKey); } } From d7d9b11fbd5fdc86515116297cc2fe79a0970b9e Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:46:13 +0200 Subject: [PATCH 5/8] Add anti-flood 'find my polls' --- find_polls.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/find_polls.php b/find_polls.php index e3ca6dd..5e25a07 100644 --- a/find_polls.php +++ b/find_polls.php @@ -43,7 +43,7 @@ if (!empty($_POST['mail'])) { $smarty->assign('polls', $polls); $body = $smarty->fetch('mail/find_polls.tpl'); - $mailService->send($mail, __('Homepage', 'Where are my polls'), $body); + $mailService->send($mail, __('Homepage', 'Where are my polls'), $body, '', 'SEND_POLLS'); $message = new Message('success', __('FindPolls', 'Polls sent')); } else { $message = new Message('warning', __('Error', 'No polls found')); From ad2b146c3c813c481d14b6390583e957d447574e Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 17:49:01 +0200 Subject: [PATCH 6/8] Remove parameter from MailService::send --- app/classes/Framadate/Services/MailService.php | 8 ++++---- find_polls.php | 2 +- studs.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/classes/Framadate/Services/MailService.php b/app/classes/Framadate/Services/MailService.php index 1f87d6e..18807b2 100644 --- a/app/classes/Framadate/Services/MailService.php +++ b/app/classes/Framadate/Services/MailService.php @@ -20,7 +20,7 @@ class MailService { return filter_var($email, FILTER_VALIDATE_EMAIL); } - function send($to, $subject, $body, $param = '', $msgKey = null) { + function send($to, $subject, $body, $msgKey = null) { if ($this->smtp_allowed == true && $this->canSendMsg($msgKey)) { mb_internal_encoding('UTF-8'); @@ -54,7 +54,7 @@ class MailService { // Send mail - $this->sendMail($to, $subject, $body, $param, $msgKey, $headers); + $this->sendMail($to, $subject, $body, $msgKey, $headers); } } @@ -69,8 +69,8 @@ class MailService { return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || time() - $_SESSION[self::MAILSERVICE_KEY][$msgKey] > self::DELAY_BEFORE_RESEND; } - private function sendMail($to, $subject, $body, $param, $msgKey, $headers) { - mail($to, $subject, $body, $headers, $param); + private function sendMail($to, $subject, $body, $msgKey, $headers) { + mail($to, $subject, $body, $headers, ''); // Log diff --git a/find_polls.php b/find_polls.php index 5e25a07..c4ced25 100644 --- a/find_polls.php +++ b/find_polls.php @@ -43,7 +43,7 @@ if (!empty($_POST['mail'])) { $smarty->assign('polls', $polls); $body = $smarty->fetch('mail/find_polls.tpl'); - $mailService->send($mail, __('Homepage', 'Where are my polls'), $body, '', 'SEND_POLLS'); + $mailService->send($mail, __('Homepage', 'Where are my polls'), $body, 'SEND_POLLS'); $message = new Message('success', __('FindPolls', 'Polls sent')); } else { $message = new Message('warning', __('Error', 'No polls found')); diff --git a/studs.php b/studs.php index 26d7b23..0ebdd0f 100644 --- a/studs.php +++ b/studs.php @@ -83,7 +83,7 @@ function sendUpdateNotification($poll, $mailService, $name, $type) { $message .= Utils::getUrlSondage($poll->admin_id, true) . "\n\n"; $messageTypeKey = $type . '-' . $poll->id; - $mailService->send($poll->admin_mail, $subject, $message, '', $messageTypeKey); + $mailService->send($poll->admin_mail, $subject, $message, $messageTypeKey); } } From cb0864f8fd88bb4562b9c2135387ba0c4825fd06 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 18:11:12 +0200 Subject: [PATCH 7/8] Fix a lot of things --- admin/purge.php | 1 - app/classes/Framadate/Form.php | 2 -- create_classic_poll.php | 10 +++++----- create_date_poll.php | 2 +- exportcsv.php | 3 --- index.php | 2 -- studs.php | 2 +- 7 files changed, 7 insertions(+), 15 deletions(-) diff --git a/admin/purge.php b/admin/purge.php index 5a8e268..fb817f1 100644 --- a/admin/purge.php +++ b/admin/purge.php @@ -21,7 +21,6 @@ use Framadate\Services\InputService; use Framadate\Services\LogService; use Framadate\Services\PurgeService; use Framadate\Services\SecurityService; -use Framadate\Utils; include_once __DIR__ . '/../app/inc/init.php'; include_once __DIR__ . '/../bandeaux.php'; diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php index ce802ba..f73cd9e 100644 --- a/app/classes/Framadate/Form.php +++ b/app/classes/Framadate/Form.php @@ -18,8 +18,6 @@ */ namespace Framadate; -use Framadate\Editable; - class Form { diff --git a/create_classic_poll.php b/create_classic_poll.php index 1b989e8..21c652b 100644 --- a/create_classic_poll.php +++ b/create_classic_poll.php @@ -41,13 +41,13 @@ if (file_exists('bandeaux_local.php')) { // Step 1/4 : error if $_SESSION from info_sondage are not valid if (empty($_SESSION['form']->title) || empty($_SESSION['form']->admin_name) || (($config['use_smtp']) ? empty($_SESSION['form']->admin_mail) : false)) { - Utils::print_header(__("Error!")); - bandeau_titre(__("Error!")); + Utils::print_header(__('Error', 'Error!')); + bandeau_titre(__('Error', 'Error!')); echo '
-

' . __('You haven\'t filled the first section of the poll creation.') . ' !

-

' . __('Back to the homepage of') . ' ' . NOMAPPLICATION . '

+

' . __('Error', 'You haven\'t filled the first section of the poll creation.') . ' !

+

' . __('Generic', 'Back to the homepage of') . ' ' . NOMAPPLICATION . '

' . "\n"; bandeau_pied(); @@ -149,7 +149,7 @@ if (empty($_SESSION['form']->title) || empty($_SESSION['form']->admin_name) || ( // Summary $summary = '
    '; - foreach ($_SESSION['form']->getChoices() as $choice) { + foreach ($_SESSION['form']->getChoices() as $i=>$choice) { preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/', $choice->getName(), $md_a_img); // Markdown [![alt](src)](href) preg_match_all('/!\[(.*?)\]\((.*?)\)/', $choice->getName(), $md_img); // Markdown ![alt](src) diff --git a/create_date_poll.php b/create_date_poll.php index aec2a26..f170b5b 100644 --- a/create_date_poll.php +++ b/create_date_poll.php @@ -194,7 +194,7 @@ if (!isset($_SESSION['form']->title) || !isset($_SESSION['form']->admin_name) ||
    - +
    ('. __('Date', 'dd/mm/yyyy') .') diff --git a/exportcsv.php b/exportcsv.php index f5b5d0b..6197cfb 100644 --- a/exportcsv.php +++ b/exportcsv.php @@ -18,9 +18,6 @@ */ use Framadate\Services\LogService; use Framadate\Services\PollService; -use Framadate\Services\InputService; -use Framadate\Services\MailService; -use Framadate\Message; use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; diff --git a/index.php b/index.php index e756076..364c90c 100644 --- a/index.php +++ b/index.php @@ -17,9 +17,7 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -use Framadate\Services\LogService; use Framadate\Services\PollService; -use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; diff --git a/studs.php b/studs.php index 0ebdd0f..9448297 100644 --- a/studs.php +++ b/studs.php @@ -151,7 +151,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote $message = new Message('danger', __('Error', 'The name is invalid.')); } if (count($choices) != count($_POST['choices'])) { - $message = new Message('danger', __('There is a problem with your choices')); + $message = new Message('danger', __('Error', 'There is a problem with your choices')); } if ($message == null) { From b717bee76515b2db6b739a792de19ef450a91bea Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Fri, 29 May 2015 18:25:48 +0200 Subject: [PATCH 8/8] Remove '?' image on 'Where are my polls' link --- images/question.png | Bin 9757 -> 0 bytes tpl/index.tpl | 2 -- 2 files changed, 2 deletions(-) delete mode 100644 images/question.png diff --git a/images/question.png b/images/question.png deleted file mode 100644 index 73d1d94803366747773dd6e0a1f9e5fc6201cbcb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9757 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 VreR7G{2>=aU&mOx__{;b{{hO-bbtT= diff --git a/tpl/index.tpl b/tpl/index.tpl index 815938c..1d39687 100644 --- a/tpl/index.tpl +++ b/tpl/index.tpl @@ -29,8 +29,6 @@