Skip to content
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

Implement Analytics #240

Merged
merged 16 commits into from
Jun 4, 2023
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
6 changes: 5 additions & 1 deletion .github/workflows/lint-check-spa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ jobs:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-node-

- name: Setup Registry
run: printf "@newfold-labs:registry=https://npm.pkg.github.com/\n//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
if: steps.cache.outputs.cache-hit != 'true'

# Installs @wordpress/scripts for lint checks if it does not exist in the cache.
- name: Install dependencies
run: npm i @wordpress/scripts
run: npm i @wordpress/scripts @newfold-labs/js-utility-ui-analytics
if: steps.cache.outputs.cache-hit != 'true'

# Gets the files changed wrt to trunk and filters out the js files.
Expand Down
68 changes: 52 additions & 16 deletions includes/Data/Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,65 @@
namespace NewfoldLabs\WP\Module\Onboarding\Data;

/**
* List of Onboarding events.
* Contains data related to Onboarding Hiive Events.
*/
final class Events {
/**
* The category of an event.
*
* @var string
*/
protected static $category = 'wp-onboarding';

/**
* Contains a list of events with the key being the event slug.
*
* @var array
*/
protected static $events = array(
'nfd-module-onboarding-event-pageview' => array(
'category' => 'Admin',
'action' => 'pageview',
),
/**
* List of valid actions that an event can perform.
*
* A value of true indicates that the action is valid, set it to null if you want to invalidate an action.
*
* @var array
*/
protected static $valid_actions = array(
'pageview' => true,
'sidebar-opened' => true,
'sidebar-closed' => true,
'wp-experience' => true,
'primary-type' => true,
'secondary-type' => true,
'tax-information' => true,
'selected-style' => true,
'default-style' => true,
'customize-design' => true,
'font-selection' => true,
'theme-header' => true,
'homepage-layout' => true,
'top-priority' => true,
'top-priority-skipped' => true,
'exit-to-wordpress' => true,
'products-info' => true,
'yith-wonder/company-page-layout' => true,
'yith-wonder/contact-us-layout' => true,
'yith-wonder/blog-page-layout' => true,
'yith-wonder/testimonials-page-layout' => true,
'site-features' => true,
'color-selection' => true,
'color-selection-reset' => true,
);

/**
* Retrieves the active theme color variations.
* Returns the list of valid actions that an event can perform
*
* @return array
*/
public static function get_valid_actions() {
return self::$valid_actions;
}

/**
* Valid category of on event.
*
* @param array $event_slug Event data.
* @return array|boolean
* @return string
*/
public static function get_event( $event_slug ) {
return self::$events[ $event_slug ] ? self::$events[ $event_slug ] : false;
public static function get_category() {
return self::$category;
}
}
157 changes: 98 additions & 59 deletions includes/RestApi/EventsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,100 +3,139 @@

use NewfoldLabs\WP\Module\Onboarding\Data\Events;
use NewfoldLabs\WP\Module\Onboarding\Permissions;
use NewfoldLabs\WP\Module\Onboarding\Services\EventService;

/**
* [Class EventsController]
* Controller to send analytics events.
*/
class EventsController extends \WP_REST_Controller {

/**
* This is the REST API namespace that will be used for our custom API
* The namespace of the controller.
*
* @var string
*/
protected $namespace = 'newfold-onboarding/v1';
protected $namespace = 'newfold-onboarding/v1';

/**
* This is the REST endpoint
*
* @var string
*/
protected $rest_base = '/events';
/**
* The REST base endpoint.
*
* @var string
*/
protected $rest_base = '/events';

/**
* Register REST routes for EventsController class.
*
* @return void
*/
/**
* Register routes that the controller will expose.
*
* @return void
*/
public function register_routes() {
\register_rest_route(
$this->namespace,
$this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'send_event' ),
'callback' => array( $this, 'send' ),
'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
'args' => $this->get_send_args(),
),
)
);

\register_rest_route(
$this->namespace,
$this->rest_base . '/batch',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'send_batch' ),
'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
'args' => $this->get_send_event_args(),
),
)
);
}

