Skip to content

Commit

Permalink
Merge pull request #32 from Automattic/release/1.4.0
Browse files Browse the repository at this point in the history
Release 1.4.0
  • Loading branch information
GaryJones authored Jan 13, 2025
2 parents 8eee37a + 8110dc4 commit 1a18c69
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 15 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.0] - 2025-01-14

### Added
* Added upload custom WP-CLI command to upload a single attachment by @ovidiul in https://github.com/Automattic/s3-media-sync/pull/20
* Added documentation for WP-CLI commands by @GaryJones in https://github.com/Automattic/s3-media-sync/pull/31

## [1.3.0] - 2025-01-01

### Changed
Expand Down Expand Up @@ -39,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 1.0.0 - 2020-06-03
* Initial release.

[1.4.0]: https://github.com/Automattic/s3-media-sync/compare/1.3.0...1.4.0
[1.3.0]: https://github.com/Automattic/s3-media-sync/compare/1.2.0...1.3.0
[1.2.0]: https://github.com/Automattic/s3-media-sync/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/Automattic/s3-media-sync/compare/1.0.0...1.1.0
67 changes: 60 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,76 @@ Running one of the above commands will create a `vendor` directory which is requ
* Enter the provided AWS S3 API keys on the plugins's Settings page.
* Backfill the uploads directory on AWS by running the following command:

```
```sh
wp s3-media upload-all --url=example-site.com
```

## WP-CLI Commands

This plugin provides several WP-CLI commands for managing media uploads to S3.

### Upload a Single Attachment

To upload a single attachment to S3, use the following command:

```sh
wp s3-media upload <attachment_id>
```

**Example:**

```sh
wp s3-media upload 123
```

### Upload All Validated Media

To upload all validated media to S3, use the command:

```sh
wp s3-media upload-all [--threads=<number>]
```

**Options:**
- `--threads=<number>`: The number of concurrent threads to use for uploading. Defaults to 10 (range: 1-10).

**Example:**

```sh
wp s3-media upload-all --threads=5
```

### Remove Files from S3

To remove files from S3, use the command:

```sh
wp s3-media rm <path> [--regex=<regex>]
```

**Options:**
- `<path>`: The path of the file or directory to remove from S3.
- `--regex=<regex>`: Optional regex pattern to match files for deletion.

**Example:**

```sh
wp s3-media rm path/to/file.jpg
```

## Development

### Running Tests

This plugin uses PHPUnit for testing. To run the test suite:

1. Install development dependencies:
```
```sh
composer install
```

2. Install the WordPress test suite:
```
```sh
./bin/install-wp-tests.sh s3_media_sync_test root 'root' localhost latest
```

Expand All @@ -51,17 +104,17 @@ The install script parameters are:
- WordPress version: `latest`

3. Run tests:
```
```sh
composer test
```

For specific test files:
```
```sh
composer test -- tests/test-class-s3-media-sync-wp-cli.php
```

For coverage reports:
```
```sh
composer test -- --coverage-html coverage
```

Expand All @@ -81,7 +134,7 @@ Then, all media will automatically be kept in-sync within `my-awesome-site/prepr

You can check which attachments were skipped by running the following command:

```
```sh
wp vip migration validate-attachments invalid-attachments.csv --url=example-site.com
```

Expand Down
136 changes: 129 additions & 7 deletions inc/class-s3-media-sync-wp-cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,119 @@

use \WP_CLI\Utils;

