Skip to content

Commit

Permalink
add field to denote where a data source config is managed
Browse files Browse the repository at this point in the history
  • Loading branch information
shekharnwagh committed Feb 7, 2025
1 parent 64af67d commit 58f4ca1
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 34 deletions.
164 changes: 164 additions & 0 deletions inc/Config/DataSource/DataSourceConfigManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php declare(strict_types = 1);

namespace RemoteDataBlocks\Config\DataSource;

use RemoteDataBlocks\Editor\BlockManagement\ConfigStore;
use RemoteDataBlocks\WpdbStorage\DataSourceCrud;
use WP_Error;

class DataSourceConfigManager {
public const CONFIG_SOURCE_CODE = 'code';
public const CONFIG_SOURCE_STORAGE = 'storage';
public const MUTABLE_CONFIG_SOURCES = [ self::CONFIG_SOURCE_STORAGE ];

private static function get_all_from_storage(): array {
return array_map(
fn ( array $config ) => array_merge( $config, [ 'config_source' => self::CONFIG_SOURCE_STORAGE ] ),
DataSourceCrud::get_configs()
);
}

private static function get_all_from_code(): array {
return array_map(
fn ( array $config ) => array_merge( $config, [ 'config_source' => self::CONFIG_SOURCE_CODE ] ),
ConfigStore::get_data_sources_as_array()
);
}

/**
* Get all data sources from all origins.
*
* @return array<array{
* uuid?: string,
* service: string,
* service_config: array<string, mixed>,
* config_source: string,
* __metadata?: array{
* created_at: string,
* updated_at: string
* }
* }>
*/
public static function get_all(): array {
$code_configured = self::get_all_from_code();
$storage_configured = self::get_all_from_storage();

/**
* Quick and dirty de-duplication of data sources. If the data source does
* not have a UUID (because it is registered in code), we generate an
* identifier based on the display name and service name.
*
* Storage configured data sources take precedence over code configured ones
* here due to the ordering of the two arrays passed to array_reduce.
*/
return array_values( array_reduce(
array_merge( $code_configured, $storage_configured ),
function ( array $acc, array $item ) {
$identifier = $item['uuid'] ?? md5( sprintf( '%s_%s', $item['service_config']['display_name'], $item['service'] ) );
$acc[ $identifier ] = $item;
return $acc;
},
[]
) );
}

/**
* Get a data source by its UUID.
*
* @param string $uuid The UUID of the data source to get.
* @return array{
* uuid: string,
* service: string,
* service_config: array<string, mixed>,
* config_source: string,
* __metadata?: array{
* created_at: string,
* updated_at: string
* }
* }|WP_Error
*/
public static function get( string $uuid ): array|WP_Error {
// Currently only storage-configured data sources are supported.
$from_storage = DataSourceCrud::get_config_by_uuid( $uuid );

if ( is_wp_error( $from_storage ) ) {
return new WP_Error(
'data_source_not_found',
__( 'Data source not found', 'remote-data-blocks' ),
[ 'status' => 404 ]
);
}

return array_merge( $from_storage, [ 'config_source' => self::CONFIG_SOURCE_STORAGE ] );
}

/**
* Create a new data source.
*
* @param array $config The configuration for the new data source.
* @return array{
* uuid: string,
* service: string,
* service_config: array<string, mixed>,
* config_source: string,
* __metadata: array{
* created_at: string,
* updated_at: string
* }
* }|WP_Error
*/
public static function create( array $config ): array|WP_Error {
$result = DataSourceCrud::create_config( $config );
if ( is_wp_error( $result ) ) {
return $result;
}

return array_merge( $result, [ 'config_source' => self::CONFIG_SOURCE_STORAGE ] );
}

/**
* Update a data source.
*
* @param string $uuid The UUID of the data source to update.
* @param array $config The new configuration for the data source.
* @return array{
* uuid: string,
* service: string,
* service_config: array<string, mixed>,
* config_source: string,
* __metadata: array{
* created_at: string,
* updated_at: string
* }
* }|WP_Error
*/
public static function update( string $uuid, array $config ): array|WP_Error {
if ( isset( $config['config_source'] ) && ! in_array( $config['config_source'], self::MUTABLE_CONFIG_SOURCES, true ) ) {
/**
* Only storage-configured data sources are mutable.
*/
return new WP_Error(
'cannot_update_config',
__( 'Cannot update a data source with this config_source', 'remote-data-blocks' ),
[ 'status' => 400 ]
);
}

$result = DataSourceCrud::update_config_by_uuid( $uuid, $config );
if ( is_wp_error( $result ) ) {
return $result;
}

return array_merge( $result, [ 'config_source' => self::CONFIG_SOURCE_STORAGE ] );
}

/**
* Delete a data source.
*
* @param string $uuid The UUID of the data source to delete.
* @return true|WP_Error True on success, WP_Error on failure.
*/
public static function delete( string $uuid ): bool|WP_Error {
return DataSourceCrud::delete_config_by_uuid( $uuid );
}
}
53 changes: 19 additions & 34 deletions inc/REST/DataSourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
namespace RemoteDataBlocks\REST;

