Skip to content

Commit

Permalink
Merge pull request #1 from udx/develop-alexey
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
balexey88 authored Nov 24, 2023
2 parents 864eb39 + 4a0c3ae commit 64ff311
Show file tree
Hide file tree
Showing 25 changed files with 3,625 additions and 2 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Validate composer.json and composer.lock
run: composer validate

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress

- name: Run test suite
run: composer test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
.DS_Store
.vscode
37 changes: 35 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# wp-stateless-wp-smushit-addon
WP-Stateless - Smash Addon
# WP-Stateless - Smush Addon

Provides compatibility between the [Smush](https://wordpress.org/plugins/wp-smushit/) and the [WP-Stateless](https://wordpress.org/plugins/wp-stateless/) plugins.

### Features

* Sync images optimized by Smush plugin with Google Cloud Storage.

### Notes

* Tested with Smush plugin version 3.15.1

### Support, Feedback, & Contribute

We welcome community involvement via the [GitHub repository](https://github.com/udx/wp-stateless-wp-smushit-addon).

### Frequently Asked Questions

<details>
<summary>Where can I submit feature requests or bug reports?</summary>

We encourage community feedback and discussion through issues on the [GitHub repository](https://github.com/udx/wp-stateless-wp-smushit-addon/issues).
</details>

<details>
<summary>Can I test new features before they are released?</summary>

To ensure new releases cause as little disruption as possible, we rely on early adopters who assist us by testing out new features before they are released. [Please contact us](https://udx.io/) if you are interested in becoming an early adopter.
</details>

<details>
<summary>Who maintains this plugin?</summary>

[UDX](https://udx.io/) maintains this plugin by continuing development through its own staff, reviewing pull requests, testing, and steering the overall release schedule. UDX is located in Durham, North Carolina, and provides WordPress engineering and hosting services to clients throughout the United States.
</details>
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
== Changelog ==
= 0.0.1 =
* Initial public release.
3 changes: 3 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#### 0.0.1

- Initial public release.
234 changes: 234 additions & 0 deletions class-wp-smushit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
<?php
/**
* Compatibility Plugin Name: Smush – Optimize, Compress and Lazy Load Images
* Compatibility Plugin URI: https://wordpress.org/plugins/wp-smushit/
*
* Compatibility Description: Sync images optimized by Smush plugin.
*
*/

namespace WPSL\Smush;

use wpCloud\StatelessMedia\Compatibility;

class Smush extends Compatibility {
protected $id = 'wp-smush';
protected $title = 'WP Smush';
protected $constant = 'WP_STATELESS_COMPATIBILITY_WPSMUSH';
protected $description = 'Ensures compatibility with WP Smush.';
protected $plugin_file = ['wp-smushit/wp-smush.php', 'wp-smush-pro/wp-smush.php', 'wp-smushit-pro/wp-smush-pro.php'];

/**
* @param $sm
*/
public function module_init($sm) {
add_action('wp_smush_image_optimised', array($this, 'image_optimized'), 10, 2);
// Check if the file not exists for the given path then download
// Useful in Ephemeral mode
add_action('smush_file_exists', array($this, 'maybe_download_file'), 10, 3);

// Skip sync when attachment is image, sync will be handled after image is optimized.
// add_filter( 'wp_stateless_skip_add_media', array( $this, 'skip_add_media' ), 10, 5 );

add_filter('delete_attachment', array($this, 'remove_backup'));
add_filter('smush_backup_exists', array($this, 'backup_exists_on_gcs'), 10, 3);
add_action('sm:synced::image', array($this, 'sync_backup'), 10, 2);
}

/**
* Whether to skip the sync on image upload before the image is optimized.
* The sync is skipped if the image is compatible with Smush.
*
* The image will be synced after it's get optimized using the 'wp_smush_image_optimised' action.
*
*
* @param bool $return This should return true if want to skip the sync.
* @param int $metadata Metadata for the attachment.
* @param string $attachment_id Attachment ID.
* @param bool $force Whether to force the sync even the file already exist in GCS.
* @param bool $args Whether to only sync the full size image.
*
* @return bool $return True to skip the sync and false to do the sync.
*
*/
public function skip_add_media($return, $metadata, $attachment_id, $force = false, $args = array()) {
global $doing_manual_sync;

if ($force || $doing_manual_sync) return false;

if (class_exists('WP_Smush_Modules')) {
$auto_smush = \WP_Smush::get_instance()->core()->mod->settings->get('auto');
} else {
global $wpsmush_settings;
$auto_smush = $wpsmush_settings->settings['auto'];
}

if (
!$auto_smush || !wp_attachment_is_image($attachment_id) ||
!apply_filters('wp_smush_image', true, $attachment_id) ||
!(
((!empty($_POST['action']) && 'upload-attachment' == $_POST['action']) || isset($_POST['post_id'])) &&
// And, check if Async is enabled.
defined('WP_SMUSH_ASYNC') && WP_SMUSH_ASYNC)
) {
return false;
}
return true;
}

/**
* Sync image after it's been optimized.
*
* @param int $attachment_id attachment id
* @param array $stats compression stats
*
* @return null
*/
public function image_optimized($attachment_id, $stats) {
// Sync the attachment to GCS
ud_get_stateless_media()->add_media(array(), $attachment_id, true);

// also sync the backup images
$this->sync_backup($attachment_id);
}

/**
* If local file don't exists then download it from GCS
*
* @param string $file_path Full file path
* @param string $attachment_id
* @param array $size_details Array of width and height for the image
*
* @return null
*/
function maybe_download_file($file_path = '', $attachment_id = '', $size_details = array()) {
if (empty($file_path) || empty($attachment_id)) {
return;
}

//Download if file not exists
if (!file_exists($file_path)) {
$client = ud_get_stateless_media()->get_client();
$metadata = wp_get_attachment_metadata($attachment_id);
if (!empty($metadata['gs_name'])) {
$image_sizes = Utility::get_path_and_url($metadata, $attachment_id);
foreach ($image_sizes as $size => $img) {
$client->get_media(apply_filters('wp_stateless_file_name', $img['gs_name']), true, $img['path']);
}

$gs_name = dirname($metadata['gs_name']) . '/' . basename($file_path);
// We need to remove backup from GCS if it's a restore action
// @todo revise this code
if ($this->hook_from_restore_image()) {
$client->remove_media(apply_filters('wp_stateless_file_name', $gs_name));
}
}
}
}

/**
* Remove backup when attachment is removed
*
* @param $attachment_id
*/
function remove_backup($attachment_id) {
$upload_dir = wp_get_upload_dir();
$metadata = wp_get_attachment_metadata($attachment_id);
$backup_paths = get_post_meta($attachment_id, '_wp_attachment_backup_sizes', true);

if (!empty($metadata['gs_name']) && !empty($backup_paths) && is_array($backup_paths)) {
// Getting local dir path for backup image
$base_dir = $upload_dir['basedir'] . '/' . dirname($metadata['file']);
// Getting GCS dir name from meta data. In case Bucket Folder used.
$gs_dir = dirname($metadata['gs_name']);
foreach ($backup_paths as $key => $data) {
$gs_name = $gs_dir . '/' . basename($data['file']);
// Path of backup image
$backup_path = $base_dir . '/' . basename($data['file']);
do_action('sm:sync::deleteFile', apply_filters('wp_stateless_file_name', $gs_name), $backup_path);
delete_transient('sm-wp-smush-backup-exists-' . $attachment_id);
}
}
}

/**
* Checks if we've backup on gcs for the given attachment id and backup path
*
* @param string $attachment_id
* @param string $backup_path
*
* @return bool
*/
function backup_exists_on_gcs($exists, $attachment_id = '', $backup_path = '') {
if (!$exists && $attachment_id) {
if (get_transient('sm-wp-smush-backup-exists-' . $attachment_id)) {
return true;
}

$metadata = wp_get_attachment_metadata($attachment_id);
if (!empty($metadata['gs_name'])) {
$gs_name = dirname($metadata['gs_name']) . '/' . basename($backup_path);
if (ud_get_stateless_media()->get_client()->media_exists(apply_filters('wp_stateless_file_name', $gs_name))) {
set_transient('sm-wp-smush-backup-exists-' . $attachment_id, true, HOUR_IN_SECONDS);
return true;
}
}
}

return $exists;
}

/**
* Sync backup image to GCS
*
* @param $attachment_id
* @param array $metadata
*/
public function sync_backup($attachment_id, $metadata = array()) {
$upload_dir = wp_get_upload_dir();
if (empty($metadata) || empty($metadata['gs_name'])) {
$metadata = wp_get_attachment_metadata($attachment_id);
}

// Getting backup path from smush settings in db
$backup_paths = get_post_meta($attachment_id, '_wp_attachment_backup_sizes', true);

if (!empty($metadata['gs_name']) && !empty($backup_paths) && is_array($backup_paths)) {
// Getting local dir for backup image
$base_dir = $upload_dir['basedir'] . '/' . dirname($metadata['file']);
// Getting GCS dir name from meta data. In case Bucket Folder used.
$gs_dir = dirname($metadata['gs_name']);

foreach ($backup_paths as $key => $data) {
$gs_name = $gs_dir . '/' . basename($data['file']);
// Path of backup image
$backup_path = $base_dir . '/' . basename($data['file']);
// Sync backup image with GCS
do_action('sm:sync::syncFile', apply_filters('wp_stateless_file_name', $gs_name), $backup_path);
delete_transient('sm-wp-smush-backup-exists-' . $attachment_id);
}
}
}

/**
* Determine where we hook from
* Is this a hook from wp smush restore image or not.
*
* @return bool
*/
private function hook_from_restore_image() {
$call_stack = debug_backtrace();
$class_name = class_exists('WpSmushBackup') ? 'WpSmushBackup' : 'WP_Smush_Backup';

if (!empty($call_stack) && is_array($call_stack)) {
foreach ($call_stack as $step) {

if ($step['function'] == 'restore_image' && $step['class'] == $class_name) {
return true;
}
}
}

return false;
}
}
31 changes: 31 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "udx/wp-stateless-wp-smushit-addon",
"description": "Ensures compatibility with Smush",
"type": "wordpress-plugin",
"license": "MIT",
"authors": [
{
"name": "UDX",
"email": "[email protected]"
}
],
"minimum-stability": "stable",
"require-dev": {
"phpunit/phpunit": "^9.5",
"brain/monkey": "2.*"
},
"autoload": {
"files": [
"class-wp-smushit.php"
]
},
"scripts": {
"test": [
"@composer install",
"./vendor/bin/phpunit --prepend tests/prepend.php tests/ --testdox"
]
},
"scripts-descriptions": {
"test": "Run all tests."
}
}
Loading

0 comments on commit 64ff311

Please sign in to comment.