Skip to content

Commit fdcc490

Browse files
authored
Merge pull request #3 from jaapromijn/ticket-12888-subscription-confirmation-email
Add the receiver determiner
2 parents 65899d5 + 93c535d commit fdcc490

File tree

6 files changed

+554
-0
lines changed

6 files changed

+554
-0
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,45 @@ Create your message in $message and
7777
```
7878
$mailer->sendMessage($message);
7979
```
80+
81+
## Retrieving receivers from objects
82+
83+
It is possible to use a Determiner to retrieve the receivers (email/name) from an email configuration.
84+
For instance from an object:
85+
86+
``` php
87+
$profile = new Profile();
88+
$profile->setEmail('foobarz@example.com');
89+
$profile->setFullName('Foo Barz');
90+
91+
$emailConfiguration = ['{{email}}' => '{{full_name'}}];
92+
$determiner = new RonRademaker\Mailer\Receiver\Determiner();
93+
$receiver = $determiner->getReceivers($profile, null, $emailConfiguration);
94+
// results in ['foobarz@example.com' => 'Foo Barz'];
95+
```
96+
Or an object with chained field configuration:
97+
98+
``` php
99+
$profile = new Profile();
100+
$profile->setEmail('foobarz@example.com');
101+
$profile->setFullName('Foo Barz');
102+
$company = new Company();
103+
$company->setContactperson($profile);
104+
105+
$emailConfiguration = ['email' => '{{contactperson.email}}', 'name' => '{{contactperson.full_name'}}];
106+
$determiner = new RonRademaker\Mailer\Receiver\Determiner();
107+
$receiver = $determiner->getReceivers($company, null, $emailConfiguration);
108+
// results in ['email' => 'foobarz@example.com', 'name' => 'Foo Barz'];
109+
```
110+
NOTE: The determiner requires getters.
111+
112+
113+
Or just hardcoded settings:
114+
115+
``` php
116+
$emailConfiguration = ['email' => 'foobarz@example.com', 'name' => 'Foo Barz'];
117+
$determiner = new RonRademaker\Mailer\Receiver\Determiner();
118+
$receiver = $determiner->getReceivers($object, null, $emailConfiguration);
119+
// results in ['email' => 'foobarz@example.com', 'name' => 'Foo Barz'];
120+
```
121+

