Skip to content

Commit 84e0fe6

Browse files
authored
Merge pull request #43 from ConvertKit/sequence-functions
Update `add_subscriber_to_sequence()` to support name, custom fields and tags
2 parents 3cc8333 + 663f84f commit 84e0fe6

File tree

2 files changed

+200
-80
lines changed

2 files changed

+200
-80
lines changed

src/ConvertKit_API.php

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ public function get_form_subscriptions(
206206
/**
207207
* Gets all sequences
208208
*
209+
* @see https://developers.convertkit.com/#list-sequences
210+
*
209211
* @return false|mixed
210212
*/
211213
public function get_sequences()
@@ -219,39 +221,73 @@ public function get_sequences()
219221
}
220222

221223
/**
222-
* Gets subscribers to a sequence
224+
* Adds a subscriber to a sequence by email address
223225
*
224-
* @param integer $sequence_id Sequence ID.
225-
* @param string $sort_order Sort Order (asc|desc).
226+
* @param integer $sequence_id Sequence ID.
227+
* @param string $email Email Address.
228+
* @param string $first_name First Name.
229+
* @param array<string, string> $fields Custom Fields.
230+
* @param array<string, int> $tag_ids Tag ID(s) to subscribe to.
231+
*
232+
* @see https://developers.convertkit.com/#add-subscriber-to-a-sequence
226233
*
227234
* @return false|mixed
228235
*/
229-
public function get_sequence_subscriptions(int $sequence_id, string $sort_order = 'asc')
230-
{
231-
return $this->get(
232-
sprintf('sequences/%s/subscriptions', $sequence_id),
233-
[
234-
'api_secret' => $this->api_secret,
235-
'sort_order' => $sort_order,
236-
]
236+
public function add_subscriber_to_sequence(
237+
int $sequence_id,
238+
string $email,
239+
string $first_name = '',
240+
array $fields = [],
241+
array $tag_ids = []
242+
) {
243+
// Build parameters.
244+
$options = [
245+
'api_key' => $this->api_key,
246+
'email' => $email,
247+
];
248+
249+
if (!empty($first_name)) {
250+
$options['first_name'] = $first_name;
251+
}
252+
if (!empty($fields)) {
253+
$options['fields'] = $fields;
254+
}
255+
if (!empty($tag_ids)) {
256+
$options['tags'] = $tag_ids;
257+
}
258+
259+
// Send request.
260+
return $this->post(
261+
sprintf('sequences/%s/subscribe', $sequence_id),
262+
$options
237263
);
238264
}
239265

240266
/**
241-
* Adds a subscriber to a sequence by email address
267+
* Gets subscribers to a sequence
268+
*
269+
* @param integer $sequence_id Sequence ID.
270+
* @param string $sort_order Sort Order (asc|desc).
271+
* @param string $subscriber_state Subscriber State (active,cancelled).
272+
* @param integer $page Page.
242273
*
243-
* @param integer $sequence_id Sequence ID.
244-
* @param string $email Email Address.
274+
* @see https://developers.convertkit.com/#list-subscriptions-to-a-sequence
245275
*
246276
* @return false|mixed
247277
*/
248-
public function add_subscriber_to_sequence(int $sequence_id, string $email)
249-
{
250-
return $this->post(
251-
sprintf('courses/%s/subscribe', $sequence_id),
278+
public function get_sequence_subscriptions(
279+
int $sequence_id,
280+
string $sort_order = 'asc',
281+
string $subscriber_state = 'active',
282+
int $page = 1
283+
) {
284+
return $this->get(
285+
sprintf('sequences/%s/subscriptions', $sequence_id),
252286
[
253-
'api_key' => $this->api_key,
254-
'email' => $email,
287+
'api_secret' => $this->api_secret,
288+
'sort_order' => $sort_order,
289+
'subscriber_state' => $subscriber_state,
290+
'page' => $page,
255291
]
256292
);
257293
}
@@ -747,8 +783,8 @@ private function strip_html_head_body_tags(string $markup)
747783
/**
748784
* Performs a GET request to the API.
749785
*
750-
* @param string $endpoint API Endpoint.
751-
* @param array<string, int|string> $args Request arguments.
786+
* @param string $endpoint API Endpoint.
787+
* @param array<string, int|string|array<string, int|string>|string> $args Request arguments.
752788
*
753789
* @throws \InvalidArgumentException If the provided arguments are not of the expected type.
754790
*
@@ -766,8 +802,8 @@ public function get(string $endpoint, array $args = [])
766802
/**
767803
* Performs a POST request to the API.
768804
*
769-
* @param string $endpoint API Endpoint.
770-
* @param array<string, int|string> $args Request arguments.
805+
* @param string $endpoint API Endpoint.
806+
* @param array<string, int|string|array<string, int|string>|string> $args Request arguments.
771807
*
772808
* @throws \InvalidArgumentException If the provided arguments are not of the expected type.
773809
*
@@ -785,8 +821,8 @@ public function post(string $endpoint, array $args = [])
785821
/**
786822
* Performs a PUT request to the API.
787823
*
788-
* @param string $endpoint API Endpoint.
789-
* @param array<string, int|string> $args Request arguments.
824+
* @param string $endpoint API Endpoint.
825+
* @param array<string, int|string|array<string, int|string>|string> $args Request arguments.
790826
*
791827
* @throws \InvalidArgumentException If the provided arguments are not of the expected type.
792828
*
@@ -804,8 +840,8 @@ public function put(string $endpoint, array $args = [])
804840
/**
805841
* Performs a DELETE request to the API.
806842
*
807-
* @param string $endpoint API Endpoint.
808-
* @param array<string, int|string> $args Request arguments.
843+
* @param string $endpoint API Endpoint.
844+
* @param array<string, int|string|array<string, int|string>|string> $args Request arguments.
809845
*
810846
* @throws \InvalidArgumentException If the provided arguments are not of the expected type.
811847
*
@@ -823,9 +859,9 @@ public function delete(string $endpoint, array $args = [])
823859
/**
824860
* Performs an API request using Guzzle.
825861
*
826-
* @param string $endpoint API Endpoint.
827-
* @param string $method Request method (POST, GET, PUT, PATCH, DELETE).
828-
* @param array<string, int|string> $args Request arguments.
862+
* @param string $endpoint API Endpoint.
863+
* @param string $method Request method.
864+
* @param array<string, int|string|array<string, int|string>|string> $args Request arguments.
829865
*
830866
* @throws \InvalidArgumentException If the provided arguments are not of the expected type.
831867
* @throws \Exception If JSON encoding arguments failed.

tests/ConvertKitAPITest.php

Lines changed: 133 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,135 @@ public function testGetSequences()
248248
$this->assertArrayHasKey('created_at', $sequence);
249249
}
250250

251+
/**
252+
* Test that add_subscriber_to_sequence() returns the expected data.
253+
*
254+
* @since 1.0.0
255+
*
256+
* @return void
257+
*/
258+
public function testAddSubscriberToSequence()
259+
{
260+
$result = $this->api->add_subscriber_to_sequence(
261+
$_ENV['CONVERTKIT_API_SEQUENCE_ID'],
262+
$this->generateEmailAddress()
263+
);
264+
$this->assertInstanceOf('stdClass', $result);
265+
$this->assertArrayHasKey('subscription', get_object_vars($result));
266+
}
267+
268+
/**
269+
* Test that add_subscriber_to_sequence() throws a ClientException when an invalid
270+
* sequence is specified.
271+
*
272+
* @since 1.0.0
273+
*
274+
* @return void
275+
*/
276+
public function testAddSubscriberToSequenceWithInvalidSequenceID()
277+
{
278+
$this->expectException(GuzzleHttp\Exception\ClientException::class);
279+
$result = $this->api->add_subscriber_to_sequence(12345, $this->generateEmailAddress());
280+
}
281+
282+
/**
283+
* Test that add_subscriber_to_sequence() throws a ClientException when an invalid
284+
* email address is specified.
285+
*
286+
* @since 1.0.0
287+
*
288+
* @return void
289+
*/
290+
public function testAddSubscriberToSequenceWithInvalidEmailAddress()
291+
{
292+
$this->expectException(GuzzleHttp\Exception\ClientException::class);
293+
$result = $this->api->add_subscriber_to_sequence($_ENV['CONVERTKIT_API_SEQUENCE_ID'], 'not-an-email-address');
294+
}
295+
296+
/**
297+
* Test that add_subscriber_to_sequence() returns the expected data
298+
* when a first_name parameter is included.
299+
*
300+
* @since 1.0.0
301+
*
302+
* @return void
303+
*/
304+
public function testAddSubscriberToSequenceWithFirstName()
305+
{
306+
$emailAddress = $this->generateEmailAddress();
307+
$firstName = 'First Name';
308+
$result = $this->api->add_subscriber_to_sequence(
309+
$_ENV['CONVERTKIT_API_SEQUENCE_ID'],
310+
$emailAddress,
311+
$firstName
312+
);
313+
314+
$this->assertInstanceOf('stdClass', $result);
315+
$this->assertArrayHasKey('subscription', get_object_vars($result));
316+
317+
// Fetch subscriber from API to confirm the first name was saved.
318+
$subscriber = $this->api->get_subscriber($result->subscription->subscriber->id);
319+
$this->assertEquals($subscriber->subscriber->email_address, $emailAddress);
320+
$this->assertEquals($subscriber->subscriber->first_name, $firstName);
321+
}
322+
323+
/**
324+
* Test that add_subscriber_to_sequence() returns the expected data
325+
* when custom field data is included.
326+
*
327+
* @since 1.0.0
328+
*
329+
* @return void
330+
*/
331+
public function testAddSubscriberToSequenceWithCustomFields()
332+
{
333+
$result = $this->api->add_subscriber_to_sequence(
334+
$_ENV['CONVERTKIT_API_SEQUENCE_ID'],
335+
$this->generateEmailAddress(),
336+
'First Name',
337+
[
338+
'last_name' => 'Last Name',
339+
]
340+
);
341+
342+
// Check subscription object returned.
343+
$this->assertInstanceOf('stdClass', $result);
344+
$this->assertArrayHasKey('subscription', get_object_vars($result));
345+
346+
// Fetch subscriber from API to confirm the custom fields were saved.
347+
$subscriber = $this->api->get_subscriber($result->subscription->subscriber->id);
348+
$this->assertEquals($subscriber->subscriber->fields->last_name, 'Last Name');
349+
}
350+
351+
/**
352+
* Test that add_subscriber_to_sequence() returns the expected data
353+
* when custom field data is included.
354+
*
355+
* @since 1.0.0
356+
*
357+
* @return void
358+
*/
359+
public function testAddSubscriberToSequenceWithTagID()
360+
{
361+
$result = $this->api->add_subscriber_to_sequence(
362+
$_ENV['CONVERTKIT_API_SEQUENCE_ID'],
363+
$this->generateEmailAddress(),
364+
'First Name',
365+
[],
366+
[
367+
(int) $_ENV['CONVERTKIT_API_TAG_ID']
368+
]
369+
);
370+
371+
// Check subscription object returned.
372+
$this->assertInstanceOf('stdClass', $result);
373+
$this->assertArrayHasKey('subscription', get_object_vars($result));
374+
375+
// Fetch subscriber tags from API to confirm the tag saved.
376+
$subscriberTags = $this->api->get_subscriber_tags($result->subscription->subscriber->id);
377+
$this->assertEquals($subscriberTags->tags[0]->id, $_ENV['CONVERTKIT_API_TAG_ID']);
378+
}
379+
251380
/**
252381
* Test that get_sequence_subscriptions() returns the expected data.
253382
*
@@ -305,20 +434,6 @@ public function testGetSequenceSubscriptionsWithDescSortOrder()
305434
);
306435
}
307436

308-
/**
309-
* Test that get_sequence_subscriptions() throws a ClientException when an invalid
310-
* sequence ID is specified.
311-
*
312-
* @since 1.0.0
313-
*
314-
* @return void
315-
*/
316-
public function testGetSequenceSubscriptionsWithInvalidSequenceID()
317-
{
318-
$this->expectException(GuzzleHttp\Exception\ClientException::class);
319-
$result = $this->api->get_sequence_subscriptions(12345);
320-
}
321-
322437
/**
323438
* Test that get_sequence_subscriptions() throws a ClientException when an invalid
324439
* sort order is specified.
@@ -334,48 +449,17 @@ public function testGetSequenceSubscriptionsWithInvalidSortOrder()
334449
}
335450

336451
/**
337-
* Test that add_subscriber_to_sequence() returns the expected data.
338-
*
339-
* @since 1.0.0
340-
*
341-
* @return void
342-
*/
343-
public function testAddSubscriberToSequence()
344-
{
345-
$result = $this->api->add_subscriber_to_sequence(
346-
$_ENV['CONVERTKIT_API_SEQUENCE_ID'],
347-
$this->generateEmailAddress()
348-
);
349-
$this->assertInstanceOf('stdClass', $result);
350-
$this->assertArrayHasKey('subscription', get_object_vars($result));
351-
}
352-
353-
/**
354-
* Test that add_subscriber_to_sequence() throws a ClientException when an invalid
355-
* sequence is specified.
356-
*
357-
* @since 1.0.0
358-
*
359-
* @return void
360-
*/
361-
public function testAddSubscriberToSequenceWithInvalidSequenceID()
362-
{
363-
$this->expectException(GuzzleHttp\Exception\ClientException::class);
364-
$result = $this->api->add_subscriber_to_sequence(12345, $this->generateEmailAddress());
365-
}
366-
367-
/**
368-
* Test that add_subscriber_to_sequence() throws a ClientException when an invalid
369-
* email address is specified.
452+
* Test that get_sequence_subscriptions() throws a ClientException when an invalid
453+
* sequence ID is specified.
370454
*
371455
* @since 1.0.0
372456
*
373457
* @return void
374458
*/
375-
public function testAddSubscriberToSequenceWithInvalidEmailAddress()
459+
public function testGetSequenceSubscriptionsWithInvalidSequenceID()
376460
{
377461
$this->expectException(GuzzleHttp\Exception\ClientException::class);
378-
$result = $this->api->add_subscriber_to_sequence($_ENV['CONVERTKIT_API_SEQUENCE_ID'], 'not-an-email-address');
462+
$result = $this->api->get_sequence_subscriptions(12345);
379463
}
380464

381465
/**

0 commit comments

Comments
 (0)