Skip to content

Commit

Permalink
Merge pull request #136 from humanmade/tachyon-provider
Browse files Browse the repository at this point in the history
Add Tachyon Provider for AMF WP
  • Loading branch information
roborourke authored Jun 18, 2021
2 parents 3067f85 + 3879e84 commit 0ed8800
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 5 deletions.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
"humanmade/gaussholder": "1.1.3",
"humanmade/aws-rekognition": "~0.1.7",
"humanmade/rename-images-command": "^0.1.0",
"humanmade/asset-manager-framework": "^0.11.0",
"humanmade/asset-manager-framework": "^0.12.0",
"humanmade/amf-wordpress": "^0.2.0"
},
"autoload": {
"classmap": [
"inc/"
],
"files": [
"inc/namespace.php",
"inc/global_assets/namespace.php"
Expand Down
45 changes: 42 additions & 3 deletions docs/asset-manager-framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,58 @@ add_action( 'amf/register_providers', function ( ProviderRegistry $provider_regi

For a more complete example using Unsplash see the [AMF Unsplash integration plugin](https://github.com/humanmade/amf-unsplash) for reference.

### Extending Existing Providers
### Dynamic Image Resizing

Since you have access to each provider instance during registration via the `amf/provider` filter, you can also use it and decorate it:
AMF provides an interface to enable dynamic image resizing for your provider classes. The Global Media Library uses this to deliver assets via Tachyon out of the box.

To make a provider that can resize assets on the fly it needs to implement the `Resize` interface:

```php
use UnsplashProvider;
use AssetManagerFramework\Interfaces\{
Resize
};

class ResizingUnsplashProvider extends UnsplashProvider implements Resize {

public function resize( WP_Post $attachment, int $width, int $height, $crop = false ) : string {

$base_url = wp_get_attachment_url( $attachment->ID );

$query_args = [
'w' => $width,
'h' => $height,
'fit' => $crop ? 'crop' : 'clip',
'crop' => 'faces,focalpoint',
];

if ( is_array( $crop ) ) {
$crop = array_filter( $crop, function ( $value ) {
return $value !== 'center';
} );
$query_args['crop'] = implode( ',', $crop );
}

return add_query_args( urlencode_deep( $query_args ), $base_url );
}

}
```

### Modifying Existing Providers

Since you have access to each provider instance during registration via the `amf/provider` filter, you can also use it and decorate it, replace it with a subclass of a specific provider or replace it entirely:

```php
use AssetManagerFramework\Provider;
use ResizingUnsplashProvider;

add_filter( 'amf/provider', function ( Provider $provider, string $id ) {
if ( $provider->get_id() !== 'unsplash' ) {
return $provider;
}

return new DecoratingProvider( $provider );
return new ResizingUnsplashProvider();
}, 10, 2 );
```

Expand Down
104 changes: 104 additions & 0 deletions inc/global_assets/class-tachyon-provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* Tachyon Provider for Global Assets.
*
* @package altis/media
*/

namespace Altis\Media\Global_Assets;

use AMFWordPress\Provider;
use AssetManagerFramework\Interfaces\Resize;
use WP_Post;

/**
* Tachyon extension for the AMF WordPress provider.
*/
class Tachyon_Provider extends Provider implements Resize {

/**
* Handles resizing of an AMF WordPress attachment.
*
* @param WP_Post $attachment The attachment post.
* @param int $width Target width.
* @param int $height Target height.
* @param bool|array $crop If truthy crop to the given dimensions, can be a non-associative
* array of x and y positions where x is 'left', 'center' or 'right'
* and y is 'top', 'center' or 'bottom'.
* @return string The resized asset URL.
*/
public function resize( WP_Post $attachment, int $width, int $height, $crop = false ) : string {
// Determine resize method.
$method = $crop ? 'resize' : 'fit';

$tachyon_args = [
$method => "{$width},{$height}",
];

// If crop is true.
if ( $crop ) {
if ( is_array( $crop ) ) {
$tachyon_args['gravity'] = implode( '', array_map( function ( $v ) {
$map = [
'top' => 'north',
'center' => '',
'bottom' => 'south',
'left' => 'west',
'right' => 'east',
];
return $map[ $v ];
}, array_reverse( $crop ) ) );
} else {
$tachyon_args = array_merge(
$tachyon_args,
$this->get_crop( $attachment, $width, $height )
);
}
}

$url = add_query_arg(
urlencode_deep( $tachyon_args ),
wp_get_attachment_url( $attachment->ID )
);

return $url;
}

/**
* Get Tachyon crop arguments.
*
* Uses focal point meta data if provided.
*
* @param WP_Post $attachment The attachment post.
* @param integer $width The crop width.
* @param integer $height The crop height.
* @return array
*/
protected function get_crop( WP_Post $attachment, int $width, int $height ) : array {
$metadata = wp_get_attachment_metadata( $attachment->ID, true );

$focal_point = get_post_meta( $attachment->ID, '_focal_point', true );

if ( ! empty( $focal_point ) ) {
// Get max size of crop aspect ratio within original image.
$dimensions = wp_constrain_dimensions( $width, $height, $metadata['width'], $metadata['height'] );

if ( $dimensions[0] === $metadata['width'] && $dimensions[1] === $metadata['height'] ) {
return [];
}

$crop = [];
$crop['width'] = $dimensions[0];
$crop['height'] = $dimensions[1];

// Set x & y but constrain within original image bounds.
$crop['x'] = min( $metadata['width'] - $crop['width'], max( 0, $focal_point['x'] - ( $crop['width'] / 2 ) ) );
$crop['y'] = min( $metadata['height'] - $crop['height'], max( 0, $focal_point['y'] - ( $crop['height'] / 2 ) ) );

return [ 'crop' => sprintf( '%dpx,%dpx,%dpx,%dpx', $crop['x'], $crop['y'], $crop['width'], $crop['height'] ) ];
} else {
return [ 'crop_strategy' => 'smart' ];
}
}

}
24 changes: 23 additions & 1 deletion inc/global_assets/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Altis;
use Altis\Global_Content;
use Altis\Media;
use AMFWordPress\Factory;
use AssetManagerFramework\Provider;
use WP_Post;

/**
Expand Down Expand Up @@ -38,6 +40,11 @@ function bootstrap() {
return;
}

// Use Tachyon Provider.
if ( $config['tachyon'] ) {
add_filter( 'amf/provider', __NAMESPACE__ . '\\use_tachyon_provider' );
}

// Configure the global media site.
add_action( 'plugins_loaded', __NAMESPACE__ . '\\configure_site', 9 );
add_filter( 'altis.core.global_content_site_menu_pages', __NAMESPACE__ . '\\allow_media_pages' );
Expand Down Expand Up @@ -81,6 +88,21 @@ function maybe_load_amf_wp() {
require_once Altis\ROOT_DIR . '/vendor/humanmade/amf-wordpress/plugin.php';
}

/**
* Overrride the WordPress AMF Provider.
*
* @param Provider $provider The registered provider.
* @return Provider
*/
function use_tachyon_provider( Provider $provider ) : Provider {
// phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
if ( $provider->get_id() !== 'wordpress' ) {
return $provider;
}

return new Tachyon_Provider( new Factory() );
}

/**
* Create the Global Media Library site.
*/
Expand Down Expand Up @@ -149,7 +171,7 @@ function pre_upload_global_site_link() : void {
*/
function is_global_asset( int $attachment_id ) : bool {
// phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
return get_post_meta( $attachment_id, 'amf_provider', true ) === 'wordpress';
return get_post_meta( $attachment_id, '_amf_provider', true ) === 'wordpress';
}

/**
Expand Down

0 comments on commit 0ed8800

Please sign in to comment.