Skip to content

Commit 2b8ea3f

Browse files
authored
Adds ParseAudience (#372)
* updated ParseQuery::_setConditions * Adds ParseAudience * Handle registering and testing for new ParseAudience class * Modify test for push status to reflect change in _setConditions * updated README * lint * typo * test uncovered paths
1 parent f72cc45 commit 2b8ea3f

8 files changed

+360
-7
lines changed

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ from your PHP app or script. Designed to work with the self-hosted Parse Server
3030
- [Push Notifications](#push)
3131
- [Push to Channels](#push-to-channels)
3232
- [Push with Query](#push-with-query)
33+
- [Push with Audience](#push-with-audience)
3334
- [Push Status](#push-status)
3435
- [Server Info](#server-info)
3536
- [Version](#version)
@@ -216,6 +217,7 @@ use Parse\ParseClient;
216217
use Parse\ParsePushStatus;
217218
use Parse\ParseServerInfo;
218219
use Parse\ParseLogs;
220+
use Parse\ParseAudience;
219221
```
220222

221223
### Parse Objects
@@ -428,6 +430,42 @@ ParsePush::send(array(
428430
), true);
429431
```
430432

433+
#### Push with Audience
434+
435+
If you want to keep track of your sends when using queries you can use the `ParseAudience` class.
436+
You can create and configure your Audience objects with a name and query.
437+
When you indicate it's being used in a push the `lastUsed` and `timesUsed` values are updated for you.
438+
```php
439+
$iosQuery = ParseInstallation::getQuery();
440+
$iosQuery->equalTo("deviceType", "ios");
441+
442+
// create & save your audience
443+
$audience = ParseAudience::createAudience(
444+
'MyiOSAudience',
445+
$iosQuery
446+
);
447+
$audience->save(true);
448+
449+
// send a push using the query in this audience and it's id
450+
// The 'audience_id' is what allows parse to update 'lastUsed' and 'timesUsed'
451+
// You could use any audience_id with any query and it will still update that audience
452+
ParsePush::send([
453+
'data' => [
454+
'alert' => 'hello ios users!'
455+
],
456+
'where' => $audience->getQuery(),
457+
'audience_id' => $audience->getObjectId()
458+
], true);
459+
460+
// fetch changes to this audience
461+
$audience->fetch(true);
462+
463+
// get last & times used for tracking
464+
$timesUsed = $audience->getTimesUsed();
465+
$lastUsed = $audience->getLastUsed();
466+
```
467+
Audiences provide you with a convenient way to group your queries and keep track of how often and when you send to them.
468+
431469
#### Push Status
432470

433471
If your server supports it you can extract and check the current status of your pushes.

src/Parse/ParseAudience.php

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
/**
3+
* Class ParseAudience | Parse/ParseAudience.php
4+
*/
5+
6+
namespace Parse;
7+
8+
/**
9+
* Class ParseAudience - Representation of Audience for tracking and sending push notifications
10+
*
11+
* @author Ben Friedman <[email protected]>
12+
* @package Parse
13+
*/
14+
class ParseAudience extends ParseObject
15+
{
16+
/**
17+
* Parse Class name
18+
*
19+
* @var string
20+
*/
21+
public static $parseClassName = '_Audience';
22+
23+
/**
24+
* Create a new audience with name & query
25+
*
26+
* @param string $name Name of the audience to create
27+
* @param ParseQuery $query Query to create audience with
28+
* @return ParseAudience
29+
*/
30+
public static function createAudience($name, $query)
31+
{
32+
$audience = new ParseAudience();
33+
$audience->setName($name);
34+
$audience->setQuery($query);
35+
return $audience;
36+
}
37+
38+
/**
39+
* Sets the name of this audience
40+
*
41+
* @param string $name Name to set
42+
*/
43+
public function setName($name)
44+
{
45+
$this->set('name', $name);
46+
}
47+
48+
/**
49+
* Gets the name for this audience
50+
*
51+
* @return string
52+
*/
53+
public function getName()
54+
{
55+
return $this->get('name');
56+
}
57+
58+
/**
59+
* Sets the query for this Audience
60+
*
61+
* @param ParseQuery $query Query for this Audience
62+
*/
63+
public function setQuery($query)
64+
{
65+
$this->set('query', json_encode($query->_getOptions()));
66+
}
67+
68+
/**
69+
* Gets the query for this Audience
70+
*
71+
* @return ParseQuery
72+
*/
73+
public function getQuery()
74+
{
75+
$query = new ParseQuery('_Installation');
76+
$query->_setConditions(json_decode($this->get('query'), true));
77+
return $query;
78+
}
79+
80+
/**
81+
* Gets when this Audience was last used
82+
*
83+
* @return \DateTime|null
84+
*/
85+
public function getLastUsed()
86+
{
87+
return $this->get('lastUsed');
88+
}
89+
90+
/**
91+
* Gets the times this Audience has been used
92+
*
93+
* @return int
94+
*/
95+
public function getTimesUsed()
96+
{
97+
return $this->get('timesUsed');
98+
}
99+
}

src/Parse/ParseClient.php

+4
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ public static function initialize(
151151
ParsePushStatus::registerSubclass();
152152
}
153153

154+
if (!ParseObject::hasRegisteredSubclass('_Audience')) {
155+
ParseAudience::registerSubclass();
156+
}
157+
154158
ParseSession::registerSubclass();
155159
self::$applicationId = $app_id;
156160
self::$restKey = $rest_key;

src/Parse/ParsePushStatus.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ public function getPushQuery()
7575
$query = new ParseQuery(self::$parseClassName);
7676

7777
// set the conditions
78-
$query->_setConditions($queryConditions);
78+
$query->_setConditions([
79+
'where' => $queryConditions
80+
]);
7981

8082
return $query;
8183
}

src/Parse/ParseQuery.php

+34-2
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,40 @@ public function _setConditions($conditions)
152152

153153
// iterate over and add each condition
154154
foreach ($conditions as $key => $entry) {
155-
foreach ($entry as $condition => $value) {
156-
$this->addCondition($key, $condition, $value);
155+
switch ($key) {
156+
case 'where':
157+
$this->where = $entry;
158+
break;
159+
160+
case 'include':
161+
$this->includes = explode(',', $entry);
162+
break;
163+
164+
case 'keys':
165+
$this->selectedKeys = explode(',', $entry);
166+
break;
167+
168+
case 'limit':
169+
$this->limit = $entry;
170+
break;
171+
172+
// skip
173+
case 'skip':
174+
$this->skip = $entry;
175+
break;
176+
177+
// orderBy
178+
case 'order':
179+
$this->orderBy = explode(',', $entry);
180+
break;
181+
182+
// whether this query is for count or not
183+
case 'count':
184+
$this->count = $entry;
185+
break;
186+
187+
default:
188+
throw new ParseException("Unknown condition to set '{$key}''");
157189
}
158190
}
159191
}

tests/Parse/ParseAudienceTest.php

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
namespace Parse\Test;
4+
5+
use Parse\ParseAudience;
6+
use Parse\ParseInstallation;
7+
use Parse\ParseObject;
8+
use Parse\ParsePush;
9+
use Parse\ParseQuery;
10+
11+
class ParseAudienceTest extends \PHPUnit_Framework_TestCase
12+
{
13+
public function setUp()
14+
{
15+
Helper::clearClass('_Audience');
16+
Helper::clearClass('_Installation');
17+
}
18+
19+
public function createInstallations()
20+
{
21+
$androidInstallation = new ParseInstallation();
22+
$androidInstallation->set('installationId', 'id1');
23+
$androidInstallation->set('deviceToken', '12345');
24+
$androidInstallation->set('deviceType', 'android');
25+
$androidInstallation->save(true);
26+
27+
$iOSInstallation = new ParseInstallation();
28+
$iOSInstallation->set('installationId', 'id2');
29+
$iOSInstallation->set('deviceToken', '54321');
30+
$iOSInstallation->set('deviceType', 'ios');
31+
$iOSInstallation->save();
32+
33+
ParseObject::saveAll([
34+
$androidInstallation,
35+
$iOSInstallation
36+
]);
37+
}
38+
39+
/**
40+
* @group audience-tests
41+
*/
42+
public function testPushAudiences()
43+
{
44+
$this->createInstallations();
45+
46+
$androidQuery = ParseInstallation::query()
47+
->equalTo('deviceType', 'android');
48+
49+
$audience = ParseAudience::createAudience('MyAudience', $androidQuery);
50+
$audience->save();
51+
52+
// count no master should be 0
53+
$query = new ParseQuery('_Audience');
54+
$this->assertEquals(0, $query->count(), 'No master was not 0');
55+
56+
$query = new ParseQuery('_Audience');
57+
$audience = $query->first(true);
58+
$this->assertNotNull($audience);
59+
60+
$this->assertEquals('MyAudience', $audience->getName());
61+
$this->assertEquals($androidQuery, $audience->getQuery());
62+
$this->assertNull($audience->getLastUsed());
63+
$this->assertEquals(0, $audience->getTimesUsed());
64+
}
65+
66+
/**
67+
* @group audience-tests
68+
*/
69+
public function testSaveWithoutMaster()
70+
{
71+
$query = ParseAudience::query();
72+
$this->assertEquals(0, $query->count(true), 'Did not start at 0');
73+
74+
$audience = ParseAudience::createAudience(
75+
'MyAudience',
76+
ParseInstallation::query()
77+
->equalTo('deviceType', 'android')
78+
);
79+
$audience->save();
80+
81+
$query = ParseAudience::query();
82+
$this->assertEquals(1, $query->count(true), 'Did not end at 1');
83+
}
84+
85+
/**
86+
* @group audience-tests
87+
*/
88+
public function testPushWithAudience()
89+
{
90+
$this->createInstallations();
91+
92+
$audience = ParseAudience::createAudience(
93+
'MyAudience',
94+
ParseInstallation::query()
95+
->equalTo('deviceType', 'android')
96+
);
97+
$audience->save(true);
98+
99+
ParsePush::send([
100+
'data' => [
101+
'alert' => 'sample message'
102+
],
103+
'where' => $audience->getQuery(),
104+
'audience_id' => $audience->getObjectId()
105+
], true);
106+
107+
$audience->fetch(true);
108+
109+
$this->assertEquals(1, $audience->getTimesUsed());
110+
$this->assertNotNull($audience->getLastUsed());
111+
}
112+
}

tests/Parse/ParseObjectTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Parse\Internal\SetOperation;
88
use Parse\ParseACL;
99
use Parse\ParseAggregateException;
10+
use Parse\ParseAudience;
1011
use Parse\ParseClient;
1112
use Parse\ParseException;
1213
use Parse\ParseFile;
@@ -1077,6 +1078,7 @@ public function testNoRegisteredSubclasses()
10771078
ParseInstallation::_unregisterSubclass();
10781079
ParseSession::_unregisterSubclass();
10791080
ParsePushStatus::_unregisterSubclass();
1081+
ParseAudience::_unregisterSubclass();
10801082

10811083
new ParseObject('TestClass');
10821084
}

0 commit comments

Comments
 (0)