first commit
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
if (!class_exists('WP_Optimize_WebP_Images')) :
|
||||
|
||||
class WP_Optimize_WebP_Images {
|
||||
|
||||
private $directory = '';
|
||||
|
||||
private $filename = '';
|
||||
|
||||
private $original_extension = '';
|
||||
|
||||
private $webp_extension = '.webp';
|
||||
|
||||
private $meta = false;
|
||||
|
||||
private $sizes = array();
|
||||
|
||||
private $images = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
add_action('delete_attachment', array($this, 'delete_related_images'), 10, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns singleton instance
|
||||
*
|
||||
* @return WP_Optimize_WebP_Images
|
||||
*/
|
||||
public static function get_instance() {
|
||||
static $instance = null;
|
||||
if (null === $instance) {
|
||||
$instance = new WP_Optimize_WebP_Images();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes related image sizes and alternate webp format images
|
||||
*
|
||||
* @param int $attachment_id
|
||||
* @return void
|
||||
*/
|
||||
public function delete_related_images($attachment_id) {
|
||||
$this->set_meta($attachment_id);
|
||||
$this->set_file_info_properties($attachment_id);
|
||||
$this->set_sizes();
|
||||
$this->set_images();
|
||||
$this->delete_images();
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets meta property with attachment metadata
|
||||
*
|
||||
* @param int $attachment_id
|
||||
* @return void
|
||||
*/
|
||||
private function set_meta($attachment_id) {
|
||||
$this->meta = wp_get_attachment_metadata($attachment_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets file information properties
|
||||
*
|
||||
* @param int $attachment_id
|
||||
* @return void
|
||||
*/
|
||||
private function set_file_info_properties($attachment_id) {
|
||||
$file_path = get_attached_file($attachment_id);
|
||||
$file_path_info = pathinfo($file_path);
|
||||
$this->filename = $file_path_info['filename'];
|
||||
$this->original_extension = '.' . $file_path_info['extension'];
|
||||
|
||||
$file = isset($this->meta['file']) ? $this->meta['file'] : '';
|
||||
$basename = $file_path_info['basename'];
|
||||
$sub_directory = '';
|
||||
if (!empty($file)) {
|
||||
$sub_directory = str_replace($basename, '', $file);
|
||||
}
|
||||
|
||||
$uploads = wp_get_upload_dir();
|
||||
$this->directory = $uploads['basedir'] . '/' . $sub_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all available image sizes for the given attachment id
|
||||
*/
|
||||
private function set_sizes() {
|
||||
if (false !== $this->meta) {
|
||||
$this->sizes = isset($this->meta['sizes']) ? $this->meta['sizes'] : array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets images property
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function set_images() {
|
||||
$webp_format = $this->directory . $this->filename . $this->original_extension . $this->webp_extension;
|
||||
$this->images[] = $webp_format;
|
||||
|
||||
foreach ($this->sizes as $size) {
|
||||
$original_format = $this->directory . $this->filename . '-' . $size['width'] . 'x' . $size['height'] . $this->original_extension;
|
||||
$this->images[] = $original_format;
|
||||
$webp_format = $this->directory . preg_replace('/-scaled$/', '', $this->filename) . '-' . $size['width'] . 'x' . $size['height'] . $this->original_extension . $this->webp_extension;
|
||||
$this->images[] = $webp_format;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related images
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function delete_images() {
|
||||
foreach ($this->images as $image) {
|
||||
wp_delete_file($image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset class property values
|
||||
*/
|
||||
private function reset() {
|
||||
$this->directory = '';
|
||||
$this->filename = '';
|
||||
$this->original_extension = '';
|
||||
$this->meta = false;
|
||||
$this->sizes = array();
|
||||
$this->images = array();
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
400
wp-content/plugins/wp-optimize/webp/class-wp-optimize-webp.php
Normal file
400
wp-content/plugins/wp-optimize/webp/class-wp-optimize-webp.php
Normal file
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
if (!class_exists('WP_Optimize_WebP')) :
|
||||
|
||||
class WP_Optimize_WebP {
|
||||
|
||||
private $_htaccess = null;
|
||||
|
||||
private $_rewrite_status = '';
|
||||
|
||||
private $_should_use_webp = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
if ($this->should_run_webp_conversion_test()) {
|
||||
$this->set_converter_status();
|
||||
}
|
||||
|
||||
if ($this->get_webp_conversion_test_result()) {
|
||||
$this->maybe_set_rewrite_status();
|
||||
if (!is_admin()) {
|
||||
$this->maybe_decide_webp_serve_method();
|
||||
}
|
||||
} else {
|
||||
$this->empty_htaccess_file();
|
||||
}
|
||||
|
||||
$this->init_webp_cron_scheduler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns singleton instance
|
||||
*
|
||||
* @return WP_Optimize_WebP
|
||||
*/
|
||||
public static function get_instance() {
|
||||
static $instance = null;
|
||||
if (null === $instance) {
|
||||
$instance = new WP_Optimize_WebP();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Run and find converter status
|
||||
*/
|
||||
private function set_converter_status() {
|
||||
if (!class_exists('WPO_WebP_Test_Run')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wpo-webp-test-run.php';
|
||||
}
|
||||
$converter_status = WPO_WebP_Test_Run::get_converter_status();
|
||||
if ($this->is_webp_conversion_successful()) {
|
||||
WP_Optimize()->get_options()->update_option('webp_conversion_test', true);
|
||||
WP_Optimize()->get_options()->update_option('webp_converters', $converter_status['working_converters']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* May be set server's rewrite status
|
||||
*/
|
||||
private function maybe_set_rewrite_status() {
|
||||
$this->_should_use_webp = WP_Optimize()->get_options()->get_option('webp_conversion');
|
||||
if ($this->_should_use_webp) {
|
||||
$this->set_rewrite_status();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets server's rewrite status
|
||||
*/
|
||||
private function set_rewrite_status() {
|
||||
$this->_rewrite_status = WP_Optimize()->get_options()->get_option('rewrite_status', false);
|
||||
if ('true' === $this->_rewrite_status) {
|
||||
$this->setup_htaccess_file();
|
||||
return;
|
||||
} elseif ('false' === $this->_rewrite_status) return;
|
||||
|
||||
if (!class_exists('WPO_Htaccess_Capabilities')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wpo-htaccess-capabilities.php';
|
||||
}
|
||||
$htc = WPO_Htaccess_Capabilities::get_instance();
|
||||
|
||||
if ($htc->htaccess_enabled && $htc->mod_rewrite && $htc->mod_headers && $htc->mod_mime) {
|
||||
$this->_rewrite_status = 'true';
|
||||
$this->setup_htaccess_file();
|
||||
} else {
|
||||
$this->_rewrite_status = 'false';
|
||||
}
|
||||
WP_Optimize()->get_options()->update_option('rewrite_status', $this->_rewrite_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* If webp images should be used, then decide whether it is possible to server webp
|
||||
* using rewrite rules or using altered html method
|
||||
*/
|
||||
private function maybe_decide_webp_serve_method() {
|
||||
if ('true' === $this->_rewrite_status) {
|
||||
if (!$this->_should_use_webp) {
|
||||
$this->empty_htaccess_file();
|
||||
} else {
|
||||
$this->save_htaccess_rules();
|
||||
if (!$this->is_webp_redirection_possible()) {
|
||||
$this->empty_htaccess_file();
|
||||
$this->maybe_use_alter_html();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->_should_use_webp) {
|
||||
$this->maybe_use_alter_html();
|
||||
} else {
|
||||
$this->empty_htaccess_file();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If alter html method is possible, then use it
|
||||
*/
|
||||
private function maybe_use_alter_html() {
|
||||
if ($this->is_alter_html_possible()) {
|
||||
$this->use_alter_html();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Even if server support .htaccess rewrite, sometimes it is not possible
|
||||
* to serve webp images. So, find it webp redirection is possible or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_webp_redirection_possible() {
|
||||
$redirection_possible = WP_Optimize()->get_options()->get_option('redirection_possible');
|
||||
if ($redirection_possible) {
|
||||
return 'true' === $redirection_possible;
|
||||
}
|
||||
return $this->run_webp_serving_self_test();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether the browser requesting the URL can accept webp images or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_browser_accepting_webp() {
|
||||
return (isset($_SERVER['HTTP_ACCEPT']) && false !== strpos($_SERVER['HTTP_ACCEPT'], 'image/webp'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect whether using alter HTML method is possible or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_alter_html_possible() {
|
||||
if ($this->is_browser_accepting_webp()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup alter html method
|
||||
*/
|
||||
private function use_alter_html() {
|
||||
if (!class_exists('WPO_WebP_Alter_HTML')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wpo-webp-alter-html.php';
|
||||
}
|
||||
WPO_WebP_Alter_HTML::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize .htaccess
|
||||
*/
|
||||
private function setup_htaccess_file() {
|
||||
if (null !== $this->_htaccess) return;
|
||||
$wp_uploads = wp_get_upload_dir();
|
||||
$htaccess_file = $wp_uploads['basedir'] . '/.htaccess';
|
||||
if (!file_exists($htaccess_file)) {
|
||||
file_put_contents($htaccess_file, '');
|
||||
}
|
||||
if (!class_exists('WP_Optimize_Htaccess')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'includes/class-wp-optimize-htaccess.php';
|
||||
}
|
||||
$this->_htaccess = new WP_Optimize_Htaccess($htaccess_file);
|
||||
$this->add_webp_mime_type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save .htaccess rules
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function save_htaccess_rules() {
|
||||
$htaccess_comment_section = 'WP-Optimize WebP Rules';
|
||||
if ($this->_htaccess->is_commented_section_exists($htaccess_comment_section)) return false;
|
||||
$this->_htaccess->update_commented_section($this->prepare_webp_htaccess_rules(), $htaccess_comment_section);
|
||||
$this->_htaccess->write_file();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty .htaccess file
|
||||
*/
|
||||
public function empty_htaccess_file() {
|
||||
$this->setup_htaccess_file();
|
||||
$htaccess_comment_sections = array(
|
||||
'WP-Optimize WebP Rules',
|
||||
'Register webp mime type',
|
||||
);
|
||||
foreach ($htaccess_comment_sections as $htaccess_comment_section) {
|
||||
$this->_htaccess->remove_commented_section($htaccess_comment_section);
|
||||
$this->_htaccess->write_file();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare array of htaccess rules to use webp images.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function prepare_webp_htaccess_rules() {
|
||||
return array(
|
||||
array(
|
||||
'<IfModule mod_rewrite.c>',
|
||||
'RewriteEngine On',
|
||||
'',
|
||||
'# Redirect to existing converted image in same dir (if browser supports webp)',
|
||||
'RewriteCond %{HTTP_ACCEPT} image/webp',
|
||||
'RewriteCond %{REQUEST_FILENAME} (?i)(.*)(\.jpe?g|\.png)$',
|
||||
'RewriteCond %1%2\.webp -f',
|
||||
'RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1%2\.webp [T=image/webp,E=EXISTING:1,E=ADDVARY:1,L]',
|
||||
'',
|
||||
'# Make sure that browsers which does not support webp also gets the Vary:Accept header',
|
||||
'# when requesting images that would be redirected to webp on browsers that does.',
|
||||
array(
|
||||
'<IfModule mod_headers.c>',
|
||||
array(
|
||||
'<FilesMatch "(?i)\.(jpe?g|png)$">',
|
||||
'Header append "Vary" "Accept"',
|
||||
'</FilesMatch>',
|
||||
),
|
||||
'</IfModule>',
|
||||
),
|
||||
'',
|
||||
'</IfModule>',
|
||||
'',
|
||||
),
|
||||
array(
|
||||
'# Rules for handling requests for webp images',
|
||||
'# ---------------------------------------------',
|
||||
'',
|
||||
'# Set Vary:Accept header if we came here by way of our redirect, which set the ADDVARY environment variable',
|
||||
'# The purpose is to make proxies and CDNs aware that the response varies with the Accept header',
|
||||
'<IfModule mod_headers.c>',
|
||||
array(
|
||||
'<IfModule mod_setenvif.c>',
|
||||
'# Apache appends "REDIRECT_" in front of the environment variables defined in mod_rewrite, but LiteSpeed does not',
|
||||
'# So, the next lines are for Apache, in order to set environment variables without "REDIRECT_"',
|
||||
'SetEnvIf REDIRECT_EXISTING 1 EXISTING=1',
|
||||
'SetEnvIf REDIRECT_ADDVARY 1 ADDVARY=1',
|
||||
'',
|
||||
'Header append "Vary" "Accept" env=ADDVARY',
|
||||
'',
|
||||
'# Set X-WPO-WebP header for diagnose purposes',
|
||||
'Header set "X-WPO-WebP" "Redirected directly to existing webp" env=EXISTING',
|
||||
'</IfModule>',
|
||||
),
|
||||
'</IfModule>',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add webp mime type to htaccess rules.
|
||||
*/
|
||||
private function add_webp_mime_type() {
|
||||
$htaccess_comment_section = 'Register webp mime type';
|
||||
if ($this->_htaccess->is_exists() && !$this->_htaccess->is_commented_section_exists($htaccess_comment_section)) {
|
||||
$webp_mime_type = array(
|
||||
array(
|
||||
'<IfModule mod_mime.c>',
|
||||
'AddType image/webp .webp',
|
||||
'</IfModule>',
|
||||
),
|
||||
);
|
||||
$this->_htaccess->update_commented_section($webp_mime_type, $htaccess_comment_section);
|
||||
$this->_htaccess->write_file();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether webp conversion test is successful or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_webp_conversion_successful() {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$destination = $upload_dir['basedir']. '/wpo/images/wpo_logo_small.png.webp';
|
||||
return file_exists($destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether sample webp conversion test should be run or not
|
||||
*
|
||||
* @return bool Returns true if sample test should be run, false otherwise
|
||||
*/
|
||||
private function should_run_webp_conversion_test() {
|
||||
$webp_conversion_test = $this->get_webp_conversion_test_result();
|
||||
return (true != $webp_conversion_test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns webp conversion test result
|
||||
*/
|
||||
private function get_webp_conversion_test_result() {
|
||||
return WP_Optimize()->get_options()->get_option('webp_conversion_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the webp redirection is possible or not and sets flag
|
||||
*
|
||||
* @return bool Returns true if webp is served successfully, false otherwise
|
||||
*/
|
||||
private function run_webp_serving_self_test() {
|
||||
if (!class_exists('WPO_WebP_Self_Test')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wpo-webp-self-test.php';
|
||||
}
|
||||
$self_test = WPO_WebP_Self_Test::get_instance();
|
||||
|
||||
if ($self_test->get_webp_image()) {
|
||||
$this->save_htaccess_rules();
|
||||
if ($self_test->is_webp_served()) {
|
||||
WP_Optimize()->get_options()->update_option('redirection_possible', 'true');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
WP_Optimize()->get_options()->update_option('redirection_possible', 'false');
|
||||
$this->empty_htaccess_file();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets webp serving method by setting all flags status to false
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function reset_webp_serving_method() {
|
||||
$options = WP_Optimize()->get_options();
|
||||
$options->update_option('redirection_possible', false);
|
||||
$options->update_option('webp_conversion_test', false);
|
||||
$options->update_option('webp_converters', false);
|
||||
return $options->update_option('rewrite_status', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize cron scheduler
|
||||
*/
|
||||
private function init_webp_cron_scheduler() {
|
||||
WPO_WebP_Cron_Scheduler::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the php shell functions are available or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_shell_functions_available() {
|
||||
$shell_functions = self::get_shell_functions();
|
||||
foreach ($shell_functions as $shell_function) {
|
||||
if (!function_exists($shell_function)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of php shell function names
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function get_shell_functions() {
|
||||
return array(
|
||||
'escapeshellarg',
|
||||
'escapeshellcmd',
|
||||
'exec',
|
||||
'passthru',
|
||||
'proc_close',
|
||||
'proc_get_status',
|
||||
'proc_nice',
|
||||
'proc_open',
|
||||
'proc_terminate',
|
||||
'shell_exec',
|
||||
'system',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_PLUGIN_MAIN_PATH')) die('No direct access allowed');
|
||||
|
||||
require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/autoload.php');
|
||||
use HtaccessCapabilityTester\HtaccessCapabilityTester;
|
||||
|
||||
class WPO_Htaccess_Capabilities {
|
||||
|
||||
private static $_instance = null;
|
||||
|
||||
/**
|
||||
* Tests and sets up server's htacess capabilities as properties
|
||||
*/
|
||||
public function __construct() {
|
||||
$uploads = wp_upload_dir();
|
||||
$this->hct = new HtaccessCapabilityTester($uploads['basedir'] . '/wpo', $uploads['baseurl'] . '/wpo');
|
||||
$this->htaccess_enabled = $this->hct->htaccessEnabled();
|
||||
$this->mod_headers = $this->get_mod_header_status();
|
||||
$this->mod_mime = $this->get_mod_mime_status();
|
||||
$this->mod_rewrite = $this->get_mod_rewrite_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets singleton instance
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if (null === self::$_instance) {
|
||||
self::$_instance = new WPO_Htaccess_Capabilities();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets `mod_headers` status by checking if it is loaded and working
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_mod_header_status() {
|
||||
return (true === $this->hct->moduleLoaded('headers') && true === $this->hct->headerSetWorks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets `mod_mime` status by checking if it is loaded and working
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_mod_mime_status() {
|
||||
return (true === $this->hct->moduleLoaded('mime') && true === $this->hct->addTypeWorks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets `mod_rewrite` status by checking if it is loaded and working
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_mod_rewrite_status() {
|
||||
return (true === $this->hct->moduleLoaded('rewrite') && true == $this->hct->rewriteWorks());
|
||||
}
|
||||
}
|
||||
101
wp-content/plugins/wp-optimize/webp/class-wpo-server-info.php
Normal file
101
wp-content/plugins/wp-optimize/webp/class-wpo-server-info.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
if (!defined('WPO_PLUGIN_MAIN_PATH')) die('No direct access allowed');
|
||||
|
||||
class WPO_Server_Info {
|
||||
|
||||
private static $_instance = null;
|
||||
|
||||
/**
|
||||
* @var $_server_name Web server engine name
|
||||
*/
|
||||
private $_server_name;
|
||||
|
||||
/**
|
||||
* @var $_rewrite_status Web server's URL rewrite ability
|
||||
*/
|
||||
private $_rewrite_status;
|
||||
|
||||
/**
|
||||
* Setup server information
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->set_server_name();
|
||||
$this->set_rewrite_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets singleton instance
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if (null === self::$_instance) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect and set web server names
|
||||
*/
|
||||
private function set_server_name() {
|
||||
global $is_apache, $is_nginx, $is_iis7, $is_IIS;
|
||||
|
||||
if ($is_apache) {
|
||||
$this->_server_name = 'apache';
|
||||
}
|
||||
|
||||
if ($is_iis7) {
|
||||
$this->_server_name = 'iis7';
|
||||
}
|
||||
|
||||
if ($is_IIS) {
|
||||
$this->_server_name = 'iis';
|
||||
}
|
||||
|
||||
if ($is_nginx) {
|
||||
$this->_server_name = 'nginx';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets web server's rewrite ability
|
||||
*/
|
||||
private function set_rewrite_status() {
|
||||
if ('apache' === $this->_server_name) {
|
||||
$this->test_htaccess_capabilities();
|
||||
} else {
|
||||
$this->_rewrite_status = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Apache/LiteSpeed server's htaccess capabilities, and sets status and info
|
||||
*/
|
||||
private function test_htaccess_capabilities() {
|
||||
$htc = WPO_Htaccess_Capabilities::get_instance();
|
||||
if ($htc->htaccess_enabled && $htc->mod_rewrite && $htc->mod_headers && $htc->mod_mime) {
|
||||
$this->_rewrite_status = true;
|
||||
} elseif ($htc->htaccess_enabled) {
|
||||
$this->_rewrite_status = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for web server name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_server_name() {
|
||||
return $this->_server_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for web server's rewrite capability
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_rewrite_status() {
|
||||
return $this->_rewrite_status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
if (!class_exists('WPO_WebP_Alter_HTML')) :
|
||||
|
||||
class WPO_WebP_Alter_HTML {
|
||||
|
||||
private $tags = array('img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section', 'video');
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
add_action('template_redirect', array($this, 'start'), 9999);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns singleton instance
|
||||
*
|
||||
* @return WPO_WebP_Alter_HTML
|
||||
*/
|
||||
public static function get_instance() {
|
||||
static $_instance = null;
|
||||
if (null === $_instance) {
|
||||
$_instance = new self();
|
||||
}
|
||||
return $_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start to alter html in output buffer
|
||||
*/
|
||||
public function start() {
|
||||
if (apply_filters('wpo_disable_webp_alter_html', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) {
|
||||
ob_start(array(__CLASS__, 'alter_html'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter html to change image related tags to specify webp images
|
||||
*
|
||||
* @param string $html - HTML document as string
|
||||
* @return string
|
||||
*/
|
||||
public function alter_html($html) {
|
||||
|
||||
if (!$this->is_valid_html($html)) return $html;
|
||||
|
||||
$this->maybe_include_simple_html_dom();
|
||||
|
||||
$dom = str_get_html($html, false, false, 'UTF-8', false, DEFAULT_BR_TEXT, DEFAULT_SPAN_TEXT, false);
|
||||
|
||||
// MAX_FILE_SIZE is defined in simple_html_dom.
|
||||
// For safety sake, we make sure it is defined before using
|
||||
defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
|
||||
|
||||
if (false === $dom) {
|
||||
if (strlen($html) > MAX_FILE_SIZE) {
|
||||
return '<!-- Alter HTML was skipped because the HTML is too big to process! ' .
|
||||
'(limit is set to ' . MAX_FILE_SIZE . ' bytes) -->' . "\n" . $html;
|
||||
}
|
||||
return '<!-- Alter HTML was skipped because the helper library refused to process the html -->' .
|
||||
"\n" . $html;
|
||||
}
|
||||
|
||||
// Replace attributes (src, srcset, data-src, etc)
|
||||
foreach ($this->tags as $tag) {
|
||||
$elems = $dom->find($tag);
|
||||
foreach ($elems as $elem) {
|
||||
$attributes = $elem->getAllAttributes();
|
||||
foreach ($attributes as $attr_name => $attr_value) {
|
||||
if ($this->is_image_attribute($attr_name)) {
|
||||
$elem->setAttribute($attr_name, $this->handle_attribute($attr_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dom->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether supplied string is a valid html document or not
|
||||
*
|
||||
* @param string $html - HTML document as string
|
||||
* @return bool
|
||||
*/
|
||||
private function is_valid_html($html) {
|
||||
if (is_feed()) return false;
|
||||
|
||||
// To prevent issue with `simple_html_dom` class
|
||||
// Exit if it doesn't look like HTML
|
||||
// https://github.com/rosell-dk/webp-express/issues/228
|
||||
if (!preg_match("#^\\s*<#", $html)) return false;
|
||||
|
||||
if ('' == $html) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include simple html dom script if not available
|
||||
*/
|
||||
private function maybe_include_simple_html_dom() {
|
||||
if (!function_exists('str_get_html')) {
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'vendor/simplehtmldom/simplehtmldom/simple_html_dom.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append image urls with `.webp` extension
|
||||
*
|
||||
* @param strinng $url - Image URL
|
||||
* @return string
|
||||
*/
|
||||
private function replace_url($url) {
|
||||
return $url . '.webp';
|
||||
}
|
||||
|
||||
/**
|
||||
* If webp version for supplied image url is available then replace extension
|
||||
*
|
||||
* @param string $url - URL of image
|
||||
* @return string
|
||||
*/
|
||||
private function maybe_replace_url($url) {
|
||||
if ($this->is_webp_version_available($url)) {
|
||||
$url = $this->replace_url($url);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies src attribute value, if needed
|
||||
*
|
||||
* @param string $attr_value
|
||||
* @return string
|
||||
*/
|
||||
private function handle_src($attr_value) {
|
||||
return $this->maybe_replace_url($attr_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modified `srcset` attribute value, if needed
|
||||
*
|
||||
* @param string $attr_value
|
||||
* @return string
|
||||
*/
|
||||
private function handle_srcset($attr_value) {
|
||||
// $attr_value is ie: <img data-x="1.jpg 1000w, 2.jpg">
|
||||
$srcset_arr = explode(',', $attr_value);
|
||||
foreach ($srcset_arr as $i => $srcset_entry) {
|
||||
// $srcset_entry is ie "image.jpg 520w", but can also lack width, ie just "image.jpg"
|
||||
// it can also be ie "image.jpg 2x"
|
||||
$srcset_entry = trim($srcset_entry);
|
||||
$entry_parts = preg_split('/\s+/', $srcset_entry, 2);
|
||||
if (count($entry_parts) == 2) {
|
||||
list($src, $descriptors) = $entry_parts;
|
||||
} else {
|
||||
$src = $srcset_entry;
|
||||
$descriptors = null;
|
||||
}
|
||||
|
||||
$url = $this->maybe_replace_url($src);
|
||||
$srcset_arr[$i] = $url . (isset($descriptors) ? ' ' . $descriptors : '');
|
||||
}
|
||||
return implode(', ', $srcset_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether given value is a `srcset` or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function looks_like_srcset($value) {
|
||||
if (preg_match('#\s\d*(w|x)#', $value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle attribute value based on attribute name, src or srcset
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function handle_attribute($value) {
|
||||
if ($this->looks_like_srcset($value)) {
|
||||
return $this->handle_srcset($value);
|
||||
}
|
||||
return $this->handle_src($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether given attribute name is an image attribute or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_image_attribute($attr_name) {
|
||||
return preg_match('#^(src|srcset|poster|(data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*))$#i', $attr_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does webp image file exists
|
||||
*
|
||||
* @param string $url
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_webp_version_available($url) {
|
||||
$filename = $this->get_file_path($url);
|
||||
if (empty($filename)) return false;
|
||||
return file_exists($filename . '.webp');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file path
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
private function get_file_path($url) {
|
||||
if (is_multisite()) {
|
||||
if (function_exists('get_main_site_id')) {
|
||||
$site_id = get_main_site_id();
|
||||
} else {
|
||||
$network = get_network();
|
||||
$site_id = $network->site_id;
|
||||
}
|
||||
switch_to_blog($site_id);
|
||||
}
|
||||
$upload_dir = wp_upload_dir();
|
||||
$uploads_url = trailingslashit($upload_dir['baseurl']);
|
||||
$uploads_dir = trailingslashit($upload_dir['basedir']);
|
||||
if (is_multisite()) {
|
||||
restore_current_blog();
|
||||
}
|
||||
$possible_urls = array(
|
||||
WP_CONTENT_URL => WP_CONTENT_DIR,
|
||||
WP_PLUGIN_URL => WP_PLUGIN_DIR,
|
||||
$uploads_url => $uploads_dir,
|
||||
get_template_directory_uri() => get_template_directory(),
|
||||
includes_url() => preg_replace('/wp-content$/', trailingslashit('wp-includes'), WP_CONTENT_DIR),
|
||||
);
|
||||
$file = '';
|
||||
foreach ($possible_urls as $possible_url => $path) {
|
||||
$pos = strpos($url, $possible_url);
|
||||
if (false !== $pos) {
|
||||
$file = substr_replace($url, $path, $pos, strlen($possible_url));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
use \WebPConvert\Convert\ConverterFactory;
|
||||
|
||||
require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/autoload.php');
|
||||
require_once(WPO_PLUGIN_MAIN_PATH . 'webp/class-wpo-webp-test-run.php');
|
||||
|
||||
if (!class_exists('WPO_WebP_Convert')) :
|
||||
|
||||
class WPO_WebP_Convert {
|
||||
|
||||
public $converters = null;
|
||||
|
||||
public function __construct() {
|
||||
$this->converters = WP_Optimize()->get_options()->get_option('webp_converters');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts uploaded image to webp format
|
||||
*
|
||||
* @param string $source - path of the source file
|
||||
*/
|
||||
public function convert($source) {
|
||||
if (count($this->converters) < 1) return false;
|
||||
|
||||
$destination = $this->get_destination_path($source);
|
||||
$this->check_converters_and_do_conversion($source, $destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the destination full path
|
||||
*
|
||||
* @param string $source - path of the source file
|
||||
*
|
||||
* @return string $destination - path of destination file
|
||||
*/
|
||||
protected function get_destination_path($source) {
|
||||
$path_parts = pathinfo($source);
|
||||
$destination = $path_parts['dirname'] . '/'. basename($source) . '.webp';
|
||||
return $destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through available converters and do the conversion
|
||||
*
|
||||
* @param string $source - path of source file
|
||||
* @param string $destination - path of destination file
|
||||
*/
|
||||
protected function check_converters_and_do_conversion($source, $destination) {
|
||||
foreach ($this->converters as $converter) {
|
||||
$converter_instance = ConverterFactory::makeConverter(
|
||||
$converter,
|
||||
$source,
|
||||
$destination
|
||||
);
|
||||
$converter_instance->doConvert();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
if (!class_exists('WPO_WebP_Cron_Scheduler')) :
|
||||
|
||||
class WPO_WebP_Cron_Scheduler {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->setup_cron_event();
|
||||
add_action('wpo_reset_webp_conversion_test_result', array($this, 'reset_webp_conversion_flags'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns singleton instance of this class
|
||||
*
|
||||
* @return WPO_WebP_Cron_Scheduler Singleton Instance
|
||||
*/
|
||||
public static function get_instance() {
|
||||
static $instance = null;
|
||||
if (null === $instance) {
|
||||
$instance = new self();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup cron event to reset webp conversion test result
|
||||
*/
|
||||
private function setup_cron_event() {
|
||||
if (!wp_next_scheduled('wpo_reset_webp_conversion_test_result')) {
|
||||
wp_schedule_event(time(), 'wpo_daily', 'wpo_reset_webp_conversion_test_result');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all webp conversion flags
|
||||
*/
|
||||
public function reset_webp_conversion_flags() {
|
||||
WP_Optimize()->get_webp_instance()->reset_webp_serving_method();
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
if (!class_exists('WPO_WebP_Self_Test')) :
|
||||
|
||||
class WPO_WebP_Self_Test {
|
||||
|
||||
/**
|
||||
* Decided whether we can get a webp image or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_webp_image() {
|
||||
$args = array(
|
||||
'headers' => array(
|
||||
'accept' => 'image/webp'
|
||||
)
|
||||
);
|
||||
|
||||
$upload_dir = wp_upload_dir();
|
||||
$url = $upload_dir['baseurl']. '/wpo/images/wpo_logo_small.png.webp';
|
||||
|
||||
$response = wp_remote_get($url, $args);
|
||||
|
||||
if (is_wp_error($response)) return false;
|
||||
if (200 != $response['response']['code']) return false;
|
||||
|
||||
$headers = wp_remote_retrieve_headers($response);
|
||||
if (method_exists($headers, 'getAll')) {
|
||||
$headers = $headers->getAll();
|
||||
if (isset($headers['content-type']) && 'image/webp' == $headers['content-type']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decided whether webp version is served or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_webp_served() {
|
||||
$args = array(
|
||||
'headers' => array(
|
||||
'accept' => 'image/webp'
|
||||
)
|
||||
);
|
||||
|
||||
$upload_dir = wp_upload_dir();
|
||||
$url = $upload_dir['baseurl']. '/wpo/images/wpo_logo_small.png';
|
||||
|
||||
$response = wp_remote_get($url, $args);
|
||||
|
||||
if (is_wp_error($response)) return false;
|
||||
if (200 != $response['response']['code']) return false;
|
||||
|
||||
$headers = wp_remote_retrieve_headers($response);
|
||||
if (method_exists($headers, 'getAll')) {
|
||||
$headers = $headers->getAll();
|
||||
if (isset($headers['content-type']) && 'image/webp' == $headers['content-type']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns singleton instance
|
||||
*
|
||||
* @return WPO_WebP_Self_Test
|
||||
*/
|
||||
public static function get_instance() {
|
||||
static $_instance = null;
|
||||
if (null === $_instance) {
|
||||
$_instance = new self();
|
||||
}
|
||||
return $_instance;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WPO_VERSION')) die('No direct access allowed');
|
||||
|
||||
use \WebPConvert\Convert\ConverterFactory;
|
||||
|
||||
require_once WPO_PLUGIN_MAIN_PATH . 'vendor/autoload.php';
|
||||
|
||||
if (!class_exists('WPO_WebP_Test_Run')) :
|
||||
/**
|
||||
* Test run
|
||||
*/
|
||||
class WPO_WebP_Test_Run {
|
||||
|
||||
/**
|
||||
* Get a test result object OR false, if tests cannot be made.
|
||||
*
|
||||
* @return object|false
|
||||
*/
|
||||
public static function get_converter_status() {
|
||||
$source = WPO_PLUGIN_MAIN_PATH . 'images/logo/wpo_logo_small.png';
|
||||
$upload_dir = wp_upload_dir();
|
||||
$destination = $upload_dir['basedir']. '/wpo/images/wpo_logo_small.png.webp';
|
||||
|
||||
$converters = array(
|
||||
// 'cwebp',
|
||||
'vips',
|
||||
'imagemagick',
|
||||
'graphicsmagick',
|
||||
'ffmpeg',
|
||||
'wpc',
|
||||
'ewww',
|
||||
'imagick',
|
||||
'gmagick',
|
||||
'gd',
|
||||
);
|
||||
$working_converters = array();
|
||||
$errors = array();
|
||||
|
||||
foreach ($converters as $converter) {
|
||||
$converter_id = $converter;
|
||||
try {
|
||||
$converter_instance = ConverterFactory::makeConverter(
|
||||
$converter_id,
|
||||
$source,
|
||||
$destination
|
||||
);
|
||||
$converter_instance->doConvert();
|
||||
$working_converters[] = $converter_id;
|
||||
// Copying source file to `uploads` folder. To be used test redirection
|
||||
// We're doing it here, to make sure folders already exists `/wpo/images/`
|
||||
copy($source, $upload_dir['basedir'] . '/wpo/images/wpo_logo_small.png');
|
||||
} catch (\Exception $e) {
|
||||
$errors[$converter_id] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'working_converters' => $working_converters,
|
||||
'errors' => $errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
Reference in New Issue
Block a user