Skip to content

Commit

Permalink
Merge pull request #70 from stellarwp/feat/fluent-form-builder
Browse files Browse the repository at this point in the history
Feat/fluent form builder
  • Loading branch information
dpanta94 authored Aug 13, 2024
2 parents 2a37fbb + 82e2d09 commit 45a14b6
Show file tree
Hide file tree
Showing 87 changed files with 4,057 additions and 702 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ repo/
vendor/
.idea/
/composer.lock

local-scripts/
80 changes: 47 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,12 @@ src/Uplink/Helper.php
The file should match the following - keeping the `KEY` constant set to a blank string, or, if you want a default license key, set it to that.:

```php
<?php
<?php declare( strict_types=1 );

namespace Whatever\Namespace\Uplink;

class Helper {
const KEY = '';
final class Helper {
public const KEY = '';
}
```

Expand All @@ -120,7 +121,8 @@ Register::plugin(
$plugin_version,
$plugin_path,
$plugin_class,
$license_class // This is optional.
$license_class, // This is optional.
false // Whether this is an oAuth plugin. Default false.
);
```

Expand All @@ -142,7 +144,9 @@ Register::service(
$service_name,
$service_version,
$plugin_path,
$plugin_class
$plugin_class,
null,
false
);
```

Expand All @@ -153,27 +157,33 @@ In order to render license key form just add the following to your settings page
> ⚠️ This will render license key fields for all of your registered plugins/services in the same Uplink/Container instance.
```php
use StellarWP\Uplink\Config;
use StellarWP\Uplink as UplinkNamespace;

$fields = Config::get_container()->get( License_Field::class );
$form = UplinkNamespace\get_form();
$plugins = UplinkNamespace\get_plugins();

// Do one of the following:
$fields->render(); // Render the fields, titles, and submit button.
$fields->render( false ); // Render the fields without the titles.
$fields->render( false, false ); // Render the fields without the titles or submit buttons.
foreach ( $plugins as $plugin ) {
$field = UplinkNamespace\get_field( $plugin->get_slug() );
// Tha name property of the input field.
$field->set_field_name( 'field-' . $slug );
$form->add_field( $field );
}

$form->render();
// or echo $form->get_render_html();
```

To render a single product's license key, use the following:

```php
use StellarWP\Uplink\Config;
use StellarWP\Uplink as UplinkNamespace;

$field = UplinkNamespace\get_field( 'my-test-plugin' );

$field->render();
// or echo $field->get_render_html();

$fields = Config::get_container()->get( License_Field::class );

// Do one of the following:
$fields->render_single( 'my-plugin' ); // Render the fields, titles, and submit button.
$fields->render_single( 'my-plugin', false ); // Render the fields without the titles.
$fields->render_single( 'my-plugin', false, false ); // Render the fields without the titles or submit buttons.
```

