diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index d2df5560..47caa7eb 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -9,6 +9,8 @@ docs/ @JoshuaEstes
# Each component/contract needs a Team
/src/SonsOfPHP/**/Cache @JoshuaEstes
/src/SonsOfPHP/**/Clock @JoshuaEstes
+/src/SonsOfPHP/**/Container @JoshuaEstes
+/src/SonsOfPHP/**/Cookie @JoshuaEstes
/src/SonsOfPHP/**/Common @JoshuaEstes
/src/SonsOfPHP/**/Cqrs @JoshuaEstes
/src/SonsOfPHP/**/EventDispatcher @JoshuaEstes
@@ -16,10 +18,12 @@ docs/ @JoshuaEstes
/src/SonsOfPHP/**/FeatureToggle @JoshuaEstes
/src/SonsOfPHP/**/Filesystem @JoshuaEstes
/src/SonsOfPHP/**/HttpFactory @JoshuaEstes
+/src/SonsOfPHP/**/HttpHandler @JoshuaEstes
/src/SonsOfPHP/**/HttpMessage @JoshuaEstes
/src/SonsOfPHP/**/Json @JoshuaEstes
/src/SonsOfPHP/**/Link @JoshuaEstes
/src/SonsOfPHP/**/Logger @JoshuaEstes
+/src/SonsOfPHP/**/Mailer @JoshuaEstes
/src/SonsOfPHP/**/Money @JoshuaEstes
/src/SonsOfPHP/**/Pager @JoshuaEstes
/src/SonsOfPHP/**/Version @JoshuaEstes
diff --git a/.github/labeler.yml b/.github/labeler.yml
index fb9d35e6..e0ece348 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -10,6 +10,14 @@ Clock:
- docs/components/clock/*
- src/SonsOfPHP/**/Clock/*
+Container:
+ - docs/components/container/*
+ - src/SonsOfPHP/**/Container/*
+
+Cookie:
+ - docs/components/cookie/*
+ - src/SonsOfPHP/**/Cookie/*
+
Common:
- docs/components/common/*
- src/SonsOfPHP/**/Common/*
@@ -38,6 +46,10 @@ HttpFactory:
- docs/components/http-factory/*
- src/SonsOfPHP/**/HttpFactory/*
+HttpHandler:
+ - docs/components/http-handler/*
+ - src/SonsOfPHP/**/HttpHandler/*
+
HttpMessage:
- docs/components/http-message/*
- src/SonsOfPHP/**/HttpMessage/*
@@ -54,6 +66,10 @@ Logger:
- docs/components/logger/*
- src/SonsOfPHP/**/Logger/*
+Mailer:
+ - docs/components/mailer/*
+ - src/SonsOfPHP/**/Mailer/*
+
Money:
- docs/components/money/*
- src/SonsOfPHP/**/Money/*
diff --git a/.gitignore b/.gitignore
index b5a07c55..5ced1162 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/docs/coverage/
+/docs/infection/
/site/
vendor/
/.php-cs-fixer.cache
@@ -10,3 +11,4 @@ phpunit.xml
composer.phar
packages.json
results.sarif
+infection.log
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 671c4f57..691a6733 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,11 @@ To get the diff between two versions, go to https://github.com/SonsOfPHP/sonsofp
* [PR #133](https://github.com/SonsOfPHP/sonsofphp/pull/133) [Pager] New Contract
* [PR #134](https://github.com/SonsOfPHP/sonsofphp/pull/134) [Pager] New Component
* [PR #170](https://github.com/SonsOfPHP/sonsofphp/pull/170) [Link] New Component (PSR-13)
+* [PR #173](https://github.com/SonsOfPHP/sonsofphp/pull/173) [Money] Twig Bridge
+* [PR #181](https://github.com/SonsOfPHP/sonsofphp/pull/181) [Cookie] New Component and Contract
+* [PR #182](https://github.com/SonsOfPHP/sonsofphp/pull/182) [Container] New Component (PSR-11)
+* [PR #187](https://github.com/SonsOfPHP/sonsofphp/pull/187) [HttpHandler] New Component (PSR-15) and Contract
+* [PR #190](https://github.com/SonsOfPHP/sonsofphp/pull/190) [Mailer] New Component and Contract
## [0.3.8]
diff --git a/Makefile b/Makefile
index 8edf6ea1..f3fdb73b 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@ purge: # Purge vendor and lock files
rm -rf src/SonsOfPHP/Bundle/*/vendor/ src/SonsOfPHP/Bundle/*/composer.lock
rm -rf src/SonsOfPHP/Component/*/vendor/ src/SonsOfPHP/Component/*/composer.lock
rm -rf src/SonsOfPHP/Contract/*/vendor/ src/SonsOfPHP/Contract/*/composer.lock
+ rm -rf src/tools/*/vendor/ src/tools/*/composer.lock
test: phpunit ## Run PHPUnit Tests
@@ -52,15 +53,33 @@ test-cache: phpunit
test-clock: PHPUNIT_TESTSUITE=clock
test-clock: phpunit
+test-container: PHPUNIT_TESTSUITE=container
+test-container: phpunit
+
+test-cookie: PHPUNIT_TESTSUITE=cookie
+test-cookie: phpunit
+
test-cqrs: PHPUNIT_TESTSUITE=cqrs
test-cqrs: phpunit
+test-http-factory: PHPUNIT_TESTSUITE=http-factory
+test-http-factory: phpunit
+
+test-http-handler: PHPUNIT_TESTSUITE=http-handler
+test-http-handler: phpunit
+
test-link: PHPUNIT_TESTSUITE=link
test-link: phpunit
test-logger: PHPUNIT_TESTSUITE=logger
test-logger: phpunit
+test-mailer: PHPUNIT_TESTSUITE=mailer
+test-mailer: phpunit
+
+test-money: PHPUNIT_TESTSUITE=money
+test-money: phpunit
+
test-pager: PHPUNIT_TESTSUITE=pager
test-pager: phpunit
@@ -96,6 +115,12 @@ coverage-cache: coverage
coverage-clock: PHPUNIT_TESTSUITE=clock
coverage-clock: coverage
+coverage-container: PHPUNIT_TESTSUITE=container
+coverage-container: coverage
+
+coverage-cookie: PHPUNIT_TESTSUITE=cookie
+coverage-cookie: coverage
+
coverage-cqrs: PHPUNIT_TESTSUITE=cqrs
coverage-cqrs: coverage
@@ -114,6 +139,9 @@ coverage-filesystem:
coverage-http-factory:
XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --testsuite http-factory --coverage-html $(COVERAGE_DIR)
+coverage-http-handler: PHPUNIT_TESTSUITE=http-handler
+coverage-http-handler: coverage
+
coverage-http-message:
XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --testsuite http-message --coverage-html $(COVERAGE_DIR)
@@ -126,8 +154,11 @@ coverage-link: coverage
coverage-logger: PHPUNIT_TESTSUITE=logger
coverage-logger: coverage
-coverage-money:
- XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --testsuite money --coverage-html $(COVERAGE_DIR)
+coverage-mailer: PHPUNIT_TESTSUITE=mailer
+coverage-mailer: coverage
+
+coverage-money: PHPUNIT_TESTSUITE=money
+coverage-money: coverage
coverage-pager: PHPUNIT_TESTSUITE=pager
coverage-pager: coverage
@@ -162,6 +193,13 @@ php-cs-fixer-upgrade:
testdox: ## Run tests and output testdox
XDEBUG_MODE=off $(PHP) -dxdebug.mode=off $(PHPUNIT) --testdox
+infection:
+ XDEBUG_MODE=develop \
+ $(PHP) \
+ -dxdebug.mode=develop \
+ -dapc.enable_cli=1 \
+ tools/infection/vendor/bin/infection --debug -vvv --show-mutations
+
tools-install: psalm-install php-cs-fixer-install phpunit-install
tools-upgrade: psalm-upgrade php-cs-fixer-upgrade phpunit-upgrade
diff --git a/bard.json b/bard.json
index 497c40f7..d70c02bc 100644
--- a/bard.json
+++ b/bard.json
@@ -5,6 +5,14 @@
"path": "src/SonsOfPHP/Bard",
"repository": "git@github.com:SonsOfPHP/bard.git"
},
+ {
+ "path": "src/SonsOfPHP/Contract/Mailer",
+ "repository": "git@github.com:SonsOfPHP/mailer-contract.git"
+ },
+ {
+ "path": "src/SonsOfPHP/Component/Mailer",
+ "repository": "git@github.com:SonsOfPHP/mailer.git"
+ },
{
"path": "src/SonsOfPHP/Component/Cache",
"repository": "git@github.com:SonsOfPHP/cache.git"
@@ -13,6 +21,14 @@
"path": "src/SonsOfPHP/Component/Clock",
"repository": "git@github.com:SonsOfPHP/clock.git"
},
+ {
+ "path": "src/SonsOfPHP/Component/Container",
+ "repository": "git@github.com:SonsOfPHP/container.git"
+ },
+ {
+ "path": "src/SonsOfPHP/Component/Cookie",
+ "repository": "git@github.com:SonsOfPHP/cookie.git"
+ },
{
"path": "src/SonsOfPHP/Component/Cqrs",
"repository": "git@github.com:SonsOfPHP/cqrs.git"
@@ -29,6 +45,10 @@
"path": "src/SonsOfPHP/Bridge/Symfony/EventSourcing",
"repository": "git@github.com:SonsOfPHP/event-sourcing-symfony.git"
},
+ {
+ "path": "src/SonsOfPHP/Bridge/Twig/Money",
+ "repository": "git@github.com:SonsOfPHP/money-twig.git"
+ },
{
"path": "src/SonsOfPHP/Component/EventDispatcher",
"repository": "git@github.com:SonsOfPHP/event-dispatcher.git"
@@ -53,6 +73,14 @@
"path": "src/SonsOfPHP/Component/HttpFactory",
"repository": "git@github.com:SonsOfPHP/http-factory.git"
},
+ {
+ "path": "src/SonsOfPHP/Component/HttpHandler",
+ "repository": "git@github.com:SonsOfPHP/http-handler.git"
+ },
+ {
+ "path": "src/SonsOfPHP/Contract/HttpHandler",
+ "repository": "git@github.com:SonsOfPHP/http-handler-contract.git"
+ },
{
"path": "src/SonsOfPHP/Component/HttpMessage",
"repository": "git@github.com:SonsOfPHP/http-message.git"
@@ -77,6 +105,18 @@
"path": "src/SonsOfPHP/Component/Pager",
"repository": "git@github.com:SonsOfPHP/pager.git"
},
+ {
+ "path": "src/SonsOfPHP/Bridge/Doctrine/Collections/Pager",
+ "repository": "git@github.com:SonsOfPHP/pager-doctrine-collections.git"
+ },
+ {
+ "path": "src/SonsOfPHP/Bridge/Doctrine/DBAL/Pager",
+ "repository": "git@github.com:SonsOfPHP/pager-doctrine-dbal.git"
+ },
+ {
+ "path": "src/SonsOfPHP/Bridge/Doctrine/ORM/Pager",
+ "repository": "git@github.com:SonsOfPHP/pager-doctrine-orm.git"
+ },
{
"path": "src/SonsOfPHP/Component/Version",
"repository": "git@github.com:SonsOfPHP/version.git"
@@ -85,6 +125,10 @@
"path": "src/SonsOfPHP/Contract/Common",
"repository": "git@github.com:SonsOfPHP/common-contract.git"
},
+ {
+ "path": "src/SonsOfPHP/Contract/Cookie",
+ "repository": "git@github.com:SonsOfPHP/cookie-contract.git"
+ },
{
"path": "src/SonsOfPHP/Contract/Cqrs",
"repository": "git@github.com:SonsOfPHP/cqrs-contract.git"
diff --git a/composer.json b/composer.json
index f730a17d..cf9d1765 100644
--- a/composer.json
+++ b/composer.json
@@ -47,7 +47,13 @@
"psr/log-implementation": "^1.0 || ^2.0 || ^3.0",
"sonsofphp/logger-implementation": "0.3.x-dev",
"sonsofphp/pager-implementation": "0.3.x-dev",
- "psr/link-implementation": "^1.0 || ^2.0"
+ "psr/link-implementation": "^1.0 || ^2.0",
+ "sonsofphp/cookie-implementation": "0.3.x-dev",
+ "psr/container-implementation": "^1.0 || ^2.0",
+ "psr/http-server-handler-implementation": "^1.0",
+ "psr/http-server-middleware-implementation": "^1.0",
+ "sonsofphp/http-handler-implementation": "0.3.x-dev",
+ "sonsofphp/mailer-implementation": "0.3.x-dev"
},
"require": {
"php": ">=8.1",
@@ -70,7 +76,14 @@
"psr/cache": "^2.0 || ^3.0",
"psr/simple-cache": "^3.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
- "psr/link": "^1.0 || ^2.0"
+ "psr/link": "^1.0 || ^2.0",
+ "twig/twig": "^3.0",
+ "ext-intl": "*",
+ "doctrine/collections": "^2",
+ "doctrine/orm": "^2",
+ "psr/container": "^1.0 || ^2.0",
+ "psr/http-server-handler": "^1.0",
+ "psr/http-server-middleware": "^1.0"
},
"replace": {
"sonsofphp/bard": "self.version",
@@ -102,31 +115,53 @@
"sonsofphp/logger-contract": "self.version",
"sonsofphp/pager-contract": "self.version",
"sonsofphp/pager": "self.version",
- "sonsofphp/link": "self.version"
+ "sonsofphp/link": "self.version",
+ "sonsofphp/money-twig": "self.version",
+ "sonsofphp/pager-doctrine-collections": "self.version",
+ "sonsofphp/pager-doctrine-dbal": "self.version",
+ "sonsofphp/pager-doctrine-orm": "self.version",
+ "sonsofphp/cookie": "self.version",
+ "sonsofphp/cookie-contract": "self.version",
+ "sonsofphp/container": "self.version",
+ "sonsofphp/http-handler": "self.version",
+ "sonsofphp/http-handler-contract": "self.version",
+ "sonsofphp/mailer-contract": "self.version",
+ "sonsofphp/mailer": "self.version"
},
"autoload": {
"psr-4": {
"SonsOfPHP\\Bard\\": "src/SonsOfPHP/Bard/src",
+ "SonsOfPHP\\Contract\\Mailer\\": "src/SonsOfPHP/Contract/Mailer",
+ "SonsOfPHP\\Component\\Mailer\\": "src/SonsOfPHP/Component/Mailer",
"SonsOfPHP\\Component\\Cache\\": "src/SonsOfPHP/Component/Cache",
"SonsOfPHP\\Component\\Clock\\": "src/SonsOfPHP/Component/Clock",
+ "SonsOfPHP\\Component\\Container\\": "src/SonsOfPHP/Component/Container",
+ "SonsOfPHP\\Component\\Cookie\\": "src/SonsOfPHP/Component/Cookie",
"SonsOfPHP\\Component\\Cqrs\\": "src/SonsOfPHP/Component/Cqrs",
"SonsOfPHP\\Bundle\\Cqrs\\": "src/SonsOfPHP/Bundle/Cqrs",
"SonsOfPHP\\Bridge\\Symfony\\Cqrs\\": "src/SonsOfPHP/Bridge/Symfony/Cqrs",
"SonsOfPHP\\Bridge\\Symfony\\EventSourcing\\": "src/SonsOfPHP/Bridge/Symfony/EventSourcing",
+ "SonsOfPHP\\Bridge\\Twig\\Money\\": "src/SonsOfPHP/Bridge/Twig/Money",
"SonsOfPHP\\Component\\EventDispatcher\\": "src/SonsOfPHP/Component/EventDispatcher",
"SonsOfPHP\\Component\\EventSourcing\\": "src/SonsOfPHP/Component/EventSourcing",
"SonsOfPHP\\Bridge\\Doctrine\\EventSourcing\\": "src/SonsOfPHP/Bridge/Doctrine/EventSourcing",
"SonsOfPHP\\Component\\FeatureToggle\\": "src/SonsOfPHP/Component/FeatureToggle",
"SonsOfPHP\\Component\\Filesystem\\": "src/SonsOfPHP/Component/Filesystem",
"SonsOfPHP\\Component\\HttpFactory\\": "src/SonsOfPHP/Component/HttpFactory",
+ "SonsOfPHP\\Component\\HttpHandler\\": "src/SonsOfPHP/Component/HttpHandler",
+ "SonsOfPHP\\Contract\\HttpHandler\\": "src/SonsOfPHP/Contract/HttpHandler",
"SonsOfPHP\\Component\\HttpMessage\\": "src/SonsOfPHP/Component/HttpMessage",
"SonsOfPHP\\Component\\Json\\": "src/SonsOfPHP/Component/Json",
"SonsOfPHP\\Component\\Link\\": "src/SonsOfPHP/Component/Link",
"SonsOfPHP\\Component\\Logger\\": "src/SonsOfPHP/Component/Logger",
"SonsOfPHP\\Component\\Money\\": "src/SonsOfPHP/Component/Money",
"SonsOfPHP\\Component\\Pager\\": "src/SonsOfPHP/Component/Pager",
+ "SonsOfPHP\\Bridge\\Doctrine\\Collections\\Pager\\": "src/SonsOfPHP/Bridge/Doctrine/Collections/Pager",
+ "SonsOfPHP\\Bridge\\Doctrine\\DBAL\\Pager\\": "src/SonsOfPHP/Bridge/Doctrine/DBAL/Pager",
+ "SonsOfPHP\\Bridge\\Doctrine\\ORM\\Pager\\": "src/SonsOfPHP/Bridge/Doctrine/ORM/Pager",
"SonsOfPHP\\Component\\Version\\": "src/SonsOfPHP/Component/Version",
"SonsOfPHP\\Contract\\Common\\": "src/SonsOfPHP/Contract/Common",
+ "SonsOfPHP\\Contract\\Cookie\\": "src/SonsOfPHP/Contract/Cookie",
"SonsOfPHP\\Contract\\Cqrs\\": "src/SonsOfPHP/Contract/Cqrs",
"SonsOfPHP\\Contract\\EventSourcing\\": "src/SonsOfPHP/Contract/EventSourcing",
"SonsOfPHP\\Contract\\FeatureToggle\\": "src/SonsOfPHP/Contract/FeatureToggle",
@@ -138,24 +173,32 @@
},
"exclude-from-classmap": [
"src/SonsOfPHP/Bard/Tests",
+ "src/SonsOfPHP/Component/Mailer/Tests",
"src/SonsOfPHP/Component/Cache/Tests",
"src/SonsOfPHP/Component/Clock/Tests",
+ "src/SonsOfPHP/Component/Container/Tests",
+ "src/SonsOfPHP/Component/Cookie/Tests",
"src/SonsOfPHP/Component/Cqrs/Tests",
"src/SonsOfPHP/Bundle/Cqrs/Tests",
"src/SonsOfPHP/Bridge/Symfony/Cqrs/Tests",
"src/SonsOfPHP/Bridge/Symfony/EventSourcing/Tests",
+ "src/SonsOfPHP/Bridge/Twig/Money/Tests",
"src/SonsOfPHP/Component/EventDispatcher/Tests",
"src/SonsOfPHP/Component/EventSourcing/Tests",
"src/SonsOfPHP/Bridge/Doctrine/EventSourcing/Tests",
"src/SonsOfPHP/Component/FeatureToggle/Tests",
"src/SonsOfPHP/Component/Filesystem/Tests",
"src/SonsOfPHP/Component/HttpFactory/Tests",
+ "src/SonsOfPHP/Component/HttpHandler/Tests",
"src/SonsOfPHP/Component/HttpMessage/Tests",
"src/SonsOfPHP/Component/Json/Tests",
"src/SonsOfPHP/Component/Link/Tests",
"src/SonsOfPHP/Component/Logger/Tests",
"src/SonsOfPHP/Component/Money/Tests",
"src/SonsOfPHP/Component/Pager/Tests",
+ "src/SonsOfPHP/Bridge/Doctrine/Collections/Pager/Tests",
+ "src/SonsOfPHP/Bridge/Doctrine/DBAL/Pager/Tests",
+ "src/SonsOfPHP/Bridge/Doctrine/ORM/Pager/Tests",
"src/SonsOfPHP/Component/Version/Tests"
]
},
@@ -181,4 +224,4 @@
"SonsOfPHP\\Bridge\\Symfony\\Cqrs\\Tests\\": "src/SonsOfPHP/Bridge/Symfony/Cqrs/Tests"
}
}
-}
\ No newline at end of file
+}
diff --git a/docs/components/container/index.md b/docs/components/container/index.md
new file mode 100644
index 00000000..56fee6e0
--- /dev/null
+++ b/docs/components/container/index.md
@@ -0,0 +1,34 @@
+---
+title: Container
+---
+
+This is a very simple lightweight PSR-11 Container implementation.
+
+## Installation
+
+```shell
+composer require sonsofphp/container
+```
+
+## Usage
+
+```php
+set('service.id.one', function (ContainerInterface $container) {
+ return new Service();
+});
+$container->set('service.id.two', function (ContainerInterface $container) {
+ return new Service($container->get('service.id.one'));
+});
+
+// Services will not be created until they are called, once called, they will
+// always return the same instance of the service. That means that in the
+// following code, the "service.id.two" is only constructed once.
+$service = $container->get('service.id.two');
+$service2 = $container->get('service.id.two');
+```
diff --git a/docs/components/cookie/index.md b/docs/components/cookie/index.md
new file mode 100644
index 00000000..19aa6f17
--- /dev/null
+++ b/docs/components/cookie/index.md
@@ -0,0 +1,33 @@
+---
+title: Cookie
+---
+
+## Installation
+
+```shell
+composer require sonsofphp/cookie
+```
+
+## Usage
+
+A Cookie is treated as a value object. This means that if two cookie objects
+have the same name and value, they will be considered equal. They are also
+considered to be immutable.
+
+```php
+getHeaderValue());
+// OR
+// header('Set-Cookie: ' . (string) $cookie);
+
+// Set various attributes
+$cookie = $cookie
+ ->withPath('/')
+ ->withDomain('docs.sonsofphp.com')
+;
+```
diff --git a/docs/components/cqrs/index.md b/docs/components/cqrs/index.md
index 80a93123..0ef0ca40 100644
--- a/docs/components/cqrs/index.md
+++ b/docs/components/cqrs/index.md
@@ -48,11 +48,11 @@ $queryBus->addHandler(GetUser::class, $handler);
$query = (new GetUser())->with('id', 123);
$user = $queryBus->handle($query);
+```
!!! success "Symfony CQRS Bridge"
Once the CQRS Symfony Bridge is installed, you can use the Query Bus that
comes with that to gain addition features and functionality.
-```
## Messages
diff --git a/docs/components/http-handler/index.md b/docs/components/http-handler/index.md
new file mode 100644
index 00000000..4f36db66
--- /dev/null
+++ b/docs/components/http-handler/index.md
@@ -0,0 +1,56 @@
+---
+title: HttpHandler
+---
+
+Simple PSR-15 Http Handler
+
+## Installation
+
+```shell
+composer require sonsofphp/http-handler
+```
+
+## Usage
+
+Usage is pretty simple.
+
+```php
+add(new RouterMiddleware());
+$stack->add(new CookieMiddleware());
+$stack->add(function ($request, $handler) {
+ // ...
+});
+// ...
+
+$app = new HttpHandler($stack);
+$response = $app->handle($request);
+```
+
+The `MiddlewareStack` accepts objects that implement `Psr\Http\Server\MiddlewareInterface`
+and anonymous functions.
+
+### Middleware Priorities
+
+An optional second argument may be passed to the `MiddlewareStack` which is for
+the priority of the middleware. Priorities are ordered in ascending order.
+
+```php
+add(new NotFoundMiddleware(), 1025);
+$stack->add(new RouterMiddleware(), 255);
+$stack->add(new CookieMiddleware(), -255);
+$stack->add(new DefaultMiddleware());
+```
+
+In the above example, the `CookieMiddleware` will be processed first and
+`NotFoundMiddleware` will be processed last.
diff --git a/docs/components/mailer/index.md b/docs/components/mailer/index.md
new file mode 100644
index 00000000..6c134bdd
--- /dev/null
+++ b/docs/components/mailer/index.md
@@ -0,0 +1,46 @@
+---
+title: Mailer
+---
+
+Simple PHP Mailer
+
+## Installation
+
+```shell
+composer require sonsofphp/mailer
+```
+
+## Usage
+
+```php
+setTo('joshua@sonsofphp.com')
+ ->setFrom('From', 'joshua@sonsofphp.com')
+ ->setSubject('Subject', 'Test Subject')
+ ->setBody($body)
+;
+
+$mailer = new Mailer(new NullTransport());
+$mailer->send($message);
+```
+
+### Middleware
+
+The `Mailer` class supports various middleware as well.
+
+```php
+addMiddleware($middleware);
+```
diff --git a/docs/components/money/index.md b/docs/components/money/index.md
index a034f31d..6359432d 100644
--- a/docs/components/money/index.md
+++ b/docs/components/money/index.md
@@ -72,6 +72,51 @@ $currency = new Currency('USD');
$currency = Currency::USD();
```
+### Formatters
+
+```php
+format(Money::USD(4.20));
+echo $output; // $4.20
+```
+
+## Twig Bridge
+
+### Installation
+
+```shell
+composer require sonsofphp/money-twig
+```
+
+### Usage
+
+#### Add Extension to Twig Environment
+
+```php
+addExtension($extension);
+```
+
+#### Usage in Twig Templates
+
+```twig
+Your total is {{ money|format_money }}.
+```
+
+
## Need Help?
Check out [Sons of PHP's Organization Discussions][discussions].
diff --git a/docs/components/pager/index.md b/docs/components/pager/index.md
index ab57ea4d..c9a23af6 100644
--- a/docs/components/pager/index.md
+++ b/docs/components/pager/index.md
@@ -45,9 +45,35 @@ $pager = new Pager(new ArrayAdapter($results), [
// You can also set current page and max per page
$pager->setCurrentPage(1);
$pager->setMaxPerPage(10);
+
+
+$totalPages = $pager->getTotalPages();
+$totalResults = $pager->getTotalResults();
+$currentPage = $pager->getCurrentPage();
+
+if ($pager->haveToPaginate()) {
+ // ...
+}
+
+if ($pager->hasPreviousPage()) {
+ $prevPage = $pager->getPreviousPage();
+ // ...
+}
+
+if ($pager->hasNextPage()) {
+ $nextPage = $pager->getNextPage();
+ // ...
+}
```
-## Adapters
+## Custom Adapters
+
+Creating Custom Adapters is easy. You can take a look at the available adapters
+to see how easy it is.
+
+Please see the [Pager Contract](../../contracts/pager/index.md) to learn more.
+
+## Available Adapters
### ArrayAdapter
@@ -77,3 +103,59 @@ $adapter = new CallableAdapter(
},
);
```
+
+### ArrayCollectionAdapter (doctrine/collections)
+
+!!! warning "Requires `sonsofphp/pager-doctrine-collections`"
+ ```shell
+ composer require sonsofphp/pager-doctrine-collections
+ ```
+
+```php
+select('COUNT(e.id) as total');
+});
+```
+
+### QueryBuilderAdapter (doctrine/orm)
+
+!!! warning "Requires `sonsofphp/pager-doctrine-orm`"
+ ```shell
+ composer require sonsofphp/pager-doctrine-orm
+ ```
+
+```php
+createQueryBuilder('e');
+
+$adapter = new QueryBuilderAdapter($builder);
+```
diff --git a/docs/contracts/common/index.md b/docs/contracts/common/index.md
index cc1e0a7d..818c807c 100644
--- a/docs/contracts/common/index.md
+++ b/docs/contracts/common/index.md
@@ -1,5 +1,6 @@
---
title: Common Contracts - Overview
+description: PHP Common Contracts
---
# Common Contracts
@@ -15,7 +16,8 @@ composer require sonsofphp/common-contract
## Includes Interfaces
-* ArrayableInterface
-* ComparableInterface
-* EquatableInterface
-* JsonableInterface
+* `ArrayableInterface`
+* `ComparableInterface`
+* `EquatableInterface`
+* `JsonableInterface`
+* `TryableInterface`
diff --git a/docs/contracts/cookie/index.md b/docs/contracts/cookie/index.md
new file mode 100644
index 00000000..77157f49
--- /dev/null
+++ b/docs/contracts/cookie/index.md
@@ -0,0 +1,9 @@
+---
+title: Cookie
+---
+
+## Installation
+
+```shell
+composer require sonsofphp/cookie-contract
+```
diff --git a/docs/contracts/index.md b/docs/contracts/index.md
index 7a160344..6ca2be7f 100644
--- a/docs/contracts/index.md
+++ b/docs/contracts/index.md
@@ -20,6 +20,64 @@ If you want to provide a concrete library for others to use, add this to your
```json
"provide": {
- "sonsofphp/core-contract-implementation": "^1.0"
+ "sonsofphp/common-implementation": "^1.0"
},
```
+
+## Method Naming
+
+Functionality around method names are kept as similar as possible. They SHOULD
+follow this convention.
+
+### with*
+
+`with*` methods are meant to be used on value objects. They will return a new
+object with the value(s) modified.
+
+Examples:
+- `withFirstName`
+
+### has*
+
+Will always return a `boolean` value. Used to check if a property or value
+exists on the object. Doesn't matter the type of the value.
+
+Examples
+- `hasFirstName`
+
+### is*
+
+Will always return a `boolean` value.
+
+Examples:
+- `isNew`
+- `isDeleted`
+
+### get*
+
+Used to return property values.
+
+Examples:
+- `getFirstName`
+- `getLastName`
+
+### set*
+
+Used to set property values. SHOULD always return the same instance of the
+object to allow chaining.
+
+Examples:
+- `setFirstName`
+- `setLastName`
+
+### to*
+
+Used to convert an object to a specific format.
+
+Examples:
+- `toJson`
+- `toString`
+- `toArray`
+- `toInteger`
+- `toFloat`
+- `toBoolean`
diff --git a/docs/contracts/mailer/index.md b/docs/contracts/mailer/index.md
new file mode 100644
index 00000000..40eeb45d
--- /dev/null
+++ b/docs/contracts/mailer/index.md
@@ -0,0 +1,18 @@
+---
+title: Mailer Contract
+---
+
+## Installation
+
+```shell
+composer require sonsofphp/mailer-contract
+```
+
+## Definitions
+
+- **Message** - The email message that will be sent.
+- **Mailer** - Primary API used to send *messages*.
+- **Transport** - Transports are what will actually send the message. This could
+ be SMTP, Null, SendGrid, Amazon SES, or anything like that.
+- **Middleware** - Before the message is sent to the transport to be sent,
+ various middlewares have the ability to modify the message.
diff --git a/docs/contracts/pager/index.md b/docs/contracts/pager/index.md
index 550b6de1..d2333a30 100644
--- a/docs/contracts/pager/index.md
+++ b/docs/contracts/pager/index.md
@@ -10,3 +10,37 @@ components.
```shell
composer require sonsofphp/pager-contract
```
+
+## AdapterInterface
+
+```php
+
src/SonsOfPHP/Bridge/*/*/Tests
+ src/SonsOfPHP/Bridge/*/*/*/Tests
src/SonsOfPHP/Bundle/*/Tests
src/SonsOfPHP/Component/*/Tests
@@ -29,6 +30,14 @@
src/SonsOfPHP/Component/Clock/Tests
+
+ src/SonsOfPHP/Component/Container/Tests
+
+
+
+ src/SonsOfPHP/Component/Cookie/Tests
+
+
src/SonsOfPHP/Bridge/*/Cqrs/Tests
@@ -55,6 +64,10 @@
src/SonsOfPHP/Component/HttpFactory/Tests
+
+ src/SonsOfPHP/Component/HttpHandler/Tests
+
+
src/SonsOfPHP/Component/HttpMessage/Tests
@@ -71,11 +84,17 @@
src/SonsOfPHP/Component/Logger/Tests
+
+ src/SonsOfPHP/Component/Mailer/Tests
+
+
+ src/SonsOfPHP/Bridge/*/Money/Tests
src/SonsOfPHP/Component/Money/Tests
+ src/SonsOfPHP/Bridge/*/*/Pager/Tests
src/SonsOfPHP/Component/Pager/Tests
@@ -84,7 +103,7 @@
-
+