use RemoteDataBlocks\Analytics\TracksAnalytics;
use RemoteDataBlocks\Editor\BlockManagement\ConfigStore;
use RemoteDataBlocks\WpdbStorage\DataSourceCrud;
use RemoteDataBlocks\Config\DataSource\DataSourceConfigManager;
use RemoteDataBlocks\Snippet\Snippet;
use WP_REST_Controller;
use WP_REST_Request;
Expand Down Expand Up @@ -127,7 +126,7 @@ public function register_routes(): void {
'/' . $this->rest_base . '/(?P<uuids>[a-zA-Z0-9,-]+)',
[
'methods' => 'DELETE',
'callback' => [ $this, 'delete_multiple_items' ],
'callback' => [ $this, 'delete_multiple_items' ],
'permission_callback' => [ $this, 'delete_item_permissions_check' ],
'args' => [
'uuids' => [
Expand All @@ -147,7 +146,7 @@ public function register_routes(): void {
*/
public function create_item( mixed $request ): WP_REST_Response|WP_Error {
$data_source_properties = $request->get_json_params();
$item = DataSourceCrud::create_config( $data_source_properties );
$item = DataSourceConfigManager::create( $data_source_properties );

TracksAnalytics::record_event( 'remotedatablocks_data_source_interaction', array_merge( [
'data_source_type' => $data_source_properties['service'],
Expand All @@ -164,37 +163,24 @@ public function create_item( mixed $request ): WP_REST_Response|WP_Error {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_items( mixed $request ): WP_REST_Response|WP_Error {
$code_configured_data_sources = ConfigStore::get_data_sources_as_array();
$ui_configured_data_sources = DataSourceCrud::get_configs();

/**
* Quick and dirty de-duplication of data sources. If the data source does
* not have a UUID (because it is registered in code), we generate an
* identifier based on the display name and service name.
*
* UI configured data sources take precedence over code configured ones
* here due to the ordering of the two arrays passed to array_reduce.
*/
$data_sources = array_values( array_reduce(
array_merge( $code_configured_data_sources, $ui_configured_data_sources ),
function ( $acc, $item ) {
$identifier = $item['uuid'] ?? md5( sprintf( '%s_%s', $item['service_config']['display_name'], $item['service'] ) );
$acc[ $identifier ] = $item;
return $acc;
},
[]
) );
$data_sources = DataSourceConfigManager::get_all();

// Tracks Analytics. Only once per day to reduce noise.
$track_transient_key = 'remotedatablocks_view_data_sources_tracked';
if ( ! get_transient( $track_transient_key ) ) {
$code_configured_data_sources_count = count( $code_configured_data_sources );
$ui_configured_data_sources_count = count( $ui_configured_data_sources );
$code_configured_count = count( array_filter(
$data_sources,
fn ( $ds ) => $ds['config_source'] === DataSourceConfigManager::CONFIG_SOURCE_CODE
) );
$storage_configured_count = count( array_filter(
$data_sources,
fn ( $ds ) => $ds['config_source'] === DataSourceConfigManager::CONFIG_SOURCE_STORAGE
) );

TracksAnalytics::record_event( 'remotedatablocks_view_data_sources', [
'total_data_sources_count' => $code_configured_data_sources_count + $ui_configured_data_sources_count,
'code_configured_data_sources_count' => $code_configured_data_sources_count,
'ui_configured_data_sources_count' => $ui_configured_data_sources_count,
'total_data_sources_count' => count( $data_sources ),
'code_configured_data_sources_count' => $code_configured_count,
'ui_configured_data_sources_count' => $storage_configured_count,
] );
set_transient( $track_transient_key, true, DAY_IN_SECONDS );
}
Expand All @@ -209,7 +195,7 @@ function ( $acc, $item ) {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_item( mixed $request ): WP_REST_Response|WP_Error {
$response = DataSourceCrud::get_config_by_uuid( $request->get_param( 'uuid' ) );
$response = DataSourceConfigManager::get( $request->get_param( 'uuid' ) );
return rest_ensure_response( $response );
}

Expand All @@ -226,7 +212,7 @@ public function get_snippets( mixed $request ): WP_REST_Response|WP_Error {
*/
public function update_item( mixed $request ): WP_REST_Response|WP_Error {
$data_source_properties = $request->get_json_params();
$item = DataSourceCrud::update_config_by_uuid( $request->get_param( 'uuid' ), $data_source_properties );
$item = DataSourceConfigManager::update( $request->get_param( 'uuid' ), $data_source_properties );

if ( is_wp_error( $item ) ) {
return $item; // Return WP_Error if update fails
Expand All @@ -248,7 +234,7 @@ public function update_item( mixed $request ): WP_REST_Response|WP_Error {
*/
public function delete_item( mixed $request ): WP_REST_Response|WP_Error {
$data_source_properties = $request->get_json_params();
$result = DataSourceCrud::delete_config_by_uuid( $request->get_param( 'uuid' ) );
$result = DataSourceConfigManager::delete( $request->get_param( 'uuid' ) );

// Tracks Analytics.
TracksAnalytics::record_event( 'remotedatablocks_data_source_interaction', [
Expand Down Expand Up @@ -278,7 +264,7 @@ public function delete_multiple_items( WP_REST_Request $request ): WP_REST_Respo

$failed = [];
foreach ( $uuids as $uuid ) {
$result = DataSourceCrud::delete_config_by_uuid( $uuid );
$result = DataSourceConfigManager::delete( $uuid );
if ( is_wp_error( $result ) ) {
$failed[] = [
'uuid' => $uuid,
Expand All @@ -301,7 +287,6 @@ public function delete_multiple_items( WP_REST_Request $request ): WP_REST_Respo
]);
}


// These all require manage_options for now, but we can adjust as needed

public function get_item_permissions_check( mixed $request ): bool|WP_Error {
Expand Down

0 comments on commit 58f4ca1

Please sign in to comment.