├── .gitignore ├── lib └── css │ ├── airplane-mode.min.css │ └── airplane-mode.css ├── README.md ├── LICENSE └── airplane-mode.php /.gitignore: -------------------------------------------------------------------------------- 1 | .htaccess 2 | wp-content/uploads/ 3 | wp-content/blogs.dir/ 4 | wp-content/upgrade/ 5 | wp-content/backup-db/ 6 | wp-content/advanced-cache.php 7 | wp-content/wp-cache-config.php 8 | sitemap.xml 9 | *.log 10 | wp-content/cache/ 11 | wp-content/backups/ 12 | sitemap.xml.gz 13 | wp-config.php 14 | -------------------------------------------------------------------------------- /lib/css/airplane-mode.min.css: -------------------------------------------------------------------------------- 1 | #wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon{height:14px;width:14px;border-radius:50%;background:#ccc;display:inline-block;vertical-align:middle;margin-right:7px;position:relative;bottom:2px;}#wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon-on{background:green;}#wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon-off{background:red;} -------------------------------------------------------------------------------- /lib/css/airplane-mode.css: -------------------------------------------------------------------------------- 1 | #wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon { 2 | height: 14px; 3 | width: 14px; 4 | border-radius: 50%; 5 | background: #ccc; 6 | display: inline-block; 7 | vertical-align: middle; 8 | margin-right: 7px; 9 | position: relative; 10 | bottom: 2px; 11 | } 12 | 13 | #wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon-on { 14 | background: green; 15 | } 16 | 17 | #wp-admin-bar-airplane-mode-toggle span.airplane-toggle-icon-off { 18 | background: red; 19 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Airplane Mode 2 | ======================== 3 | 4 | ## About 5 | Control loading of external files when developing locally. WP loads certain external files (fonts, gravatar, etc) and makes external HTTP calls. This isn't usually an issue, unless you're working in an evironment without a web connection. This plugin removes / unhooks those actions to reduce load time and avoid errors due to missing files. 6 | 7 | ## Current Actions 8 | * sets the src for Open Sans CSS font file to null due to dependency issues ( see [related Trac ticket](https://core.trac.wordpress.org/ticket/28478) ) 9 | * replaces all instances of Gravatar with a local image to remove external call 10 | * removes all HTTP requests 11 | * includes toggle in admin bar for quick enable / disable 12 | 13 | ## Roadmap 14 | * fine tune HTTP request removal 15 | * find other calls from core 16 | * add other requests from popular plugins 17 | 18 | 19 | #### pull requests are very much welcome and encouraged -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Norcross 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /airplane-mode.php: -------------------------------------------------------------------------------- 1 | enabled() ) { 75 | add_filter( 'jetpack_development_mode', '__return_true', 9999 ); 76 | } 77 | 78 | register_activation_hook( __FILE__, array( $this, 'create_setting' ) ); 79 | register_deactivation_hook( __FILE__, array( $this, 'remove_setting' ) ); 80 | } 81 | 82 | /** 83 | * If an instance exists, this returns it. If not, it creates one and 84 | * returns it. 85 | * 86 | * @return $instance 87 | */ 88 | public static function getInstance() { 89 | if ( ! self::$instance ) { 90 | self::$instance = new self; 91 | } 92 | 93 | return self::$instance; 94 | } 95 | 96 | /** 97 | * load our textdomain for localization 98 | * 99 | * @return void 100 | */ 101 | public function textdomain() { 102 | load_plugin_textdomain( 'airplane-mode', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); 103 | } 104 | 105 | /** 106 | * Set our initial airplane mode setting to 'on' on activation. 107 | */ 108 | public function create_setting() { 109 | add_site_option( 'airplane-mode', 'on' ); 110 | } 111 | 112 | /** 113 | * Remove our setting on plugin deactivation. 114 | */ 115 | public function remove_setting() { 116 | delete_option( 'airplane-mode' ); 117 | delete_site_option( 'airplane-mode' ); 118 | } 119 | 120 | /** 121 | * Helper function to check the current status. 122 | * 123 | * @return bool True if status is 'on'; false if not. 124 | */ 125 | public function enabled() { 126 | if ( defined( 'WP_CLI' ) and WP_CLI ) { 127 | return false; 128 | } 129 | // pull our status from the options table 130 | $option = get_site_option( 'airplane-mode' ); 131 | if ( false === $option ) { 132 | $option = get_option( 'airplane-mode' ); 133 | } 134 | return 'on' === $option; 135 | } 136 | 137 | /** 138 | * Hop into the set of default CSS files to allow for 139 | * disabling Open Sans and filter to allow other mods. 140 | * 141 | * @param WP_Styles $styles All the registered CSS items. 142 | * @return WP_Styles $styles The same object with Open Sans 'src' set to null. 143 | */ 144 | public function block_style_load( WP_Styles $styles ) { 145 | // bail if disabled 146 | if ( ! $this->enabled() ) { 147 | return $styles; 148 | } 149 | 150 | // make sure we have something registered first 151 | if ( ! isset( $styles->registered ) ) { 152 | return $styles; 153 | } 154 | 155 | // fetch our registered styles 156 | $registered = $styles->registered; 157 | 158 | // pass the entire set of registered data to the action to allow a bypass 159 | do_action( 'airplane_mode_style_load', $registered ); 160 | 161 | // fetch our open sans if present and set the src inside the object to null 162 | if ( ! empty( $registered['open-sans'] ) ) { 163 | $open_sans = $registered['open-sans']; 164 | $open_sans->src = null; 165 | } 166 | 167 | // send it back 168 | return $styles; 169 | } 170 | 171 | /** 172 | * Hop into the set of default JS files to allow for 173 | * disabling as needed filter to allow other mods. 174 | * 175 | * @param WP_Scripts $scripts All the registered JS items. 176 | * @return WP_Scripts $scripts The same object, possibly filtered. 177 | */ 178 | public function block_script_load( WP_Scripts $scripts ) { 179 | // bail if disabled 180 | if ( ! $this->enabled() ) { 181 | return $scripts; 182 | } 183 | 184 | // make sure we have something registered first 185 | if ( ! isset( $scripts->registered ) ) { 186 | return $scripts; 187 | } 188 | 189 | // fetch our registered scripts 190 | $registered = $scripts->registered; 191 | 192 | // pass the entire set of registered data to the action to allow a bypass 193 | do_action( 'airplane_mode_script_load', $registered ); 194 | 195 | /* 196 | * nothing actually being done here at the present time. this is a 197 | * placeholder for being able to modify the script loading in the same 198 | * manner that we do the CSS files 199 | */ 200 | 201 | // send it back 202 | return $scripts; 203 | } 204 | 205 | /** 206 | * Block oEmbeds from displaying. 207 | * 208 | * @param string $html The embed HTML. 209 | * @param string $url The attempted embed URL. 210 | * @param array $attr An array of shortcode attributes. 211 | * @param int $post_ID Post ID. 212 | * @return string 213 | */ 214 | public function block_oembed_html( $html, $url, $attr, $post_ID ) { 215 | 216 | if ( $this->enabled() ) { 217 | return sprintf( '

