2025-08-11 11:41:25 +00:00
<? php
/*
* Plugin Name: 1984 Hosting Support
2026-03-23 10:16:07 +00:00
* Version: 1.2.0
2025-12-03 13:36:10 +00:00
* Author: 1984 ehf.
2025-08-11 11:41:25 +00:00
* Author URI: https://1984.hosting
* Description: Support plugin for 1984 Hosting customers.
2025-08-11 11:53:13 +00:00
* Update URI: https://git.1984.is/1984/1984-hosting-support/
2025-12-03 13:36:10 +00:00
* Text Domain: hostingsupport1984
* Domain Path: /languages
2025-08-11 11:41:25 +00:00
*/
/**
* The main HostingSupport1984 class
*
* @package HostingSupport1984
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html GNU General Public License v2.0
*
* This is where basic constants such as the version number are pulled from.
* There are other classes that may depend on this file, so only remove it if
* you do not intend to use the plugin.
*/
2025-12-03 13:36:10 +00:00
2025-08-11 11:41:25 +00:00
class HostingSupport1984 {
2026-03-23 10:16:07 +00:00
const HOSTING_SUPPORT_VERSION = '1.2.0' ;
2025-08-11 11:41:25 +00:00
/**
* Construct a new HostingSupport1984 object
*/
public function __construct () {
// Loading the text domain for a mu-plugin is tricky.
// We need to use admin_init instead of plugins_loaded as we are only
// using the plugin in the admin interface.
add_action (
'admin_init' ,
array ( $this , 'load_textdomain' )
);
// Register the activation hook.
register_activation_hook (
__FILE__ ,
array ( $this , 'activation_hook' )
);
// Run on activation of any plugin.
add_action (
'activated_plugin' ,
array ( $this , 'plugin_activation_hook' )
);
// Run on activation of theme.
add_action (
'switch_theme' ,
array ( $this , 'theme_switch_hook' )
);
2025-12-03 13:36:10 +00:00
// Add a clear warning on the Patchstack plugin row to discourage removal.
add_filter (
'plugin_row_meta' ,
array (
$this ,
'add_patchstack_warning_row_meta' ,
),
10 ,
2
);
// Prevent deactivation/deletion of this plugin and Patchstack via UI links.
add_filter (
'plugin_action_links' ,
array (
$this ,
'filter_plugin_action_links' ,
),
10 ,
4
);
add_filter (
'network_admin_plugin_action_links' ,
array (
$this ,
'filter_plugin_action_links' ,
),
10 ,
4
);
// Guard against direct requests (single and bulk) on Plugins screens and updater endpoints.
add_action ( 'load-plugins.php' , array (
$this ,
'protect_plugins_admin_actions' ,
) );
add_action ( 'load-plugins-network.php' , array (
$this ,
'protect_plugins_admin_actions' ,
) );
add_action ( 'load-update.php' , array (
$this ,
'protect_plugins_admin_actions' ,
) );
2025-08-11 11:41:25 +00:00
}
/**
* Load the 'hosting_support_1984' text domain
*
* @return Boolean
*/
public function load_textdomain () {
return load_plugin_textdomain (
'hostingsupport1984' ,
false ,
'1984-hosting-support/languages'
);
}
/**
* On activation of this plugin, set auto-update option for core,
* plus enable auto-updates for installed plugins and themes.
2025-08-11 12:57:39 +00:00
*
* This is skipped if Patchstack is active on the site.
2025-08-11 11:41:25 +00:00
*/
public function activation_hook () {
2025-08-11 12:57:39 +00:00
if ( $this -> is_patchstack_active () ) {
// In case Patchstack is active, do not continue.
return ;
}
2025-08-11 11:41:25 +00:00
// Auto-update WordPress core.
update_site_option ( 'auto_update_core_major' , 'enabled' );
// Auto-update plugins.
$all_plugins = apply_filters ( 'all_plugins' , get_plugins () );
update_site_option ( 'auto_update_plugins' , array_keys ( $all_plugins ) );
// Auto-update themes.
$all_themes = wp_get_themes ();
update_site_option ( 'auto_update_themes' , array_keys ( $all_themes ) );
}
2025-12-03 13:36:10 +00:00
/**
* Check if Patchstack is enabled.
*
* @return Boolean
*/
public function is_patchstack_active () {
return is_plugin_active ( 'patchstack/patchstack.php' );
}
2025-08-11 11:41:25 +00:00
/**
* On plugin activation, add to auto-updated list of plugins.
2025-08-11 12:57:39 +00:00
*
* This is skipped if Patchstack is active on the site.
2025-08-11 11:41:25 +00:00
*/
public function plugin_activation_hook ( $plugin ) {
2025-08-11 12:57:39 +00:00
if ( $this -> is_patchstack_active () ) {
// In case Patchstack is active, do not continue.
return ;
}
2025-12-03 13:36:10 +00:00
$auto_updated_plugins = ( array ) get_site_option ( 'auto_update_plugins' , array () );
2025-08-11 11:41:25 +00:00
$auto_updated_plugins [] = $plugin ;
update_site_option ( 'auto_update_plugins' , array_unique ( $auto_updated_plugins ) );
}
/**
* On theme switch, enable auto-update for all themes.
2025-08-11 12:57:39 +00:00
*
* This is skipped if Patchstack is active on the site.
2025-08-11 11:41:25 +00:00
*/
public function theme_switch_hook ( $theme ) {
2025-08-11 12:57:39 +00:00
if ( $this -> is_patchstack_active () ) {
// In case Patchstack is active, do not continue.
return ;
}
2025-08-11 11:41:25 +00:00
$all_themes = wp_get_themes ();
update_site_option ( 'auto_update_themes' , array_keys ( $all_themes ) );
}
2025-12-03 13:36:10 +00:00
/**
* Append a prominent warning to the Patchstack plugin row in the Plugins screen.
*
* @param array $links Existing row meta links.
* @param string $file Plugin file path about plugins directory.
*
* @return array Modified row meta-links.
*/
public function add_patchstack_warning_row_meta ( array $links , string $file ) : array {
// Only show the warning on the Patchstack row AND only if Patchstack is active.
if ( 'patchstack/patchstack.php' !== $file || ! $this -> is_patchstack_active () ) {
return $links ;
}
$warning_text =
2026-03-19 15:40:32 +00:00
__ ( '1984 Hosting: Please do not deactivate or delete this plugin - part of your WordPress Security Pack.' , 'hostingsupport1984' );
2025-12-03 13:36:10 +00:00
$logo_1984_url = plugins_url ( 'icons/1984-hosting-logo.webp' , __FILE__ );
$logo_patchstack = plugins_url ( 'icons/patchstack-logo.svg' , __FILE__ );
$title_1984 = __ ( 'Visit 1984 Hosting Homepage' , 'hostingsupport1984' );
$title_patchstack = __ ( 'Visit Patchstack Homepage' , 'hostingsupport1984' );
$container_open =
'<span class="description" style="color:#b32d2e;font-weight:700;display:inline-grid;grid-template-columns:auto 1fr;column-gap:6px;row-gap:4px;align-items:center;line-height:1.5;vertical-align:middle;">' ;
$warning_icon =
'<span class="dashicons dashicons-warning" aria-hidden="true" style="color:#b32d2e;grid-column:1;"></span>' ;
$text_html = '<span style="grid-column:2;">' . esc_html ( $warning_text ) . '</span>' ;
$logos_html =
'<span style="grid-column:2;display:inline-flex;align-items:center;gap:4px;">'
.
'<a href="https://1984.hosting" target="_blank" rel="noopener noreferrer" title="' . esc_attr ( $title_1984 ) . '" aria-label="' . esc_attr ( $title_1984 ) . '">'
.
'<img src="' . esc_url ( $logo_1984_url ) . '" alt="1984 Hosting" style="height:16px;width:auto;display:inline-block;" />'
.
'</a>'
.
'<a href="https://patchstack.com" target="_blank" rel="noopener noreferrer" title="' . esc_attr ( $title_patchstack ) . '" aria-label="' . esc_attr ( $title_patchstack ) . '">'
.
'<img src="' . esc_url ( $logo_patchstack ) . '" alt="Patchstack" style="height:16px;width:auto;display:inline-block;" />'
.
'</a>'
.
'</span>' ;
$links [] = $container_open . $warning_icon . $text_html . $logos_html . '</span>' ;
return $links ;
}
/**
* Remove Deactivate/Delete action links for protected plugins (single and network admin).
*
* @param array $actions
* @param string $plugin_file
* @param array $plugin_data
* @param string $context
*
* @return array
*/
public function filter_plugin_action_links (
array $actions , string $plugin_file , array $plugin_data ,
string $context
) : array {
if ( $this -> is_protected_plugin ( $plugin_file ) ) {
unset ( $actions [ 'deactivate' ] );
unset ( $actions [ 'delete' ] );
}
return $actions ;
}
/**
* Determine if a plugin file is in the protected list.
*
* @param string $plugin_file
*
* @return bool
*/
private function is_protected_plugin ( string $plugin_file ) : bool {
return in_array ( $plugin_file , $this -> get_protected_plugins (), true );
}
/**
* Return plugin basenames that must be protected from deactivation/deletion.
*
* @return string[]
*/
2026-01-05 15:35:01 +00:00
private function get_protected_plugins () : array {
if ( ! $this -> is_patchstack_active () ) {
return array ();
2025-12-11 14:18:46 +00:00
}
2025-12-10 15:30:31 +00:00
2026-01-05 15:35:01 +00:00
// Protect this plugin.
$own = plugin_basename ( __FILE__ );
$protected = array ( $own );
// Also protect Patchstack.
$protected [] = 'patchstack/patchstack.php' ;
return $protected ;
}
2025-12-03 13:36:10 +00:00
/**
* Intercept admin actions attempting to deactivate or delete protected plugins and block them.
*/
2025-12-11 14:18:46 +00:00
public function protect_plugins_admin_actions () {
// Collect requested action(s).
$action = isset ( $_REQUEST [ 'action' ] ) ? sanitize_key ( ( string ) $_REQUEST [ 'action' ] ) : '' ;
$action2 = isset ( $_REQUEST [ 'action2' ] ) ? sanitize_key ( ( string ) $_REQUEST [ 'action2' ] ) : '' ;
2025-12-03 13:36:10 +00:00
$targets = array ();
if ( ! empty ( $_REQUEST [ 'plugin' ] ) ) {
$targets [] = sanitize_text_field ( ( string ) $_REQUEST [ 'plugin' ] );
}
if ( ! empty ( $_REQUEST [ 'checked' ] ) && is_array ( $_REQUEST [ 'checked' ] ) ) {
foreach ( $_REQUEST [ 'checked' ] as $pf ) {
$targets [] = sanitize_text_field ( ( string ) $pf );
}
}
if ( empty ( $targets ) ) {
return ;
}
$blocked_actions = array (
'deactivate' ,
'deactivate-selected' ,
'delete' ,
'delete-selected' ,
'delete-plugin' ,
);
if ( ! in_array ( $action , $blocked_actions , true ) && ! in_array ( $action2 , $blocked_actions , true ) ) {
return ;
}
2025-12-11 14:18:46 +00:00
$protected = $this -> get_protected_plugins ();
$intersect = array_intersect ( $targets , $protected );
if ( ! empty ( $intersect ) ) {
wp_die (
__ ( 'For security, this action is blocked: 1984 Hosting Support cannot be deactivated or deleted. Patchstack cannot be deactivated or deleted while it is active.' , 'hostingsupport1984' ),
403
);
}
}
2025-08-11 11:41:25 +00:00
}
$hosting_support_1984 = new HostingSupport1984 ();
2025-12-10 15:30:31 +00:00
define ( 'A1984_HOSTING_SUPPORT_BASE_FILE' , __FILE__ );
2025-08-11 11:41:25 +00:00
require_once __DIR__ . '/1984-hosting-support-ui.php' ;