Skip to content

Adds ParseAudience #372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ from your PHP app or script. Designed to work with the self-hosted Parse Server
- [Push Notifications](#push)
- [Push to Channels](#push-to-channels)
- [Push with Query](#push-with-query)
- [Push with Audience](#push-with-audience)
- [Push Status](#push-status)
- [Server Info](#server-info)
- [Version](#version)
Expand Down Expand Up @@ -216,6 +217,7 @@ use Parse\ParseClient;
use Parse\ParsePushStatus;
use Parse\ParseServerInfo;
use Parse\ParseLogs;
use Parse\ParseAudience;
```

### Parse Objects
Expand Down Expand Up @@ -428,6 +430,42 @@ ParsePush::send(array(
), true);
```

#### Push with Audience

If you want to keep track of your sends when using queries you can use the `ParseAudience` class.
You can create and configure your Audience objects with a name and query.
When you indicate it's being used in a push the `lastUsed` and `timesUsed` values are updated for you.
```php
$iosQuery = ParseInstallation::getQuery();
$iosQuery->equalTo("deviceType", "ios");

// create & save your audience
$audience = ParseAudience::createAudience(
'MyiOSAudience',
$iosQuery
);
$audience->save(true);

// send a push using the query in this audience and it's id
// The 'audience_id' is what allows parse to update 'lastUsed' and 'timesUsed'
// You could use any audience_id with any query and it will still update that audience
ParsePush::send([
'data' => [
'alert' => 'hello ios users!'
],
'where' => $audience->getQuery(),
'audience_id' => $audience->getObjectId()
], true);

// fetch changes to this audience
$audience->fetch(true);

// get last & times used for tracking
$timesUsed = $audience->getTimesUsed();
$lastUsed = $audience->getLastUsed();
```
Audiences provide you with a convenient way to group your queries and keep track of how often and when you send to them.

#### Push Status

If your server supports it you can extract and check the current status of your pushes.
Expand Down
99 changes: 99 additions & 0 deletions src/Parse/ParseAudience.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
/**
* Class ParseAudience | Parse/ParseAudience.php
*/

namespace Parse;

/**
* Class ParseAudience - Representation of Audience for tracking and sending push notifications
*
* @author Ben Friedman <friedman.benjamin@gmail.com>
* @package Parse
*/
class ParseAudience extends ParseObject
{
/**
* Parse Class name
*
* @var string
*/
public static $parseClassName = '_Audience';

/**
* Create a new audience with name & query
*
* @param string $name Name of the audience to create
* @param ParseQuery $query Query to create audience with
* @return ParseAudience
*/
public static function createAudience($name, $query)
{
$audience = new ParseAudience();
$audience->setName($name);
$audience->setQuery($query);
return $audience;
}

/**
* Sets the name of this audience
*
* @param string $name Name to set
*/
public function setName($name)
{
$this->set('name', $name);
}

/**
* Gets the name for this audience
*
* @return string
*/
public function getName()
{
return $this->get('name');
}

/**
* Sets the query for this Audience
*
* @param ParseQuery $query Query for this Audience
*/
public function setQuery($query)
{
$this->set('query', json_encode($query->_getOptions()));
}

/**
* Gets the query for this Audience
*
* @return ParseQuery
*/
public function getQuery()
{
$query = new ParseQuery('_Installation');
$query->_setConditions(json_decode($this->get('query'), true));
return $query;
}

/**
* Gets when this Audience was last used
*
* @return \DateTime|null
*/
public function getLastUsed()
{
return $this->get('lastUsed');
}

/**
* Gets the times this Audience has been used
*
* @return int
*/
public function getTimesUsed()
{
return $this->get('timesUsed');
}
}
4 changes: 4 additions & 0 deletions src/Parse/ParseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ public static function initialize(
ParsePushStatus::registerSubclass();
}

if (!ParseObject::hasRegisteredSubclass('_Audience')) {
ParseAudience::registerSubclass();
}

ParseSession::registerSubclass();
self::$applicationId = $app_id;
self::$restKey = $rest_key;
Expand Down
4 changes: 3 additions & 1 deletion src/Parse/ParsePushStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ public function getPushQuery()
$query = new ParseQuery(self::$parseClassName);

// set the conditions
$query->_setConditions($queryConditions);
$query->_setConditions([
'where' => $queryConditions
]);

return $query;
}
Expand Down
36 changes: 34 additions & 2 deletions src/Parse/ParseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,40 @@ public function _setConditions($conditions)

// iterate over and add each condition
foreach ($conditions as $key => $entry) {
foreach ($entry as $condition => $value) {
$this->addCondition($key, $condition, $value);
switch ($key) {
case 'where':
$this->where = $entry;
break;

case 'include':
$this->includes = explode(',', $entry);
break;

case 'keys':
$this->selectedKeys = explode(',', $entry);
break;

case 'limit':
$this->limit = $entry;
break;

// skip
case 'skip':
$this->skip = $entry;
break;

// orderBy
case 'order':
$this->orderBy = explode(',', $entry);
break;

// whether this query is for count or not
case 'count':
$this->count = $entry;
break;

default:
throw new ParseException("Unknown condition to set '{$key}''");
}
}
}
Expand Down
112 changes: 112 additions & 0 deletions tests/Parse/ParseAudienceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

namespace Parse\Test;

use Parse\ParseAudience;
use Parse\ParseInstallation;
use Parse\ParseObject;
use Parse\ParsePush;
use Parse\ParseQuery;

class ParseAudienceTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Helper::clearClass('_Audience');
Helper::clearClass('_Installation');
}

public function createInstallations()
{
$androidInstallation = new ParseInstallation();
$androidInstallation->set('installationId', 'id1');
$androidInstallation->set('deviceToken', '12345');
$androidInstallation->set('deviceType', 'android');
$androidInstallation->save(true);

$iOSInstallation = new ParseInstallation();
$iOSInstallation->set('installationId', 'id2');
$iOSInstallation->set('deviceToken', '54321');
$iOSInstallation->set('deviceType', 'ios');
$iOSInstallation->save();

ParseObject::saveAll([
$androidInstallation,
$iOSInstallation
]);
}

/**
* @group audience-tests
*/
public function testPushAudiences()
{
$this->createInstallations();

$androidQuery = ParseInstallation::query()
->equalTo('deviceType', 'android');

$audience = ParseAudience::createAudience('MyAudience', $androidQuery);
$audience->save();

// count no master should be 0
$query = new ParseQuery('_Audience');
$this->assertEquals(0, $query->count(), 'No master was not 0');

$query = new ParseQuery('_Audience');
$audience = $query->first(true);
$this->assertNotNull($audience);

$this->assertEquals('MyAudience', $audience->getName());
$this->assertEquals($androidQuery, $audience->getQuery());
$this->assertNull($audience->getLastUsed());
$this->assertEquals(0, $audience->getTimesUsed());
}

/**
* @group audience-tests
*/
public function testSaveWithoutMaster()
{
$query = ParseAudience::query();
$this->assertEquals(0, $query->count(true), 'Did not start at 0');

$audience = ParseAudience::createAudience(
'MyAudience',
ParseInstallation::query()
->equalTo('deviceType', 'android')
);
$audience->save();

$query = ParseAudience::query();
$this->assertEquals(1, $query->count(true), 'Did not end at 1');
}

/**
* @group audience-tests
*/
public function testPushWithAudience()
{
$this->createInstallations();

$audience = ParseAudience::createAudience(
'MyAudience',
ParseInstallation::query()
->equalTo('deviceType', 'android')
);
$audience->save(true);

ParsePush::send([
'data' => [
'alert' => 'sample message'
],
'where' => $audience->getQuery(),
'audience_id' => $audience->getObjectId()
], true);

$audience->fetch(true);

$this->assertEquals(1, $audience->getTimesUsed());
$this->assertNotNull($audience->getLastUsed());
}
}
2 changes: 2 additions & 0 deletions tests/Parse/ParseObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Parse\Internal\SetOperation;
use Parse\ParseACL;
use Parse\ParseAggregateException;
use Parse\ParseAudience;
use Parse\ParseClient;
use Parse\ParseException;
use Parse\ParseFile;
Expand Down Expand Up @@ -1077,6 +1078,7 @@ public function testNoRegisteredSubclasses()
ParseInstallation::_unregisterSubclass();
ParseSession::_unregisterSubclass();
ParsePushStatus::_unregisterSubclass();
ParseAudience::_unregisterSubclass();

new ParseObject('TestClass');
}
Expand Down
Loading