Mailer - Audiences
Basics
An Audience represents a subset of Users that that remain after the query has been modified by Conditions (combinations of Operands (the thing to test against) and Operators (the way the test is made) against data (the value to test with)).
An Audience with NO Conditions will therefore return all Users.
Operands
Operand definitions are used to specifiy both the fields and relationships the AudienceBuilder can create audiences from.
By Default, the audience operands list is limited to Users' Username and Email, when the User record was created (Created) and if they have specific roles (User has Roles).
You can add your own Operands by extending the BaseOperand and filling in protected properties. For example, to create an Operand Definition for a User's postcode (stored on the users table), you might make a new file with:
use Yadda\Enso\Mailer\Handlers\Operands\BaseOperand;
class AddressPostcode extends BaseOperand
{
/**
* Allowed operators for this Operand.
*
* @var array
*/
protected $allowed_operators = [
'string_matches' => 'string_matches',
'string_partial_match' => 'string_partial_match',
'string_begins_with' => 'string_begins_with',
'string_ends_with' => 'string_ends_with',
'string_not_matches' => 'string_not_matches',
'string_not_partial_match' => 'string_not_partial_match',
'string_not_begins_with' => 'string_not_begins_with',
'string_not_ends_with' => 'string_not_ends_with',
];
protected $label = 'Address Postcode';
protected $operand = 'users.address_postcode';
}
allowed_operatorsis a list of registered Operators that can act on this Operand. This array may change in the future to allow further customisation (such as access limitations), so for now we're specifying keys as well as values so that when the values become an array (or other type) the keys will still be correctlabelis the Label on the select box for this Operandoperandis the database column that this Operand relates to. You should try to prefix the column with the table name, to limit/remove the possibility of ambiguous column name errors.
You can add Operands that modify the query based on relationships. A relationship count posts associated with the user might look like:
use Yadda\Enso\Mailer\Handlers\Operands\BaseOperand;
class PostCount extends BaseOperand
{
/**
* Allowed operators for this Operand.
*
* @var array
*/
protected $allowed_operators = [
'relationship_at_least' => 'relationship_at_least',
'relationship_equals' => 'relationship_equals',
'relationship_less_than' => 'relationship_less_than',
'relationship_more_than' => 'relationship_more_than',
'relationship_no_more_than' => 'relationship_no_more_than',
];
protected $label = 'Posts Made';
protected $relationship_name = 'posts';
}
- the
operandproperty does not matter here as we're not querying a property of the bookings relationships. The Audience builder will use the relationship definition to find the correct column to use. - the
relationship_nameproperty is introduced to specify the relationships. It also accept dot-notation nested relationships, such asposts.comments.
You can add Operands that modify the query based on relationships that meet specific criteria. An operand that works with the post's comment's date might look like:
use Yadda\Enso\Mailer\Handlers\Operands\BaseOperand;
class CommentPostedAt extends BaseOperand
{
/**
* Allowed operators for this Operand.
*
* @var array
*/
protected $allowed_operators = [
'date_greater_than' => 'date_greater_than',
'date_on_or_greater_than' => 'date_on_or_greater_than',
'date_equals' => 'date_equals',
'date_on_or_less_than' => 'date_on_or_less_than',
'date_less_than' => 'date_less_than',
];
protected $label = 'Has Comments Posted';
protected $operand = 'comments.created_at';
protected $relationship_name = 'posts.comments';
}
Once you have made the Operand(s), you can then register on the Enso Mailer to make them available:
EnsoMailer::addOperandDefinition($name, $modifier);EnsoMailer::addOperandDefinitions($modifiers);EnsoMailer::updateOperandDefinition($name, $modifier);EnsoMailer::updateOperandDefinitions($modifiers);
EnsoMailer::addOperandDefinitions('postcode', AddressPostcode::class);
Operators
Operator definitions specify how the provided data should interact with the operand, and how to map the provided data to something useful to modify the audience's User query. Typically, if there is additional functionality that you need that isn't provided by an existing Operator, it's worth considering whether it can be built into Enso directly
To create new Operators, you should start by extending the Base Operator most relevant to your use-case. Then you should override various properties and methods to get the desired output.
This might look something like:
class PriorTo extends BaseRelationshipCountOperator
{
protected $label = 'Prior To';
protected $operator = '<';
protected $component = 'enso-field-date';
/**
* Accepts a query, condition and type of application, and alters the
* query based on these three things.
*
* @param Builder $query
* @param Condition $condition
* @param string $apply_as
*
* @return Builder
*/
public function modifyQuery($query, $condition, $apply_as = 'AND') // ...
/**
* Determines what type of query modifier to use, base on an
* 'AND'/'OR' value.
*
* @param string $apply_as
*
* @return string
*/
protected function howToApply($apply_as) //...
/**
* Potentially modifies a relationship count modifier to add extra conditions
* to a subquery (converting it from a 'has' to a 'whereHas' type query);
*
* @param Builder $query
* @param Condition $condition
* @param Collection $data
* @param string $apply_as
*
* @return Builder
*/
protected function modifyChildQuery($query, $condition, $data, $apply_as = 'OR') // ...
/**
* Alters the raw data taken from the Condition into a format that will work
* as part of a query modification.
*
* @param array $data
* @param string $apply_as
*
* @return Collection
*/
protected function parseData($data, $apply_as = 'AND') // ...
/**
* Function that can be overriden if needed to alter the data collection once
* it has been parsed into the appropriate format.
*
* @param Collection $collection
* @param string $apply_as
*
* @return Collection
*/
public function alterDataCollection($collection, $apply_as = 'AND') // ...
Data
Currently, data is always returned as an array, even it it's an array of one string. As such, stubbed operators can map each array element into their stubbs. However, there is no guarantee that all possible types of data that get passed in the future will be arrays, so ideally make sure that any of your own QueryModifier classes that you build can handle strings, arrays... possibly objects?