Commit c47cbf70 authored by john_a's avatar john_a Committed by John.Avery
Browse files

Issue #3154692 by john_a: Create a new sub-module for Workflow Teams calls

parent 7d26b658
......@@ -2,7 +2,7 @@
/**
* @file
* Module that defines the marketing cloud address service.
* Module that defines the marketing cloud audit service.
*/
use Drupal\Core\Routing\RouteMatchInterface;
......
......@@ -5,7 +5,7 @@ namespace Drupal\marketing_cloud_audit;
use Drupal\marketing_cloud\MarketingCloudService;
/**
* Class AddressService.
* Class AuditService.
*
* For all of the API service calls, a correct JSON data payload is expected.
* This is then validated against the JSON Schema. This approach minimises
......
MARKETING CLOUD WORKFLOW TEAMS API
===========================
CONTENTS OF THIS FILE
---------------------
* Introduction
* Service functions
* Requirements
* Installation & Configuration
INTRODUCTION
------------
This module enables the Workflow Teams API in the Marketing Cloud as a service.
For details on individual API calls and the Marketing Cloud REST API, please
visit
https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/routes.htm
SERVICE FUNCTIONS
-----------------
| Name | Function |
| ------------------- | -------------------------- |
| Get Active Workflow Teams | getActiveWorkflowTeams($objectType, $params) |
| State Transition | stateTransition($workflowItemId, $json) |
| Create User Role | createUserRole($workflowRoleInstanceId, $workflowItemId, $json) |
| Delete User Role | deleteUserRole($workflowRoleInstanceId, $workflowItemId, $userId) |
REQUIREMENTS
------------
* marketing_cloud
INSTALLATION & CONFIGURATION
----------------------------
This module will add a tab to admin > config > marketing cloud. here you can
edit the individual rest call definitions.
Please see the
[community documentation pages](https://www.drupal.org/docs/8/modules/marketing-cloud)
for information on installation and configuration.
definitions:
get_active_workflow_teams:
method: "get"
endpoint: "/hub/v1/workflowteams/[objectType]"
schema: ""
state_transition:
method: "post"
endpoint: "/hub/v1/workflowitems/[workflowItemId]/transitions"
schema: |
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "State transition",
"description": "Transitions the workflow item associated to an approval item from one state to another.",
"type": "object",
"properties" : {
"transitionid": {
"type": "string"
},
"overrideNotificationId": {
"type": "string"
}
},
"required": [
"transitionid"
],
"additionalProperties": false
}
create_user_role:
method: "post"
endpoint: "/hub/v1/workflowitems/[workflowItemId]/roles/[workflowRoleInstanceId]"
schema: |
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "Create a user role",
"description": "Creates a user role to assign to a workflow role.",
"type": "object",
"properties" : {
"userId": {
"type": "string"
},
"userName": {
"type": "string"
}
},
"required": [
"userId",
"userName"
],
"additionalProperties": false
}
delete_user_role:
method: "delete"
endpoint: "/hub/v1/workflowitems/[workflowItemId]/roles/[workflowRoleInstanceId]/users/[userId]"
schema: ""
marketing_cloud_workflow_teams.settings:
type: config_object
label: Marketing Cloud Workflow Teams settings
mapping:
definitions:
type: sequence
sequence:
type: mapping
mapping:
method:
type: string
label: Method
endpoint:
type: string
label: Endpoint
schema:
type: string
label: Schema
name: Marketing Cloud Workflow Teams
type: module
description: Gives drupal the ability to send workflow teams message requests to Marketing Cloud
core_version_requirement: ^8.8 || ^9
package: Marketing Cloud
configure: marketing_cloud_workflow_teams.settings
dependencies:
- drupal:marketing_cloud
marketing_cloud_workflow_teams.settings:
title: Workflow Teams Endpoints
description: Configure the Marketing Cloud Workflowe Teams module
parent: marketing_cloud.settings
route_name: marketing_cloud_workflow_teams.settings
marketing_cloud_workflow_teams.settings:
route_name: marketing_cloud_workflow_teams.settings
title: Workflow Teams Endpoints
description: Configure the Marketing Cloud Workflow Teams module
base_route: marketing_cloud.settings
<?php
/**
* @file
* Module that defines the marketing cloud workflow teams service.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function marketing_cloud_workflow_teams_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.marketing_cloud_workflow_teams':
$text = file_get_contents(dirname(__FILE__) . '/README.md');
if (!\Drupal::moduleHandler()->moduleExists('markdown')) {
\Drupal::messenger()->addMessage('To view this page correctly, please
install and enable the markdown module.');
return '<pre>' . $text . '</pre>';
}
else {
// Use the Markdown filter to render the README.
$filter_manager = \Drupal::service('plugin.manager.filter');
$settings = \Drupal::configFactory()->get('markdown.settings')->getRawData();
$config = ['settings' => $settings];
$filter = $filter_manager->createInstance('markdown', $config);
return $filter->process($text, 'en');
}
}
return NULL;
}
marketing_cloud_workflow_teams.settings:
path: /admin/config/marketing_cloud/workflow_teams
defaults:
_form: \Drupal\marketing_cloud_workflow_teams\Form\WorkflowTeamsSettings
_title: Marketing Cloud Workflow Teams settings
requirements:
_permission: administer_marketing_cloud
services:
marketing_cloud_workflow_teams.service:
class: Drupal\marketing_cloud_workflow_teams\WorkflowTeamsService
arguments: ['@config.factory', '@logger.factory', '@http_client', '@messenger']
<?php
namespace Drupal\marketing_cloud_workflow_teams\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Configure custom_rest settings for this site.
*/
class WorkflowTeamsSettings extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'marketing_cloud_workflow_teams';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['marketing_cloud_workflow_teams.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('marketing_cloud_workflow_teams.settings');
$form['definitions'] = [
'#type' => 'details',
'#title' => $this->t('Endpoint definitions'),
'#description' => $this->t('These are the endpoint definitions for Mobile Connect. <b>Important: Do not edit these unless you absolutely have to</b>.'),
'#open' => FALSE,
'#tree' => TRUE,
];
foreach ($config->get('definitions') as $key => $value) {
$form['definitions'][$key] = [
'#type' => 'details',
'#title' => $key,
'#open' => FALSE,
'#tree' => TRUE,
];
$form['definitions'][$key]['method'] = [
'#type' => 'textfield',
'#title' => $this->t('Method'),
'#attributes' => ['placeholder' => $this->t('Please enter delivery method for %endpoint endpoint', ['%endpoint' => $key])],
'#default_value' => $value['method'],
];
$form['definitions'][$key]['endpoint'] = [
'#type' => 'textfield',
'#title' => $this->t('Endpoint'),
'#attributes' => ['placeholder' => $this->t('Please enter endpoint for %endpoint endpoint', ['%endpoint' => $key])],
'#default_value' => $value['endpoint'],
];
$form['definitions'][$key]['schema'] = [
'#type' => 'textarea',
'#title' => $this->t('Schema'),
'#attributes' => ['placeholder' => $this->t('Please enter schema for %endpoint endpoint', ['%endpoint' => $key])],
'#default_value' => $value['schema'],
];
}
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->config('marketing_cloud_workflow_teams.settings');
$definitions = $config->get('definitions');
foreach ($definitions as $key => $value) {
$config->set(
"definitions.$key.method",
$form_state->getValue(['definitions', $key, 'method'])
);
$config->set(
"definitions.$key.endpoint",
$form_state->getValue(['definitions', $key, 'endpoint'])
);
$config->set(
"definitions.$key.schema",
$form_state->getValue(['definitions', $key, 'schema'])
);
}
$config->save();
parent::submitForm($form, $form_state);
}
}
<?php
namespace Drupal\marketing_cloud_workflow_teams;
use Drupal\marketing_cloud\MarketingCloudService;
/**
* Class WorkflowTeamsService.
*
* For all of the API service calls, a correct JSON data payload is expected.
* This is then validated against the JSON Schema. This approach minimises
* any short-term issues with changes in the SF API, provides a sanitized
* interface to send API calls and leaves flexibility for any modules that
* want to use this as a base-module.
*
* @package Drupal\marketing_cloud
*/
class WorkflowTeamsService extends MarketingCloudService {
/**
* The machine name of the sub-module.
*
* @var string
*/
private $moduleName = 'marketing_cloud_workflow_teams';
/**
* Retrieves a list of active workflow teams. Depending on the query string parameters, the result includes one or both filtered results: role user information for each workflow item or workflow items to which the current user is assigned.
*
* @param string $objectType
* Specify the workflow object type to retrieve or use (@all to retrieve all workflow object types).
* @param array $params
* URL filter params. Permissible keys:
* assignee string
* If assignee=@current, this resource retrieves workflow teams that the current user is assigned to.
* extra string
* If extra=roleusers, then each item in the response includes role user information as a collection.
*
* @return array|bool|null
* The result of the API call or FALSE on failure.
*
* @see https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/routes.htm
*/
public function getActiveWorkflowTeams($objectType, array $params = []) {
$machineName = 'get_active_workflow_teams';
return $this->apiCall(
$this->moduleName,
$machineName,
new \stdClass(),
['[objectType]' => $objectType],
$params
);
}
/**
* Transitions the workflow item associated to an approval item from one state to another. For example, a workflow item in Draft state moves to Submitted via the Submit transition.
*
* @param string $workflowItemId
* Id of the workflow item.
* @param array|object|string $json
* The JSON payload.
*
* @return array|bool|null
* The result of the API call or FALSE on failure.
*
* @see https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/routes.htm
*/
public function stateTransition($workflowItemId, $json) {
$machineName = 'state_transition';
return $this->apiCall($this->moduleName, $machineName, $json, ['[workflowItemId]' => $workflowItemId], []);
}
/**
* Creates a user role to assign to a workflow role.
*
* @param string $workflowRoleInstanceId
* Id of the workflow role instance.
* @param string $workflowItemId
* Id of the workflow item.
* @param array|object|string $json
* The JSON payload.
*
* @return array|bool|null
* The result of the API call or FALSE on failure.
*
* @see https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/routes.htm
*/
public function createUserRole($workflowRoleInstanceId, $workflowItemId, $json) {
$machineName = 'create_user_role';
return $this->apiCall(
$this->moduleName,
$machineName,
$json,
['[workflowRoleInstanceId]' => $workflowRoleInstanceId, '[workflowItemId]' => $workflowItemId],
[]
);
}
/**
* Removes a user assigned to a workflow role.
*
* @param string $workflowRoleInstanceId
* Id of the workflow role instance record.
* @param string $workflowItemId
* Id of the workflow item.
* @param string $userId
* Id of the user to be removed.
*
* @return array|bool|null
* The result of the API call or FALSE on failure.
*
* @see https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/routes.htm
*/
public function deleteUserRole($workflowRoleInstanceId, $workflowItemId, $userId) {
$machineName = 'delete_user_role';
return $this->apiCall(
$this->moduleName,
$machineName,
new \stdClass(),
[
'[workflowRoleInstanceId]' => $workflowRoleInstanceId,
'[workflowItemId]' => $workflowItemId,
'[userId]' => $userId
],
[]
);
}
}
<?php
namespace Drupal\Tests\marketing_cloud_audit\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the base marketing_cloud_workflow_teams module.
*
* @group marketing_cloud
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*/
class MarketingCloudWorkflowTeamsTest extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['marketing_cloud', 'marketing_cloud_workflow_teams'];
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* Workflow teams service.
*
* @var \Drupal\marketing_cloud_workflow_teams\WorkflowTeamsService
*/
protected $service;
/**
* Config service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $moduleConfig;
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create user.
$this->adminUser = $this->drupalCreateUser(['administer_marketing_cloud']);
$this->drupalLogin($this->adminUser);
// Set module config.
$this->config('marketing_cloud.settings')
->set('client_id', 'testingid')
->set('client_secret', 'testingsecret')
->set('validate_json', TRUE)
->set('do_not_send', TRUE)
->save();
// Create service.
$this->service = \Drupal::service('marketing_cloud_workflow_teams.service');
// Get marketing_cloud_assets config object.
$this->moduleConfig = \Drupal::config('marketing_cloud_workflow_teams.settings');
}
/**
* Tests the services and schemas for marketing_cloud_audit.
*/
public function testDefinitions() {
// Test get_active_workflow_teams().
$this->validateDefinitionIsEmpty('get_active_workflow_teams');
// Test getActiveWorkflowTeams against expected inputs.
$result = $this->service
->getActiveWorkflowTeams('@all', ['assignee' => '@current', 'extra' => 'roleusers']);
$this->assertEquals('https://www.exacttargetapis.com/hub/v1/workflowteams/@all?assignee=@current&extra=roleusers',
$result['url'],
'Unexpected URL.');
$this->assertEquals('{}', $result['data'], 'Unexpected JSON data.');
$this->assertEquals('get', $result['method'], 'Unexpected method.');
// Test state_transition().
$this->validateDefinitionNotEmpty('state_transition');
// Test getStateTransitionData against expected inputs.
$json = $this->getStateTransitionData();
$result = $this->service
->stateTransition('workflowitemid', $json);
$this->assertEquals('https://www.exacttargetapis.com/hub/v1/workflowitems/workflowitemid/transitions',
$result['url'],
'Unexpected URL.');
$this->assertEquals(json_encode($json), $result['data'], 'Unexpected JSON data.');
$this->assertEquals('post', $result['method'], 'Unexpected method.');
// Test getActiveWorkflowTeams().
$this->validateDefinitionNotEmpty('create_user_role');
// Test getActiveWorkflowTeams against expected inputs.
$json = $this->getActiveWorkflowTeamsData();
$result = $this->service
->createUserRole('jyfiughjk', 'jgfjhf', $json);
$this->assertEquals('https://www.exacttargetapis.com/hub/v1/workflowitems/jgfjhf/roles/jyfiughjk',
$result['url'],
'Unexpected URL.');
$this->assertEquals(json_encode($json), $result['data'], 'Unexpected JSON data.');
$this->assertEquals('post', $result['method'], 'Unexpected method.');
// Test deleteUserRole().
$this->validateDefinitionIsEmpty('delete_user_role');
// Test deleteUserRole against expected inputs.
$result = $this->service
->deleteUserRole('jyfiughjk', 'jgfjhf', 'li76syred');
$this->assertEquals('https://www.exacttargetapis.com/hub/v1/workflowitems/jgfjhf/roles/jyfiughjk/users/li76syred',
$result['url'],
'Unexpected URL.');
$this->assertEquals('{}', $result['data'], 'Unexpected JSON data.');
$this->assertEquals('delete', $result['method'], 'Unexpected method.');
}
/**
* Test that the Json-Schema is empty, and that the API method id correct.
*
* @param string $machineName
* The machine name for the api call definition.
*/
protected function validateDefinitionIsEmpty($machineName) {
// Validate schema.
$schema = $this->moduleConfig->get("definitions.$machineName.schema");
$this->assertEquals($schema, '', "json schema for $machineName should be an empty string.");
}
/**
* Test that the Json-Schema is not empty, and that the API method id correct.
*
* @param string $machineName
* The machine name for the api call definition.
*/