src/Receiver/Determiner.php

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<?php
2+
3+
namespace RonRademaker\Mailer\Receiver;
4+
5+
/**
6+
* The determiner class is used to determine the receivers of a confirmation.
7+
*
8+
* @author Jaap Romijn
9+
**/
10+
class Determiner implements DeterminerInterface
11+
{
12+
/**
13+
* An array holding known camelCase results.
14+
*
15+
* @var array
16+
*/
17+
private $camelCaseCache = array();
18+
19+
/**
20+
* The determiners to retrieve receivers.
21+
*
22+
* @var array<DeterminerInterface>
23+
**/
24+
protected $determiners = array();
25+
26+
/**
27+
* The fieldGetters is description.
28+
*
29+
* @var array<FieldGetterInterface>
30+
*/
31+
private $fieldGetters = [];
32+
33+
/**
34+
* Creates a new Determiner.
35+
*/
36+
public function __construct()
37+
{
38+
$this->addFieldGetter(new FieldGetter());
39+
}
40+
41+
/**
42+
* Getter for the fieldGetters.
43+
*
44+
* @return array<FieldGetterInterface>
45+
*/
46+
public function getFieldGetters()
47+
{
48+
return $this->fieldGetters;
49+
}
50+
51+
/**
52+
* Setter for the fieldGetters.
53+
*
54+
* @param array<FieldGetterInterface> fieldGetters
55+
*/
56+
public function setFieldGetters(array $fieldGetters)
57+
{
58+
$this->fieldGetters = $fieldGetters;
59+
60+
return $this;
61+
}
62+
63+
/**
64+
* Adds a field getter.
65+
*
66+
* @param FieldGetterInterface $fieldGetter
67+
*
68+
* @return Determiner
69+
*/
70+
public function addFieldGetter(FieldGetterInterface $fieldGetter)
71+
{
72+
array_unshift($this->fieldGetters, $fieldGetter);
73+
74+
return $this;
75+
}
76+
77+
/**
78+
* Removes a field getter.
79+
*
80+
* @param FieldGetterInterface $fieldGetter
81+
*
82+
* @return Determiner
83+
*/
84+
public function removeFieldGetter(FieldGetterInterface $fieldGetter)
85+
{
86+
$this->fieldGetters = array_filter($this->fieldGetters, function (FieldGetterInterface $compareFieldGetter) use ($fieldGetter) {
87+
return !($fieldGetter === $compareFieldGetter);
88+
});
89+
90+
return $this;
91+
}
92+
93+
/**
94+
* Returns the internal determiners.
95+
*
96+
* @param array $determiners<DeterminerInterface>
97+
**/
98+
protected function getDeterminers()
99+
{
100+
return $this->determiners;
101+
}
102+
103+
/**
104+
* Determiners to confirm for.
105+
*
106+
* @param array $determiners<DeterminerInterface>
107+
*
108+
* @return Determiner
109+
**/
110+
public function setDeterminers(array $determiners)
111+
{
112+
$this->determiners = $determiners;
113+
114+
return $this;
115+
}
116+
117+
/**
118+
* Adds a determiner to the collection of determiners, unless it is already set or adding would cause an endless loop.
119+
*
120+
* @param DeterminerInterface $determiner
121+
*
122+
* @return Determiner
123+
**/
124+
public function addDeterminer(DeterminerInterface $determiner)
125+
{
126+
if (in_array($determiner, $this->getDeterminers())) {
127+
array_unshift($this->determiners, $determiner);
128+
}
129+
130+
return $this;
131+
}
132+
133+
/**
134+
* Returns true if this determiner is a handler for the given object and event.
135+
*
136+
* @param stdClass $object
137+
* @param string $event
138+
*
139+
* @return bool
140+
**/
141+
protected function isHandler($object, $event)
142+
{
143+
return true;
144+
}
145+
146+
/**
147+
* Returns the handler for the given object and event.
148+
*
149+
* @param stdClass $object
150+
* @param string $event
151+
*
152+
* @return DeterminerInterface|null
153+
**/
154+
public function getHandler($object, $event)
155+
{
156+
foreach ($this->getDeterminers() as $internalDeterminer) {
157+
if (($determiner = $internalDeterminer->getHandler($object, $event)) instanceof DeterminerInterface) {
158+
return determiner;
159+
}
160+
}
161+
162+
if ($this->isHandler($object, $event)) {
163+
return $this;
164+
}
165+
}
166+
167+
/**
168+
* Returns a collection of receivers for the given object and event.
169+
*
170+
* @param stdClass $object
171+
* @param string $event
172+
* @param array $receivers
173+
*
174+
* @return array
175+
**/
176+
public function getReceivers($object, $event, array $receivers = array())
177+
{
178+
if (($determiner = $this->getHandler($object, $event)) instanceof DeterminerInterface) {
179+
if ($determiner !== $this) {
180+
return $determiner->getReceivers($object, $event, $receivers);
181+
}
182+
}
183+
184+
return $this->parseReceivers($object, $receivers);
185+
}
186+
187+
/**
188+
* Parses the receivers on the object if needed.
189+
*
190+
* @param stdClass $object
191+
* @param array $receivers
192+
*
193+
* @return array
194+
**/
195+
protected function parseReceivers($object, array $receivers)
196+
{
197+
$parsedReceivers = array();
198+
foreach ($receivers as $field => $value) {
199+
$parsedReceivers[$this->parseReceiverValue($object, $field)] = $this->parseReceiverValue($object, $value);
200+
}
201+
202+
return array_filter($parsedReceivers);
203+
}
204+
205+
/**
206+
* Parses the receivers on the object if needed.
207+
*
208+
* @param stdClass $object
209+
* @param string $value
210+
*
211+
* @return array
212+
**/
213+
protected function parseReceiverValue($object, $value)
214+
{
215+
if (preg_match('/^{{.*}}$/', $value)) {
216+
$chainValue = $object;
217+
foreach (array_map(function ($v) { return 'get'.$this->camelCase($v); }, explode('.', str_replace(array('}', '{'), '', $value))) as $getter) {
218+
if (is_object($chainValue)) {
219+
$chainValue = $this->retrievePossibleObjectValue($chainValue, $getter);
220+
}
221+
}
222+
223+
return $chainValue;
224+
}
225+
226+
return $value;
227+
}
228+
229+
/**
230+
* Retrieves a value from an object, but sometimes the getter refers to an object and other functions are needed to retreive that actual object.
231+
*
232+
* @param stdClass $object
233+
* @param string $getter
234+
*
235+
* @return mixed
236+
**/
237+
protected function retrievePossibleObjectValue($object, $getter)
238+
{
239+
foreach ($this->getFieldGetters() as $fieldGetter) {
240+
if ($fieldGetter->handles($object, $getter) && false !== ($value = $fieldGetter->retrieveValue($object, $getter))) {
241+
return $fieldGetter->retrieveValue($object, $getter);
242+
}
243+
}
244+
}
245+
246+
/**
247+
* CamelCase function (This_is_a_string -> ThisIsAString; this_is_a_string -> ThisIsAString).
248+
*
249+
* @param string $string
250+
*
251+
* @return string
252+
*/
253+
public function camelCase($string)
254+
{
255+
if (array_key_exists($string, $this->camelCaseCache)) {
256+
return $this->camelCaseCache[$string];
257+
}
258+
259+
$result = '';
260+
foreach (explode('_', $string) as $substring) {
261+
$result .= ucfirst($substring);
262+
}
263+
264+
$this->camelCaseCache[$string] = $result;
265+
266+
return $result;
267+
}
268+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace RonRademaker\Mailer\Receiver;
4+
5+
/**
6+
* The determiner interface describes the interface used to determine the receivers of a confirmation.
7+
*
8+
* @author Jaap Romijn
9+
**/
10+
interface DeterminerInterface
11+
{
12+
/**
13+
* Returns a collection of receivers for the given object and event.
14+
*
15+
* @param stdClass $object
16+
* @param string $event
17+
* @param array $receivers
18+
*
19+
* @return array
20+
**/
21+
public function getReceivers($object, $event, array $receivers = array());
22+
23+
/**
24+
* Returns the handler for the given object and event.
25+
*
26+
* @param stdClass $object
27+
* @param string $event
28+
*
29+
* @return DeterminerInterface
30+
**/
31+
public function getHandler($object, $event);
32+
}

src/Receiver/FieldGetter.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace RonRademaker\Mailer\Receiver;
4+
5+
/**
6+
* The determiner class is used to determine the receivers of a confirmation.
7+
*
8+
* @author Jaap Romijn
9+
**/
10+
class FieldGetter implements FieldGetterInterface
11+
{
12+
/**
13+
* Returns true if this getter supports this field/object.
14+
*
15+
* @param mixed $object
16+
* @param string $getter
17+
*
18+
* @return bool
19+
*/
20+
public function handles($object, $getter)
21+
{
22+
return true;
23+
}
24+
25+
/**
26+
* Retrieves a value from an object, but sometimes the getter refers to an object and other functions are needed to retreive that actual object.
27+
*
28+
* @param stdClass $object
29+
* @param string $getter
30+
*
31+
* @return mixed
32+
**/
33+
public function retrieveValue($object, $getter)
34+
{
35+
return $object->{$getter}();
36+
}
37+
}

0 commit comments

Comments
 (0)