%s

', 218 | sprintf( __( 'Airplane Mode is enabled. oEmbed blocked for %1$s.', 'airplane-mode' ), 219 | esc_url( $url ) 220 | ) 221 | ); 222 | } else { 223 | return $html; 224 | } 225 | 226 | } 227 | 228 | /** 229 | * Replace all instances of gravatar with a local image file 230 | * to remove the call to remote service. 231 | * 232 | * @param string $avatar Image tag for the user's avatar. 233 | * @param int|object|string $id_or_email A user ID, email address, or comment object. 234 | * @param string $default URL to a default image to use if no avatar is available 235 | * @param int $size Square avatar width and height in pixels to retrieve. 236 | * @param string $alt Alternative text to use in the avatar image tag. 237 | * @return string `` tag for the user's avatar. 238 | */ 239 | public function replace_gravatar( $avatar, $id_or_email, $size, $default, $alt ) { 240 | // bail if disabled 241 | if ( ! $this->enabled() ) { 242 | return $avatar; 243 | } 244 | 245 | // swap out the file for a base64 encoded image 246 | $image = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; 247 | $avatar = "{$alt}"; 248 | 249 | // return the item 250 | return $avatar; 251 | } 252 | 253 | /** 254 | * Remove avatar images from the default avatar list 255 | * 256 | * @param string $avatar_list List of default avatars 257 | * @return string Updated list with images removed 258 | */ 259 | public function default_avatar( $avatar_list ) { 260 | // bail if disabled 261 | if ( ! $this->enabled() ) { 262 | return $avatar_list; 263 | } 264 | 265 | // remove images 266 | $avatar_list = preg_replace( '|]+)> |i', '', $avatar_list ); 267 | 268 | return $avatar_list; 269 | } 270 | 271 | /** 272 | * Disable all the HTTP requests being made with the action 273 | * happening before the status check so others can allow certain 274 | * items as desired. 275 | * 276 | * @param bool|array|WP_Error $status Whether to preempt an HTTP request return. Default false. 277 | * @param array $args HTTP request arguments. 278 | * @param string $url The request URL. 279 | * @return bool|array|WP_Error A WP_Error object if Airplane Mode is enabled. Original $status if not. 280 | */ 281 | public function disable_http_reqs( $status = false, $args = array(), $url = '' ) { 282 | // pass our data to the action to allow a bypass 283 | do_action( 'airplane_mode_http_args', $status, $args, $url ); 284 | 285 | // disable the http requests only if enabled 286 | if ( $this->enabled() ) { 287 | return new WP_Error( 'airplane_mode_enabled', __( 'Airplane Mode is enabled', 'airplane-mode' ) ); 288 | } else { 289 | return $status; 290 | } 291 | } 292 | 293 | /** 294 | * Load our small CSS file for the toggle switch. 295 | */ 296 | public function toggle_css() { 297 | // set a suffix for loading the minified or normal 298 | $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.css' : '.min.css'; 299 | // load the CSS file itself 300 | wp_enqueue_style( 'airplane-mode', plugins_url( '/lib/css/airplane-mode' . $suffix, __FILE__ ), array(), AIRMDE_VER, 'all' ); 301 | } 302 | 303 | /** 304 | * Check the user action from the toggle switch to set the option 305 | * to 'on' or 'off'. 306 | * 307 | * @return void if any of the sanity checks fail and we bail early. 308 | */ 309 | public function toggle_check() { 310 | // bail if current user doesn't have cap 311 | if ( ! current_user_can( 'manage_options' ) ) { 312 | return; 313 | } 314 | 315 | // check for our nonce 316 | if ( ! isset( $_GET['airmde_nonce'] ) || ! wp_verify_nonce( $_GET['airmde_nonce'], 'airmde_nonce' ) ) { 317 | return; 318 | } 319 | 320 | // now check for our query string 321 | if ( ! isset( $_REQUEST['airplane-mode'] ) || ! in_array( $_REQUEST['airplane-mode'], array( 'on', 'off' ) ) ) { 322 | return; 323 | } 324 | 325 | // delete old per-site option 326 | delete_option( 'airplane-mode' ); 327 | 328 | // update the setting 329 | update_site_option( 'airplane-mode', sanitize_key( $_REQUEST['airplane-mode'] ) ); 330 | 331 | // and go about our business 332 | wp_redirect( self::get_redirect() ); 333 | exit; 334 | } 335 | 336 | /** 337 | * Fetch the URL to redirect to after toggling Airplane Mode. 338 | * 339 | * @return string The URL to redirect to. 340 | */ 341 | protected static function get_redirect() { 342 | 343 | return remove_query_arg( array( 344 | 'airplane-mode', 'airmde_nonce', 345 | 'user_switched', 'switched_off', 'switched_back', 346 | 'message', 'update', 'updated', 'settings-updated', 'saved', 347 | 'activated', 'activate', 'deactivate', 'enabled', 'disabled', 348 | 'locked', 'skipped', 'deleted', 'trashed', 'untrashed', 349 | ) ); 350 | 351 | } 352 | 353 | /** 354 | * Add our quick toggle to the admin bar to enable / disable 355 | * 356 | * @param WP_Admin_Bar $wp_admin_bar The admin bar object. 357 | * @return void if current user can't manage options and we bail early. 358 | */ 359 | public function admin_bar_toggle( WP_Admin_Bar $wp_admin_bar ) { 360 | // bail if current user doesn't have cap 361 | if ( ! current_user_can( 'manage_options' ) ) { 362 | return; 363 | } 364 | 365 | // get the current status 366 | $status = $this->enabled(); 367 | 368 | // set a title message (translatable) 369 | $title = ! $status ? __( 'Airplane Mode is disabled', 'airplane-mode' ) : __( 'Airplane Mode is enabled', 'airplane-mode' ); 370 | 371 | // set our toggle variable parameter (in reverse since we want the opposite action) 372 | $toggle = $status ? 'off' : 'on'; 373 | 374 | // determine our class based on the status 375 | $class = 'airplane-toggle-icon-'; 376 | $class .= $status ? 'on' : 'off'; 377 | 378 | // get my text 379 | $text = __( 'Airplane Mode', 'airplane-mode' ); 380 | 381 | // get my icon 382 | $icon = ''; 383 | 384 | // get our link with the status parameter 385 | $link = wp_nonce_url( add_query_arg( 'airplane-mode', $toggle ), 'airmde_nonce', 'airmde_nonce' ); 386 | 387 | // now add the admin bar link 388 | $wp_admin_bar->add_menu( 389 | array( 390 | 'id' => 'airplane-mode-toggle', 391 | 'title' => $icon . $text, 392 | 'href' => esc_url( $link ), 393 | 'position' => 0, 394 | 'meta' => array( 395 | 'title' => $title 396 | ) 397 | ) 398 | ); 399 | } 400 | 401 | /** 402 | * Filter a user's meta capabilities to prevent auto-updates from being attempted. 403 | * 404 | * @param array $caps Returns the user's actual capabilities. 405 | * @param string $cap Capability name. 406 | * @return array The user's filtered capabilities. 407 | */ 408 | function prevent_auto_updates( $caps, $cap ) { 409 | 410 | if ( $this->enabled() && in_array( $cap, array( 'update_plugins', 'update_themes', 'update_core' ) ) ) { 411 | $caps[] = 'do_not_allow'; 412 | } 413 | return $caps; 414 | } 415 | 416 | /// end class 417 | } 418 | 419 | // Instantiate our class 420 | $Airplane_Mode_Core = Airplane_Mode_Core::getInstance(); 421 | --------------------------------------------------------------------------------