/**
* Get args for the send_event endpoint.
*
* @return array
*/
public function get_send_event_args() {
return array(
'slug' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
'data' => array(
'type' => 'object',
),
);
/**
* Args for a single event.
*
* @return array
*/
public function get_send_args() {
return array(
'action' => array(
'required' => true,
'description' => __( 'Event action', 'wp-module-onboarding' ),
'type' => 'string',
'sanitize_callback' => 'sanitize_title',
'validate_callback' => array( EventService::class, 'validate_action' ),
),
'category' => array(
'default' => Events::get_category(),
'description' => __( 'Event category', 'wp-module-onboarding' ),
'type' => 'string',
'sanitize_callback' => 'sanitize_title',
'validate_callback' => array( EventService::class, 'validate_category' ),
),
'data' => array(
'description' => __( 'Event data', 'wp-module-onboarding' ),
'type' => 'object',
),
);
}

/**
* Sends a Hiive Event to the data module API.
*
* @param \WP_REST_Request $request The incoming request object.
* @return \WP_REST_Response|\WP_Error
*/
public function send( \WP_REST_Request $request ) {
return EventService::send( $request->get_params() );
}

/**
* Send events to the data module events API.
*
* @param \WP_REST_Request $request Request model.
*
* @return \WP_REST_Response|\WP_Error
*/
public function send_event( \WP_REST_Request $request ) {
$event = Events::get_event( $request->get_param( 'slug' ) );
if ( ! $event ) {
/**
* Sends an array of Hiive Events to the data module API programmatically.
*
* @param \WP_REST_Request $request The incoming request object.
* @return \WP_REST_Response|\WP_Error
*/
public function send_batch( \WP_REST_Request $request ) {
$events = $request->get_json_params();
if ( ! rest_is_array( $events ) ) {
return new \WP_Error(
'event-error',
'No such event found',
array( 'status' => 404 )
'nfd_module_onboarding_error',
__( 'Request does not contain an array of events.', 'wp-module-onboarding' )
);
}

$event['data'] = $request->get_param( 'data' );

if ( ! empty( $event['data'] ) && ! empty( $event['data']['stepID'] ) ) {
$event['data']['page'] = \admin_url( '/index.php?page=nfd-onboarding#' . $event['data']['stepID'] );
$response_errors = array();
foreach ( $events as $index => $event ) {
$response = EventService::send( $event );
if ( is_wp_error( $response ) ) {
array_push(
$response_errors,
array(
'index' => $index,
'data' => $response,
)
);
}
}

$event_data_request = new \WP_REST_Request(
\WP_REST_Server::CREATABLE,
NFD_MODULE_DATA_EVENTS_API
);
$event_data_request->set_body_params( $event );
$response = \rest_do_request( $event_data_request );
if ( $response->is_error() ) {
return $response->as_error();
if ( ! empty( $response_errors ) ) {
return new \WP_Error(
'nfd_module_onboarding_error',
__( 'Some events failed.', 'wp-module-onboarding' ),
array(
'data' => $response_errors,
)
);
}

return new \WP_REST_Response(
$response,
$response->status
array(),
202
);
}
}
83 changes: 83 additions & 0 deletions includes/Services/EventService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace NewfoldLabs\WP\Module\Onboarding\Services;

use NewfoldLabs\WP\Module\Onboarding\Data\Events;

/**
* Class for handling analytics events.
*/
class EventService {

/**
* Sends a Hiive Event to the data module API.
*
* @param array $event The event to send.
* @return WP_REST_Response|WP_Error
*/
public static function send( $event ) {
$event = self::validate( $event );
if ( ! $event ) {
return new \WP_Error(
'nfd_module_onboarding_error',
__( 'Bad event structure/value.', 'wp-module-onboarding' )
);
}

$event_data_request = new \WP_REST_Request(
\WP_REST_Server::CREATABLE,
NFD_MODULE_DATA_EVENTS_API
);
$event_data_request->set_body_params( $event );

$response = rest_do_request( $event_data_request );
if ( $response->is_error() ) {
return $response->as_error();
}

return $response;
}

/**
* Validates the category of an event.
*
* @param string $category The category of an event.
* @return boolean
*/
public static function validate_category( $category ) {
return Events::get_category() === $category;
}

/**
* Validates the action performed in an event.
*
* @param string $action The action performed in an event.
* @return boolean
*/
public static function validate_action( $action ) {
$valid_actions = Events::get_valid_actions();
if ( ! isset( $valid_actions[ $action ] ) ) {
return false;
}

return true;
}

/**
* Sanitizes and validates the action and category parameters of an event.
*
* @param array $event The event to sanitize and validate.
* @return array|boolean
*/
public static function validate( $event ) {
if ( ! isset( $event['action'] ) || ! self::validate_action( $event['action'] ) ) {
return false;
}

if ( ! isset( $event['category'] ) || ! self::validate_category( $event['category'] ) ) {
return false;
}

return $event;
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"test:unit": "npx wp-env run phpunit 'phpunit -c /var/www/html/wp-content/plugins//phpunit.xml --verbose'"
},
"dependencies": {
"@newfold-labs/js-utility-ui-analytics": "1.0.0",
"@wordpress/interface": "^5.10.0",
"@wordpress/style-engine": "^0.11.0",
"classnames": "^2.3.1",
Expand Down
Loading