eth-escape-headspace.php 6.59 KB
Newer Older
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
  Plugin Name: ETH Escape HeadSpace2
  Plugin URI: https://ethitter.com/plugins/
  Description: Output existing HeadSpace2 data without the original plugin. Allows HeadSpace2 (no longer maintained) to be deactivated without impactacting legacy content.
  Author: Erick Hitter
  Version: 0.2.1
  Author URI: https://ethitter.com/

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * Class ETH_Escape_HeadSpace2.
 */
Erick Hitter's avatar
Erick Hitter committed
28 29 30
class ETH_Escape_HeadSpace2 {
	/**
	 * Singleton
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
31 32
	 *
	 * @var self
Erick Hitter's avatar
Erick Hitter committed
33 34 35 36 37 38 39 40
	 */
	private static $instance = null;

	/**
	 * Instantiate singleton
	 */
	public static function get_instance() {
		if ( ! is_a( self::$instance, __CLASS__ ) ) {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
41
			self::$instance = new self();
Erick Hitter's avatar
Erick Hitter committed
42 43 44 45 46 47
		}

		return self::$instance;
	}

	/**
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
48 49 50
	 * Headspace's string keys.
	 *
	 * @var array
51
	 */
52
	private $hs_string_keys = array(
53 54
		'_headspace_description',
		'_headspace_metakey',
55 56 57
		'_headspace_raw',
	);

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
58 59 60 61 62
	/**
	 * Headspace's array keys.
	 *
	 * @var array
	 */
63 64 65
	private $hs_array_keys = array(
		'_headspace_scripts',
		'_headspace_stylesheets',
66 67
	);

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
68
	/**
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
69
	 * Headspace's robots.txt keys.
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
70 71 72
	 *
	 * @var array
	 */
73
	private $hs_robots_keys = array(
74
		'_headspace_noindex',
75 76 77 78
		'_headspace_nofollow',
		'_headspace_noarchive',
		'_headspace_noodp',
		'_headspace_noydir',
79 80
	);

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
81 82 83 84 85
	/**
	 * Map Headspace keys.
	 *
	 * @var array
	 */
86 87 88 89 90
	private $hs_keys_to_meta_names = array(
		'_headspace_description' => 'description',
		'_headspace_metakey'     => 'keywords',
	);

91
	/**
92 93
	 * Defer plugin hook additions until all plugins are loaded
	 * Allows plugin to defer to HeadSpace2 when active
Erick Hitter's avatar
Erick Hitter committed
94 95 96 97
	 *
	 * @return null
	 */
	private function __construct() {
98 99 100 101 102 103 104
		add_action( 'plugins_loaded', array( $this, 'maybe_add_hooks' ) );
	}