### Example: Register settings page and render license fields
Expand All @@ -195,13 +205,23 @@ add_action( 'admin_menu', function () {

Add lines below to your settings page. This will render license key form with titles and a submit button
```php
use StellarWP\Uplink\Config;
use StellarWP\Uplink as UplinkNamespace;

function render_settings_page() {
// ...
$form = UplinkNamespace\get_form();
$plugins = UplinkNamespace\get_plugins();

foreach ( $plugins as $plugin ) {
$field = UplinkNamespace\get_field( $plugin->get_slug() );
// Tha name property of the input field.
$field->set_field_name( 'field-' . $slug );
$form->add_field( $field );
}

$form->show_button( true, __( 'Submit', 'text-domain' ) );

$fields = Config::get_container()->get( License_Field::class );
$fields->render(); // or $fields->render_single( 'my-plugin' ); to render a single plugin
$form->render();

//....
}
Expand Down Expand Up @@ -256,15 +276,15 @@ You can also pass in a custom license domain, which can be fetched on the Uplink
This connects to the licensing server to check in real time if the license is authorized. Use sparingly.

```php
$container = \StellarWP\Uplink\Config::get_container();
$token_manager = $container->get( \StellarWP\Uplink\Auth\Token\Contracts\Token_Manager::class );
$token = $token_manager->get();
$token = \StellarWP\Uplink\get_authorization_token( 'my-plugin-slug' );
$license_key = \StellarWP\Uplink\get_license_key( 'my-plugin-slug' );
$domain = \StellarWP\Uplink\get_license_domain();

if ( ! $token ) {
return;
if ( ! $token || ! $license_key || ! $domain ) {
return; // or, log/show errors.
}

$is_authorized = \StellarWP\Uplink\is_authorized( 'customer_license_key', $token, 'customer_domain' );
$is_authorized = \StellarWP\Uplink\is_authorized( $license_key, 'my-plugin-slug', $token, $domain );

echo $is_authorized ? esc_html__( 'authorized' ) : esc_html__( 'not authorized' );
```
Expand All @@ -274,13 +294,7 @@ echo $is_authorized ? esc_html__( 'authorized' ) : esc_html__( 'not authorized'
If for some reason you need to fetch your `auth_url` manually, you can do so by:

```php
$container = \StellarWP\Uplink\Config::get_container();
$auth_url_manager = $container->get( \StellarWP\Uplink\API\V3\Auth\Contracts\Auth_Url::class );

// Pass your product or service slug.
$auth_url = $auth_url_manager->get( 'kadence-blocks-pro' );

echo $auth_url;
echo esc_url( \StellarWP\Uplink\get_auth_url( 'my-plugin-slug' ) );
```

> 💡 Auth URL connections are cached for one day using transients.
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"codeception/module-rest": "^1.0",
"codeception/module-webdriver": "^1.0",
"codeception/util-universalframework": "^1.0",
"lucatume/codeception-snapshot-assertions": "^0.4.0",
"lucatume/di52": "^3.0",
"lucatume/wp-browser": "^3.0.14",
"phpspec/prophecy": "^1.0",
Expand Down
15 changes: 11 additions & 4 deletions src/Uplink/API/V3/Auth/Auth_Url_Cache_Decorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace StellarWP\Uplink\API\V3\Auth;

use InvalidArgumentException;
use StellarWP\Uplink\Storage\Contracts\Storage;

/**
* Auth URL cache decorator.
Expand All @@ -16,6 +17,11 @@ final class Auth_Url_Cache_Decorator implements Contracts\Auth_Url {
*/
private $auth_url;

/**
* @var Storage
*/
private $storage;

/**
* The cache expiration in seconds.
*
Expand All @@ -27,8 +33,9 @@ final class Auth_Url_Cache_Decorator implements Contracts\Auth_Url {
* @param Auth_Url $auth_url Remotely fetch the Origin's Auth URL.
* @param int $expiration The cache expiration in seconds.
*/
public function __construct( Auth_Url $auth_url, int $expiration = DAY_IN_SECONDS ) {
public function __construct( Auth_Url $auth_url, Storage $storage, int $expiration = DAY_IN_SECONDS ) {
$this->auth_url = $auth_url;
$this->storage = $storage;
$this->expiration = $expiration;
}

Expand All @@ -48,16 +55,16 @@ public function get( string $slug ): string {

$transient = $this->build_transient( $slug );

$url = get_transient( $transient );
$url = $this->storage->get( $transient );

if ( $url !== false ) {
if ( $url !== null ) {
return $url;
}

$url = $this->auth_url->get( $slug );

// We'll cache empty auth URLs to prevent further remote requests.
set_transient( $transient, $url, $this->expiration );
$this->storage->set( $transient, $url, $this->expiration );

return $url;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Uplink/API/V3/Auth/Contracts/Token_Authorizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ interface Token_Authorizer {
* @see \StellarWP\Uplink\API\V3\Auth\Token_Authorizer
*
* @param string $license The license key.
* @param string $slug The plugin/service slug.
* @param string $token The stored token.
* @param string $domain The user's domain.
*
* @return bool
*/
public function is_authorized( string $license, string $token, string $domain ): bool;
public function is_authorized( string $license, string $slug, string $token, string $domain ): bool;

}
11 changes: 8 additions & 3 deletions src/Uplink/API/V3/Auth/Token_Authorizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,21 @@ public function __construct( Client_V3 $client ) {
* Manually check if a license is authorized.
*
* @see is_authorized()
* @see Token_Authorizer_Cache_Decorator
*
* @param string $license The license key.
* @param string $token The stored token.
* @param string $domain The user's domain.
* @param string $slug The plugin/service slug.
* @param string $token The stored token.
* @param string $domain The user's domain.
*
* @return bool
*
* @see is_authorized()
*/
public function is_authorized( string $license, string $token, string $domain ): bool {
public function is_authorized( string $license, string $slug, string $token, string $domain ): bool {
$response = $this->client->get( 'tokens/auth', [
'license' => $license,
'slug' => $slug,
'token' => $token,
'domain' => $domain,
] );
Expand Down
34 changes: 27 additions & 7 deletions src/Uplink/API/V3/Auth/Token_Authorizer_Cache_Decorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use StellarWP\Uplink\API\V3\Provider;
use StellarWP\Uplink\Config;
use StellarWP\Uplink\Storage\Contracts\Storage;

/**
* Token Authorizer Cache Decorator.
Expand All @@ -19,6 +20,11 @@ final class Token_Authorizer_Cache_Decorator implements Contracts\Token_Authoriz
*/
private $authorizer;

/**
* @var Storage
*/
private $storage;

/**
* The cache expiration in seconds.
*
Expand All @@ -35,9 +41,11 @@ final class Token_Authorizer_Cache_Decorator implements Contracts\Token_Authoriz
*/
public function __construct(
Token_Authorizer $authorizer,
Storage $storage,
int $expiration = 21600
) {
$this->authorizer = $authorizer;
$this->storage = $storage;
$this->expiration = $expiration;
}

Expand All @@ -49,24 +57,25 @@ public function __construct(
* @see Token_Authorizer
*
* @param string $license The license key.
* @param string $slug The plugin/service slug.
* @param string $token The stored token.
* @param string $domain The user's domain.
*
* @return bool
*/
public function is_authorized( string $license, string $token, string $domain ): bool {
public function is_authorized( string $license, string $slug, string $token, string $domain ): bool {
$transient = $this->build_transient( [ $license, $token, $domain ] );
$is_authorized = get_transient( $transient );
$is_authorized = $this->storage->get( $transient );

if ( $is_authorized === true ) {
return true;
}

$is_authorized = $this->authorizer->is_authorized( $license, $token, $domain );
$is_authorized = $this->authorizer->is_authorized( $license, $slug, $token, $domain );

// Only cache successful responses.
if ( $is_authorized ) {
set_transient( $transient, true, $this->expiration );
$this->storage->set( $transient, true, $this->expiration );
}

return $is_authorized;
Expand All @@ -75,12 +84,23 @@ public function is_authorized( string $license, string $token, string $domain ):
/**
* Build a transient key.
*
* @param array<int, string> ...$args
* @param array<int, string> $args
*
* @return string
*/
public function build_transient( array $args ): string {
return self::TRANSIENT_PREFIX . $this->build_transient_no_prefix( $args );
}

/**
* Build a transient key without the prefix.
*
* @param array $args
*
* @return string
*/
public function build_transient( array ...$args ): string {
return self::TRANSIENT_PREFIX . hash( 'sha256', json_encode( $args ) );
public function build_transient_no_prefix( array $args ): string {
return hash( 'sha256', json_encode( $args ) );
}

}
2 changes: 2 additions & 0 deletions src/Uplink/API/V3/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use StellarWP\Uplink\API\V3\Contracts\Client_V3;
use StellarWP\Uplink\Config;
use StellarWP\Uplink\Contracts\Abstract_Provider;
use StellarWP\Uplink\Storage\Contracts\Storage;
use WP_Http;

final class Provider extends Abstract_Provider {
Expand Down Expand Up @@ -74,6 +75,7 @@ private function register_token_authorizer(): void {
static function ( $c ) use ( $expiration ): Token_Authorizer {
return new Token_Authorizer_Cache_Decorator(
$c->get( Auth\Token_Authorizer::class ),
$c->get( Storage::class ),
$expiration
);
}
Expand Down
10 changes: 8 additions & 2 deletions src/Uplink/Admin/Ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ class Ajax {
*/
protected $container;

public function __construct() {
/**
* @var Group
*/
protected $group;

public function __construct( Group $group ) {
$this->container = Config::get_container();
$this->group = $group;
}

/**
Expand All @@ -29,7 +35,7 @@ public function validate_license(): void {
'key' => Utils\Sanitize::key( wp_unslash( $_POST['key'] ?? '' ) ),
];

if ( empty( $submission['key'] ) || ! wp_verify_nonce( $submission['_wpnonce'], $this->container->get( License_Field::class )->get_group_name() ) ) {
if ( empty( $submission['key'] ) || ! wp_verify_nonce( $submission['_wpnonce'], $this->group->get_name() ) ) {
wp_send_json_error( [
'status' => 0,
'message' => __( 'Invalid request: nonce field is expired. Please try again.', '%TEXTDOMAIN%' ),
Expand Down
Loading

0 comments on commit 45a14b6

Please sign in to comment.