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

Add Adapter for JW Player #8

Merged
merged 12 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
126 changes: 43 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,27 @@ Contributors: alleyinteractive

Tags: alleyinteractive, wp-video-sync

Stable tag: 0.0.0
Stable tag: 0.1.0

Requires at least: 5.9
Requires at least: 6.6

Tested up to: 6.1
Tested up to: 6.6

Requires PHP: 8.1
Requires PHP: 8.2

License: GPL v2 or later

[![Coding Standards](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/coding-standards.yml/badge.svg)](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/coding-standards.yml)
[![Testing Suite](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/unit-test.yml/badge.svg)](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/unit-test.yml)
[![Testing Suite](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/all-pr-tests.yml/badge.svg)](https://github.com/alleyinteractive/wp-video-sync/actions/workflows/all-pr-tests.yml)

Sync videos from a hosting provider to WordPress.

Runs a scheduled task to sync videos from a supported video hosting provider to WordPress in batches based on the last modified date of the video. Implementers are responsible for installing and configuring a compatible plugin, choosing it as an adapter, and defining the callback that will be run for each video, which will be responsible for performing any post creations or updates in WordPress.

This plugin is a great way to sync videos uploaded to a hosting provider (such as JW Player) to WordPress, such that the video itself remains on the hosting provider, but the video can be displayed in WordPress using a player block or shortcode, appears at its own unique URL, and can be included in search results.

## Installation

You can install the package via composer:
You can install the package via Composer:

```bash
composer require alleyinteractive/wp-video-sync
Expand All @@ -32,90 +35,47 @@ composer require alleyinteractive/wp-video-sync
Activate the plugin in WordPress and use it like so:

```php
$plugin = Alley\WP\WP_Video_Sync\WP_Video_Sync\WP_Video_Sync();
$plugin->perform_magic();
use Alley\WP\WP_Video_Sync\Adapters\JW_Player_7_For_WP;
use Alley\WP\WP_Video_Sync\Sync_Manager;
use DateTimeImmutable;
use WP_Query;

$sync_manager = Sync_Manager::init()
->with_adapter( new JW_Player_7_For_WP() )
->with_frequency( 'hourly' )
->with_callback(
function ( $video ) {
$existing_video = new WP_Query( [ 'meta_key' => 'jwplayer_id', 'meta_value' => $video->id ] );
$existing_id = $existing_video->posts[0]->ID ?? 0;
wp_insert_post(
[
'ID' => $existing_id,
'post_title' => $video->metadata->title,
'post_date' => DateTimeImmutable::createFromFormat( DATE_W3C, $video->created )->format( 'Y-m-d H:i:s' ),
'post_modified' => DateTimeImmutable::createFromFormat( DATE_W3C, $video->last_modified )->format( 'Y-m-d H:i:s' ),
'meta_input' => [
'jwplayer_id' => $video->id,
],
]
);
}
);
```
<!--front-end-->
## Testing

Run `npm run test` to run Jest tests against JavaScript files. Run
`npm run test:watch` to keep the test runner open and watching for changes.

Run `npm run lint` to run ESLint against all JavaScript files. Linting will also
happen when running development or production builds.

Run `composer test` to run tests against PHPUnit and the PHP code in the plugin.

### The `entries` directory and entry points

All directories created in the `entries` directory can serve as entry points and will be compiled with [@wordpress/scripts](https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/README.md#scripts) into the `build` directory with an accompanied `index.asset.php` asset map.

#### Scaffolding an entry point

To generate a new entry point, run the following command:
This will configure the plugin to import a batch of 100 videos every hour from JW Player, sorted by least to most recently updated, starting with the date and time of the last video that was updated. If videos have already been imported (as identified by the postmeta value saved for the unique video ID) they will be updated rather than created. New videos will be created. The example code above uses the `post` post type for this purpose, but the code could easily be adapted to use a custom post type. Additionally, the post content could be set to include a Gutenberg block or a shortcode for a player.

```sh
npm run create-entry
```

To generate a new slotfill, run the following command:

```sh
npm run create-slotfill
```

The command will prompt the user through several options for creating an entry or slotfill. The entries are scaffolded with the `@alleyinteractive/create-entry` script. Run the help command to see all the options:

```sh
npx @alleyinteractive/create-entry --help
```
[Visit the package README](https://www.npmjs.com/package/@alleyinteractive/create-entry) for more information.
### Supported Adapters

#### Enqueuing Entry Points
As of now, the plugin only supports JW Player 7 for WordPress (both the free and premium versions). Other adapters may be added in the future.

You can also include an `index.php` file in the entry point directory for enqueueing or registering a script. This file will then be moved to the build directory and will be auto-loaded with the `load_scripts()` function in the `functions.php` file. Alternatively, if a script is to be enqueued elsewhere there are helper functions in the `src/assets.php` file for getting the assets.
#### JW Player 7 for WordPress

### Scaffold a dynamic block with `create-block`

Use the `create-block` command to create custom blocks with [@alleyinteractive/create-block](https://github.com/alleyinteractive/alley-scripts/tree/main/packages/create-block) script and follow the prompts to generate all the block assets in the `blocks/` directory.
Block registration, script creation, etc will be scaffolded from the `create-block` script. Run `npm run build` to compile and build the custom block. Blocks are enqueued using the `load_scripts()` function in `src/assets.php`.

### Updating WP Dependencies

Update the [WordPress dependency packages](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/#packages-update) used in the project to their latest version.

To update `@wordpress` dependencies to their latest version use the packages-update command:

```sh
npx wp-scripts packages-update
```

This script provides the following custom options:

- `--dist-tag` – allows specifying a custom dist-tag when updating npm packages. Defaults to `latest`. This is especially useful when using [`@wordpress/dependency-extraction-webpack-plugin`](https://www.npmjs.com/package/@wordpress/dependency-extraction-webpack-plugin). It lets installing the npm dependencies at versions used by the given WordPress major version for local testing, etc. Example:

```sh
npx wp-scripts packages-update --dist-tag=wp-WPVERSION`
```

Where `WPVERSION` is the version of WordPress you are targeting. The version
must include both the major and minor version (e.g., `6.1`). For example:

```sh
npx wp-scripts packages-update --dist-tag=wp-6.1`
```
- Requires the [JW Player 7 for WordPress](https://wordpress.org/plugins/jw-player-7-for-wp/) plugin to be installed, activated, and properly configured with access credentials. Also supports the premium version.
- The video object in the callback is a `stdClass` with the properties described in the `media` object under response code `200` in [the JW Player API documentation for the media list endpoint](https://docs.jwplayer.com/platform/reference/get_v2-sites-site-id-media).

## Releasing the Plugin

The plugin uses a [built release workflow](./.github/workflows/built-release.yml)
to compile and tag releases. Whenever a new version is detected in the root
`composer.json` file or in the plugin's headers, the workflow will automatically
build the plugin and tag it with a new version. The built tag will contain all
the required front-end assets the plugin may require. This works well for
publishing to WordPress.org or for submodule-ing.

When you are ready to release a new version of the plugin, you can run
`npm run release` to start the process of setting up a new release.
New versions of this plugin will be created as releases in GitHub once ready.

## Changelog

Expand All @@ -132,4 +92,4 @@ with us](https://alley.co/careers/).

## License

The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.
The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.
66 changes: 66 additions & 0 deletions src/adapters/class-jw-player-7-for-wp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* WP Video Sync: JW Player 7 for WP Adapter
*
* @package wp-video-sync
*/

namespace Alley\WP\WP_Video_Sync\Adapters;

use Alley\WP\WP_Video_Sync\Interfaces\Adapter;
use DateTimeImmutable;
use stdClass;

/**
* JW Player 7 for WP Adapter. Supports both the free and premium versions of the plugin.
*/
class JW_Player_7_For_WP implements Adapter {
/**
* The date of the last modification to the last batch of videos.
*
* @var DateTimeImmutable
*/
private DateTimeImmutable $last_modified_date;
kevinfodness marked this conversation as resolved.
Show resolved Hide resolved

/**
* Fetches the date of the last modification to the last batch of videos.
*
* @return ?DateTimeImmutable
*/
public function get_last_modified_date(): ?DateTimeImmutable {
return $this->last_modified_date;
}

/**
* Fetches videos from JW Player that were modified after the provided DateTime.
*
* @param DateTimeImmutable $updated_after Return videos modified after this date.
*
* @return stdClass[] An array of video data.
*/
public function get_videos( DateTimeImmutable $updated_after ): array {
// Check if the JW Player 7 for WP plugin is active (free or premium).
if ( class_exists( 'JWPPP_Dashboard_Api' ) ) {
$api = new \JWPPP_Dashboard_Api();
$result = $api->call(
sprintf(
'media/?q=last_modified:[%s TO *]&page=1&page_length=100&sort=last_modified:asc',
$updated_after->format( 'Y-m-d' )
)
);
$videos = $result->media ?? [];

// Attempt to set the last modified date.
if ( isset( $videos[ count( $videos ) - 1 ]->last_modified ) ) {
$last_modified_date = DateTimeImmutable::createFromFormat( DATE_W3C, $videos[ count( $videos ) - 1 ]->last_modified );
if ( $last_modified_date instanceof DateTimeImmutable ) {
$this->last_modified_date = $last_modified_date;
}
}

return $videos;
}

return [];
}
}
34 changes: 34 additions & 0 deletions src/autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* WP Video Sync: Autoloader
*
* @package wp-video-sync
*/

namespace Alley\WP\WP_Video_Sync;

/**
* Autoload classes.
*
* @param string $class Class name.
*/
function autoload( string $class ): void {
// Only autoload classes for this namespace.
$class = ltrim( $class, '\\' );
if ( strpos( $class, __NAMESPACE__ . '\\' ) !== 0 ) {
return;
}

$class = strtolower( str_replace( [ __NAMESPACE__ . '\\', '_' ], [ '', '-' ], $class ) );
$dirs = explode( '\\', $class );
$class = array_pop( $dirs );

// Negotiate filename.
$filename = ! in_array( 'interfaces', $dirs, true )
? 'class-' . $class . '.php'
: $class . '.php';

require_once __DIR__ . '/' . implode( '/', $dirs ) . '/' . $filename;
}

spl_autoload_register( '\Alley\WP\WP_Video_Sync\autoload' );
Loading