	/**
	 * Conditionally register plugin's hooks
	 */
	public function maybe_add_hooks() {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
105
		// Defer to HeadSpace2 when active.
106 107 108 109
		if ( class_exists( 'HeadSpace_Plugin' ) ) {
			return;
		}

Erick Hitter's avatar
Erick Hitter committed
110
		add_filter( 'pre_get_document_title', array( $this, 'filter_pre_get_document_title' ) );
Erick Hitter's avatar
Erick Hitter committed
111 112
		add_filter( 'wp_title', array( $this, 'filter_wp_title' ), 10, 3 );

113
		add_action( 'wp_head', array( $this, 'action_wp_head' ) );
Erick Hitter's avatar
Erick Hitter committed
114
		add_action( 'wp_footer', array( $this, 'action_wp_footer' ) );
115 116
	}

Erick Hitter's avatar
Erick Hitter committed
117
	/**
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
118 119 120 121
	 * Filter page titles in WP 4.1+ themes add_theme_support( 'title-tag' ).
	 *
	 * @param string $title Page title.
	 * @return string
Erick Hitter's avatar
Erick Hitter committed
122 123 124 125 126 127 128 129 130 131 132 133 134
	 */
	public function filter_pre_get_document_title( $title ) {
		$_title = get_post_meta( get_the_ID(), '_headspace_page_title', true );

		if ( ! empty( $_title ) ) {
			$title = esc_html( $_title );
		}

		unset( $_title );

		return $title;
	}

Erick Hitter's avatar
Erick Hitter committed
135
	/**
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
136 137 138 139 140 141
	 * Filter page titles in themes designed for < WP 4.1 wp_title().
	 *
	 * @param string $title Object title.
	 * @param string $sep   Title separator.
	 * @param string $loc   Separator location.
	 * @return string
Erick Hitter's avatar
Erick Hitter committed
142 143 144 145 146 147 148
	 */
	public function filter_wp_title( $title, $sep, $loc ) {
		$_title = get_post_meta( get_the_ID(), '_headspace_page_title', true );

		if ( ! empty( $_title ) ) {
			$_title = esc_html( $_title );

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
149
			if ( 'right' === $loc ) {
Erick Hitter's avatar
Erick Hitter committed
150 151 152 153 154 155 156 157 158 159 160
				$title = $_title . ' ' . $sep . ' ';
			} else {
				$title = ' ' . $sep . ' ' . $_title;
			}
		}

		unset( $_title );

		return $title;
	}

161
	/**
Erick Hitter's avatar
Erick Hitter committed
162
	 * Add <head> meta tags
163 164
	 */
	public function action_wp_head() {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
165
		// Applies only to individual post objects.
166 167 168 169
		if ( ! is_singular() ) {
			return;
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
170
		// Check for HS data.
171 172
		$hs_data = array();

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
173
		// Keys that only exist once per post.
174
		foreach ( array_merge( $this->hs_string_keys, $this->hs_robots_keys ) as $hs_key ) {
175 176 177 178 179 180 181
			$value = get_post_meta( get_the_ID(), $hs_key, true );

			if ( ! empty( $value ) ) {
				$hs_data[ $hs_key ] = $value;
			}
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
182
		// Keys that can exist multiple times per post.
183 184 185 186 187 188 189 190
		foreach ( $this->hs_array_keys as $hs_key ) {
			$values = get_post_meta( get_the_ID(), $hs_key, false );

			if ( ! empty( $values ) ) {
				$hs_data[ $hs_key ] = $values;
			}
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
191
		// Bail if no HS data exists for this post.
192 193 194 195
		if ( empty( $hs_data ) ) {
			return;
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
196
		// Handle basic, string-containing keys.
197 198
		$output = array();

199
		foreach ( $hs_data as $hs_key => $hs_value ) {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
200 201 202
			switch ( $hs_key ) {
				case '_headspace_description':
				case '_headspace_metakey':
203 204 205
					$output[] = '<meta name="' . esc_attr( $this->hs_keys_to_meta_names[ $hs_key ] ) . '" content="' . esc_attr( $hs_value ) . '" />';
					break;

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
206
				case '_headspace_scripts':
207 208 209 210 211
					foreach ( $hs_value as $_source ) {
						$output[] = '<script type="text/javascript" src="' . esc_url( $_source ) . '"></script>';
					}
					break;

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
212
				case '_headspace_stylesheets':
213 214 215
					foreach ( $hs_value as $_source ) {
						$output[] = '<link rel="stylesheet" href="' . esc_url( $_source ) . '" type="text/css" />';
					}
216 217
					break;

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
218
				default:
Erick Hitter's avatar
Erick Hitter committed
219
					continue 2;
220 221 222
					break;
			}
		}
223

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
224
		// Handle robots key, which is build from several meta keys.
225 226 227
		$robots = array();

		foreach ( $this->hs_robots_keys as $hs_robot_key ) {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
228
			if ( isset( $hs_data[ $hs_robot_key ] ) ) {
229 230 231 232 233 234 235 236 237 238 239
				$robots[] = str_replace( '_headspace_', '', $hs_robot_key );
			}
		}

		if ( ! empty( $robots ) ) {
			if ( 1 === count( $robots ) && in_array( 'noindex', $robots ) ) {
				$robots[] = 'follow';
			}

			$robots = implode( ',', $robots );

240 241 242
			$output[] = '<meta name="robots" content="' . esc_attr( $robots ) . '" />' . "\n";
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
243
		// Raw output should follow all other output.
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
244 245
		if ( ! empty( $hs_data['_headspace_raw'] ) ) {
			$output[] = $hs_data['_headspace_raw'];
246 247
		}

Erick Hitter's avatar
PHPCS  
Erick Hitter committed
248
		// Output whatever we've built.
249
		if ( ! empty( $output ) ) {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
250
			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
Erick Hitter's avatar
Erick Hitter committed
251
			echo "\n<!-- Escape HeadSpace2 by Erick Hitter; https://ethitter.com/plugins/ -->\n" . implode( "\n", $output ) . "\n<!-- Escape HeadSpace2 -->\n";
252
		}
Erick Hitter's avatar
Erick Hitter committed
253
	}
Erick Hitter's avatar
Erick Hitter committed
254 255

	/**
Erick Hitter's avatar
Erick Hitter committed
256
	 * Add custom footer content
Erick Hitter's avatar
Erick Hitter committed
257 258 259 260 261
	 */
	public function action_wp_footer() {
		$output = get_post_meta( get_the_ID(), '_headspace_raw_footer', true );

		if ( ! empty( $output ) ) {
Erick Hitter's avatar
PHPCS  
Erick Hitter committed
262
			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
Erick Hitter's avatar
Erick Hitter committed
263 264 265
			echo $output . "\n";
		}
	}
Erick Hitter's avatar
Erick Hitter committed
266 267 268
}

ETH_Escape_HeadSpace2::get_instance();