/**
* Class S3_Media_Sync_WP_CLI_Command
*
* Provides WP-CLI commands for managing media uploads to S3.
*
* ## EXAMPLES
*
* # Upload a single attachment to S3.
* $ wp s3-media upload <attachment_id>
*
* # Upload all validated media to S3.
* $ wp s3-media upload-all
*
* # Remove files from S3.
* $ wp s3-media rm <path> [--regex=<regex>]
*/
class S3_Media_Sync_WP_CLI_Command extends WPCOM_VIP_CLI_Command {

/**
* Upload a single attachment to S3
*
* @synopsis <attachment_id>
*
* ## OPTIONS
*
* <attachment_id>
* : The ID of the attachment to upload to S3.
*
* ## EXAMPLES
*
* # Upload an attachment with ID 123 to S3.
* $ wp s3-media upload 123
*/
public function upload( $args, $assoc_args ) {
// Get the source and destination and initialize some concurrency variables
$from = wp_get_upload_dir();
$to = S3_Media_Sync::init()->get_s3_bucket_url();

$attachment_id = absint( $args[0] );

if ( $attachment_id === 0 ) {
WP_CLI::error( 'Invalid attachment ID.' );
}

$url = wp_get_attachment_url( $attachment_id );

if ( false === $url || '' === $url ) {
WP_CLI::error( 'Failed to retrieve attachment URL for ID: ' . $attachment_id );
}

// By switching the URLs from http:// to https:// we save a request, since it will be redirected to the SSL url
if ( is_ssl() ) {
$url = str_replace( 'http://', 'https://', $url );
}

$ch = curl_init();
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_NOBODY, true );

// Check for errors before setting options
if ( curl_errno( $ch ) ) {
WP_CLI::error( 'cURL error for attachment ID ' . $attachment_id . ': ' . curl_error( $ch ) );
}

$response = curl_exec( $ch );

// Check for errors after executing cURL request
if ( curl_errno( $ch ) ) {
WP_CLI::error( 'cURL error for attachment ID ' . $attachment_id . ': ' . curl_error( $ch ) );
}

$response_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close( $ch );

if ( 200 === $response_code ) {
// Process the response and upload the attachment to S3
$path = str_replace( $from['baseurl'], '', $url );

// Check if the file exists before copying it over
if ( ! is_file( trailingslashit( $to ) . 'wp-content/uploads' . $path ) ) {
copy( $from['basedir'] . $path, trailingslashit( $to ) . 'wp-content/uploads' . $path );
}
WP_CLI::success( 'Attachment ID ' . $attachment_id . ' successfully uploaded to S3.' );
} else {
WP_CLI::error( 'Failed to fetch attachment from URL for attachment ID ' . $attachment_id . ': ' . $url );
}
}

/**
* Upload all validated media to S3
*
* @subcommand upload-all
*/
*
* ## OPTIONS
*
* [--threads=<number>]
* : The number of concurrent threads to use for uploading. Defaults to 10.
* ---
* default: 10
* options:
* - 1-10
* ---
*
* ## EXAMPLES
*
* # Upload all media to S3 using the default number of threads.
* $ wp s3-media upload-all
*
* # Upload all media to S3 using 5 threads.
* $ wp s3-media upload-all --threads=5
*/
public function upload_all( $args, $assoc_args ) {
global $wpdb;

Expand Down Expand Up @@ -92,12 +198,28 @@ public function upload_all( $args, $assoc_args ) {
}

/**
* Remove files from S3
*
* Props S3 Uploads and HM: https://github.com/humanmade/S3-Uploads/
*
* @synopsis <path> [--regex=<regex>]
*/
* Remove files from S3
*
* Props S3 Uploads and HM: https://github.com/humanmade/S3-Uploads/
*
* @synopsis <path> [--regex=<regex>]
*
* ## OPTIONS
*
* <path>
* : The path of the file or directory to remove from S3.
*
* [--regex=<regex>]
* : Optional regex pattern to match files for deletion.
*
* ## EXAMPLES
*
* # Remove a specific file from S3.
* $ wp s3-media rm path/to/file.jpg
*
* # Remove all files matching a regex pattern from S3.
* $ wp s3-media rm path/to/files --regex='.*\.jpg'
*/
public function rm( $args, $args_assoc ) {
$s3 = S3_Media_Sync::init()->s3();
$bucket = S3_Media_Sync::init()->get_s3_bucket();
Expand Down
2 changes: 1 addition & 1 deletion s3-media-sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Requires PHP: 8.1
* Text Domain: s3-media-sync
* Domain Path: /languages/
* Version: 1.3.0
* Version: 1.4.0
*/

/**
Expand Down

0 comments on commit 1a18c69

Please sign in to comment.