{"action":"created","comment":{"url":"https://api.github.com/repos/cakephp/cakephp/pulls/comments/28385363","id":28385363,"diff_hunk":"@@ -0,0 +1,118 @@\n+<?php\n+namespace Cake\\Test\\TestCase\\Mailer;\n+\n+use Cake\\Mailer\\Email;\n+use Cake\\Mailer\\Mailer;\n+use Cake\\TestSuite\\TestCase;\n+\n+class TestMailer extends Mailer\n+{\n+    public function getEmailForAssertion()","path":"tests/TestCase/Mailer/MailerTest.php","position":10,"original_position":10,"commit_id":"be2289fe1bce2ffe9bb88492c8503f0e2567baab","original_commit_id":"be2289fe1bce2ffe9bb88492c8503f0e2567baab","user":{"login":"markstory","id":24086,"avatar_url":"https://avatars.githubusercontent.com/u/24086?v=3","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"body":"Why not have a public getter for the underlying email?","created_at":"2015-04-15T00:41:14Z","updated_at":"2015-04-15T00:41:14Z","html_url":"https://github.com/cakephp/cakephp/pull/6324#discussion_r28385363","pull_request_url":"https://api.github.com/repos/cakephp/cakephp/pulls/6324","_links":{"self":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/comments/28385363"},"html":{"href":"https://github.com/cakephp/cakephp/pull/6324#discussion_r28385363"},"pull_request":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/6324"}}},"pull_request":{"url":"https://api.github.com/repos/cakephp/cakephp/pulls/6324","id":33123281,"html_url":"https://github.com/cakephp/cakephp/pull/6324","diff_url":"https://github.com/cakephp/cakephp/pull/6324.diff","patch_url":"https://github.com/cakephp/cakephp/pull/6324.patch","issue_url":"https://api.github.com/repos/cakephp/cakephp/issues/6324","number":6324,"state":"open","locked":false,"title":"RFC - Mailer","user":{"login":"jadb","id":33527,"avatar_url":"https://avatars.githubusercontent.com/u/33527?v=3","gravatar_id":"","url":"https://api.github.com/users/jadb","html_url":"https://github.com/jadb","followers_url":"https://api.github.com/users/jadb/followers","following_url":"https://api.github.com/users/jadb/following{/other_user}","gists_url":"https://api.github.com/users/jadb/gists{/gist_id}","starred_url":"https://api.github.com/users/jadb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jadb/subscriptions","organizations_url":"https://api.github.com/users/jadb/orgs","repos_url":"https://api.github.com/users/jadb/repos","events_url":"https://api.github.com/users/jadb/events{/privacy}","received_events_url":"https://api.github.com/users/jadb/received_events","type":"User","site_admin":false},"body":"This supersedes #6319 and as suggested by @markstory, adds some conventions borrowed from Rails' [ActionMailer](http://edgeguides.rubyonrails.org/action_mailer_basics.html).\r\n\r\n## TODO\r\n\r\n- [x] Move all email related classes out of `Cake\\Network\\Email` and into their own namespace. Agreed with @markstory and @lorenzo on `Cake\\Mailer`, with aliases for BC.\r\n- [x] Move transports into their own namespace at `Cake\\Mailer\\Transport` with aliases for BC.\r\n- [x] Create a new `Mailer` class that would make working with emails very similar to controllers (actions, templates, model-aware).\r\n- [ ] Create new bake command(s) to create mailer classes and/or templates.\r\n- [x] Update cakephp/app's `config/bootstrap.php` and `config/app.default.php`.\r\n\r\n## Usage\r\n\r\nFor documentation's sake and to better grasp the changes, here's a sample code of what would/should work when the work is finished.\r\n\r\n```\r\nbin/cake bake mailer user welcome,reset_password\r\n```\r\n\r\nwhich would generate the following:\r\n\r\n```\r\n- src/Mailer/UserMailer.php\r\n- src/Template/Layout/Email/html/user.ctp\r\n- src/Template/Layout/Email/text/user.ctp\r\n- src/Template/Email/html/User/welcome.ctp\r\n- src/Template/Email/html/User//reset_password.ctp\r\n- src/Template/Email/text/User/welcome.ctp\r\n- src/Template/Email/text/User/reset_password.ctp\r\n```\r\n\r\n`UserMailer` would look like this after some customizations:\r\n\r\n```php\r\n<?php\r\nnamespace App\\Mailer;\r\n\r\nuse ArrayObject;\r\nuse Cake\\Event\\Event;\r\nuse Cake\\Mailer\\Mailer;\r\nuse Cake\\ORM\\Entity;\r\n\r\nclass UserMailer extends Mailer\r\n{\r\n    public function welcome($user)\r\n    {\r\n        $this->subject = sprintf('Welcome %s', $user->name);\r\n        $this->to = $user->email;\r\n    }\r\n\r\n    public function resetPassword($user)\r\n    {\r\n        $this->subject = sprintf('Reset password');\r\n        $this->to = $user->email;\r\n        $this->set(['token' => $user->token]);\r\n    }\r\n\r\n    public function implementedEvents()\r\n    {\r\n        return [\r\n            'Model.afterSave' => 'onRegistration',\r\n        ];\r\n    }\r\n\r\n   public function onRegistration(Event $event, Entity $entity, ArrayObject $options)\r\n   {\r\n       if ($entity->isNew()) {\r\n            $this->send('welcome', [$entity]);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nAnd then from the controller (or any class using `MailerAwareTrait`):\r\n\r\n```php\r\n<?php\r\nnamespace App\\Controller;\r\n\r\nuse Cake\\Mailer\\MailerAwareTrait;\r\n\r\nclass UsersController extends AppController\r\n{\r\n    use MailerAwareTrait;\r\n\r\n    public function register()\r\n    {\r\n        ...\r\n        $this->getMailer('User')->send('welcome', [$user]);\r\n        ...\r\n    }\r\n}\r\n```\r\n\r\nor in a table using events:\r\n\r\n```php\r\n<?php\r\nnamespace App\\Model\\Table;\r\n\r\nuse App\\Mailer\\UserMailer;\r\nuse Cake\\ORM\\Table;\r\n\r\nclass UsersTable extends Table\r\n{\r\n    public function initialize(array $config = [])\r\n    {\r\n        ...\r\n        $this->eventManager->on(new UserMailer());\r\n    }\r\n}\r\n```","created_at":"2015-04-12T17:36:01Z","updated_at":"2015-04-15T00:41:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d29df824cb5503c59ad918b0f45dc47fd9e54117","assignee":{"login":"jadb","id":33527,"avatar_url":"https://avatars.githubusercontent.com/u/33527?v=3","gravatar_id":"","url":"https://api.github.com/users/jadb","html_url":"https://github.com/jadb","followers_url":"https://api.github.com/users/jadb/followers","following_url":"https://api.github.com/users/jadb/following{/other_user}","gists_url":"https://api.github.com/users/jadb/gists{/gist_id}","starred_url":"https://api.github.com/users/jadb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jadb/subscriptions","organizations_url":"https://api.github.com/users/jadb/orgs","repos_url":"https://api.github.com/users/jadb/repos","events_url":"https://api.github.com/users/jadb/events{/privacy}","received_events_url":"https://api.github.com/users/jadb/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/cakephp/cakephp/milestones/31","html_url":"https://github.com/cakephp/cakephp/milestones/3.1.0","labels_url":"https://api.github.com/repos/cakephp/cakephp/milestones/31/labels","id":919718,"number":31,"title":"3.1.0","description":"Backwards compatible with 3.0.x. Will require PHP 5.5\r\n\r\n### Specific issues\r\n\r\n* Adding the exception trace to the error view data. #6000 \r\n* Changed the translate behavior to support translation engines. #5958 \r\n* Database connection prefixes, or table prefixes.","creator":{"login":"lorenzo","id":37621,"avatar_url":"https://avatars.githubusercontent.com/u/37621?v=3","gravatar_id":"","url":"https://api.github.com/users/lorenzo","html_url":"https://github.com/lorenzo","followers_url":"https://api.github.com/users/lorenzo/followers","following_url":"https://api.github.com/users/lorenzo/following{/other_user}","gists_url":"https://api.github.com/users/lorenzo/gists{/gist_id}","starred_url":"https://api.github.com/users/lorenzo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lorenzo/subscriptions","organizations_url":"https://api.github.com/users/lorenzo/orgs","repos_url":"https://api.github.com/users/lorenzo/repos","events_url":"https://api.github.com/users/lorenzo/events{/privacy}","received_events_url":"https://api.github.com/users/lorenzo/received_events","type":"User","site_admin":false},"open_issues":51,"closed_issues":32,"state":"open","created_at":"2015-01-02T15:38:07Z","updated_at":"2015-04-14T18:11:20Z","due_on":"2015-07-26T04:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/cakephp/cakephp/pulls/6324/commits","review_comments_url":"https://api.github.com/repos/cakephp/cakephp/pulls/6324/comments","review_comment_url":"https://api.github.com/repos/cakephp/cakephp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cakephp/cakephp/issues/6324/comments","statuses_url":"https://api.github.com/repos/cakephp/cakephp/statuses/be2289fe1bce2ffe9bb88492c8503f0e2567baab","head":{"label":"cakephp:3.1-mailer","ref":"3.1-mailer","sha":"be2289fe1bce2ffe9bb88492c8503f0e2567baab","user":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"repo":{"id":656494,"name":"cakephp","full_name":"cakephp/cakephp","owner":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cakephp/cakephp","description":"CakePHP: The Rapid Development Framework for PHP - Official Repository","fork":false,"url":"https://api.github.com/repos/cakephp/cakephp","forks_url":"https://api.github.com/repos/cakephp/cakephp/forks","keys_url":"https://api.github.com/repos/cakephp/cakephp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cakephp/cakephp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cakephp/cakephp/teams","hooks_url":"https://api.github.com/repos/cakephp/cakephp/hooks","issue_events_url":"https://api.github.com/repos/cakephp/cakephp/issues/events{/number}","events_url":"https://api.github.com/repos/cakephp/cakephp/events","assignees_url":"https://api.github.com/repos/cakephp/cakephp/assignees{/user}","branches_url":"https://api.github.com/repos/cakephp/cakephp/branches{/branch}","tags_url":"https://api.github.com/repos/cakephp/cakephp/tags","blobs_url":"https://api.github.com/repos/cakephp/cakephp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cakephp/cakephp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cakephp/cakephp/git/refs{/sha}","trees_url":"https://api.github.com/repos/cakephp/cakephp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cakephp/cakephp/statuses/{sha}","languages_url":"https://api.github.com/repos/cakephp/cakephp/languages","stargazers_url":"https://api.github.com/repos/cakephp/cakephp/stargazers","contributors_url":"https://api.github.com/repos/cakephp/cakephp/contributors","subscribers_url":"https://api.github.com/repos/cakephp/cakephp/subscribers","subscription_url":"https://api.github.com/repos/cakephp/cakephp/subscription","commits_url":"https://api.github.com/repos/cakephp/cakephp/commits{/sha}","git_commits_url":"https://api.github.com/repos/cakephp/cakephp/git/commits{/sha}","comments_url":"https://api.github.com/repos/cakephp/cakephp/comments{/number}","issue_comment_url":"https://api.github.com/repos/cakephp/cakephp/issues/comments{/number}","contents_url":"https://api.github.com/repos/cakephp/cakephp/contents/{+path}","compare_url":"https://api.github.com/repos/cakephp/cakephp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cakephp/cakephp/merges","archive_url":"https://api.github.com/repos/cakephp/cakephp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cakephp/cakephp/downloads","issues_url":"https://api.github.com/repos/cakephp/cakephp/issues{/number}","pulls_url":"https://api.github.com/repos/cakephp/cakephp/pulls{/number}","milestones_url":"https://api.github.com/repos/cakephp/cakephp/milestones{/number}","notifications_url":"https://api.github.com/repos/cakephp/cakephp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cakephp/cakephp/labels{/name}","releases_url":"https://api.github.com/repos/cakephp/cakephp/releases{/id}","created_at":"2010-05-08T14:38:22Z","updated_at":"2015-04-15T00:34:42Z","pushed_at":"2015-04-15T00:34:42Z","git_url":"git://github.com/cakephp/cakephp.git","ssh_url":"git@github.com:cakephp/cakephp.git","clone_url":"https://github.com/cakephp/cakephp.git","svn_url":"https://github.com/cakephp/cakephp","homepage":"http://cakephp.org","size":161922,"stargazers_count":5690,"watchers_count":5690,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2560,"mirror_url":null,"open_issues_count":134,"forks":2560,"open_issues":134,"watchers":5690,"default_branch":"master"}},"base":{"label":"cakephp:3.1","ref":"3.1","sha":"53fbde2fa943351c76acfd6979f3a83e733bc549","user":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"repo":{"id":656494,"name":"cakephp","full_name":"cakephp/cakephp","owner":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cakephp/cakephp","description":"CakePHP: The Rapid Development Framework for PHP - Official Repository","fork":false,"url":"https://api.github.com/repos/cakephp/cakephp","forks_url":"https://api.github.com/repos/cakephp/cakephp/forks","keys_url":"https://api.github.com/repos/cakephp/cakephp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cakephp/cakephp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cakephp/cakephp/teams","hooks_url":"https://api.github.com/repos/cakephp/cakephp/hooks","issue_events_url":"https://api.github.com/repos/cakephp/cakephp/issues/events{/number}","events_url":"https://api.github.com/repos/cakephp/cakephp/events","assignees_url":"https://api.github.com/repos/cakephp/cakephp/assignees{/user}","branches_url":"https://api.github.com/repos/cakephp/cakephp/branches{/branch}","tags_url":"https://api.github.com/repos/cakephp/cakephp/tags","blobs_url":"https://api.github.com/repos/cakephp/cakephp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cakephp/cakephp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cakephp/cakephp/git/refs{/sha}","trees_url":"https://api.github.com/repos/cakephp/cakephp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cakephp/cakephp/statuses/{sha}","languages_url":"https://api.github.com/repos/cakephp/cakephp/languages","stargazers_url":"https://api.github.com/repos/cakephp/cakephp/stargazers","contributors_url":"https://api.github.com/repos/cakephp/cakephp/contributors","subscribers_url":"https://api.github.com/repos/cakephp/cakephp/subscribers","subscription_url":"https://api.github.com/repos/cakephp/cakephp/subscription","commits_url":"https://api.github.com/repos/cakephp/cakephp/commits{/sha}","git_commits_url":"https://api.github.com/repos/cakephp/cakephp/git/commits{/sha}","comments_url":"https://api.github.com/repos/cakephp/cakephp/comments{/number}","issue_comment_url":"https://api.github.com/repos/cakephp/cakephp/issues/comments{/number}","contents_url":"https://api.github.com/repos/cakephp/cakephp/contents/{+path}","compare_url":"https://api.github.com/repos/cakephp/cakephp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cakephp/cakephp/merges","archive_url":"https://api.github.com/repos/cakephp/cakephp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cakephp/cakephp/downloads","issues_url":"https://api.github.com/repos/cakephp/cakephp/issues{/number}","pulls_url":"https://api.github.com/repos/cakephp/cakephp/pulls{/number}","milestones_url":"https://api.github.com/repos/cakephp/cakephp/milestones{/number}","notifications_url":"https://api.github.com/repos/cakephp/cakephp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cakephp/cakephp/labels{/name}","releases_url":"https://api.github.com/repos/cakephp/cakephp/releases{/id}","created_at":"2010-05-08T14:38:22Z","updated_at":"2015-04-15T00:34:42Z","pushed_at":"2015-04-15T00:34:42Z","git_url":"git://github.com/cakephp/cakephp.git","ssh_url":"git@github.com:cakephp/cakephp.git","clone_url":"https://github.com/cakephp/cakephp.git","svn_url":"https://github.com/cakephp/cakephp","homepage":"http://cakephp.org","size":161922,"stargazers_count":5690,"watchers_count":5690,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2560,"mirror_url":null,"open_issues_count":134,"forks":2560,"open_issues":134,"watchers":5690,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/6324"},"html":{"href":"https://github.com/cakephp/cakephp/pull/6324"},"issue":{"href":"https://api.github.com/repos/cakephp/cakephp/issues/6324"},"comments":{"href":"https://api.github.com/repos/cakephp/cakephp/issues/6324/comments"},"review_comments":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/6324/comments"},"review_comment":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/6324/commits"},"statuses":{"href":"https://api.github.com/repos/cakephp/cakephp/statuses/be2289fe1bce2ffe9bb88492c8503f0e2567baab"}}}}