Completed
Push — add/custom-footer-credit ( 059332 )
by
unknown
38:23 queued 21:54
created

theme-optimizations.php ➔ wpcom_better_footer_links()   F

Complexity

Conditions 16
Paths 289

Size

Total Lines 144
Code Lines 83

Duplication

Lines 3
Ratio 2.08 %

Importance

Changes 0
Metric Value
cc 16
eloc 83
nc 289
nop 1
dl 3
loc 144
rs 3.7109
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Create an output buffer to capture the HTML content of the footer.php theme
5
 * template. Used to change links, text, run a/b tests. Etc.
6
 *
7
 * @param string $page The HTML content from footer.php template file.
8
 * @return string $page HTML content.
9
 */
10
function wpcom_better_footer_links_buffer( $page ) {
11
	// Only add theme and colophon links for pub and premium themes, and VIP "partner" themes.
12 View Code Duplication
	if ( ! wpcom_is_pub_theme() && ! wpcom_is_premium_theme() && ! wpcom_is_vip_theme() && ! wpcom_is_a8c_theme() ) {
13
		return $page;
14
	}
15
16
	// Would like to only see footer content before wp_footer output.
17
	$output = preg_split( '/wpcom_wp_footer/i', $page, 2 );
18
19
	// Run "better link" filters.
20
	$footer = wpcom_better_footer_links( $output[0] );
21
22
	// Piece back together again.
23
	$page = implode( array( $footer, 'wpcom_wp_footer' . $output[1] ) );
24
25
	// If nothing to join, return empty string.
26
	if ( 'wpcom_wp_footer' === $page ) {
27
		return '';
28
	}
29
30
	// Replace any dangling references of glue code.
31
	$page = preg_replace( '/wpcom_wp_footer/i', '', $page );
32
33
	return $page;
34
}
35
36
/**
37
 * Better WP.com footer links.
38
 *
39
 * 1. Replace default "Powered by WordPress" text and link with
40
 * a link to WordPress.com and custom call-out text.
41
 *
42
 * 2. Replace theme name in footer with a link to relevant theme page on the Theme Showcase.
43
 * URL structure: http://theme.wordpress.com/themes/{theme-slug}/
44
 *
45
 * 3. Link to the Vertical landing page for sites that are stickered with a vertical.
46
 *
47
 * @param string $footer Footer HTML content to filter.
48
 * @return string $footer Filtered HTML content.
49
 */
50
function wpcom_better_footer_links( $footer ) {
51
	// Only add theme and colophon links for pub and premium themes, and VIP "partner" themes.
52 View Code Duplication
	if ( ! wpcom_is_pub_theme() && ! wpcom_is_premium_theme() && ! wpcom_is_vip_theme() && ! wpcom_is_a8c_theme() ) {
53
		return $footer;
54
	}
55
56
	// Get current theme data.
57
	$theme = wp_get_theme();
58
59
	// Replace separator from content, since we are replacing theme and designer credits.
60
	// Any span separator with a .sep class will be matched and replaced by the regular expression.
61
	$footer = preg_replace("/\s\|\s(?=\<a)|\<span class=\"([^\"]+\s)?sep(\s[^\"]+)?\">.*<\/span>/i", '', $footer);
62
63
	// Handle WP.com footer text.
64
	$lang = get_bloginfo( 'language' );
65
66
	$_blog_id = get_current_blog_id();
67
	$vertical = site_vertical( $_blog_id );
68
69
	$noads = defined( 'NOADVERTS' ) || defined( 'NOADSUPGRADE' );
70
	if ( $vertical ) {
71
		if ( $noads ) {
72
			$credit_link = sprintf( '<a href="%s">%s.</a>', localized_wpcom_url( 'https://wordpress.com/' . $vertical . '/?ref=vertical_footer', $lang ), __( 'Blog at WordPress.com' ) );
73
		} else {
74
			$credit_link = sprintf( '<a href="%s">%s.</a>', localized_wpcom_url( 'https://wordpress.com/' . $vertical . '/?ref=vertical_footer', $lang ), __( 'Create a free website at WordPress.com' ) );
75
		}
76
	} else if ( $noads || mt_rand( 0, 1 ) ) {
77
		$credit_link = sprintf( '<a href="%s">%s.</a>', localized_wpcom_url( 'https://wordpress.com/?ref=footer_blog', $lang ), __( 'Blog at WordPress.com' ) );
78
	} else {
79
		$credit_link = sprintf( '<a href="%s">%s.</a>', localized_wpcom_url( 'https://wordpress.com/?ref=footer_website', $lang ), __( 'Create a free website or blog at WordPress.com' ) );
80
	}
81
82
	// Replace credit link in footer, and make sure it is replaced only once, to avoid duplicates.
83
	$credit_link = apply_filters( 'wpcom_better_footer_credit_link', $credit_link, $lang );
84
85
	// The regular expression to match the credit link replacement.
86
	$credit_regex = implode( '', array(
87
		'#' , // Open delimiter
88
			'<a[^>]*href="http(s?)://(([a-z]{2}|www)\.)?(wordpress|wordpress-fr|wpfr)\.(com|org|net)/?"([^>]+)?>' , // Opening link tag
89
			    '\s*'   , // Optional whitespace
90
			    '(.+?)' , // Any word or sentence
91
			    '\s*'   , // Optional whitespace
92
			'</a>'      , // Closing link tag
93
			'\.?'       , // Optional period
94
			'(\s*&[^;]+;\s*)?' , // Optional HTML Entity
95
		'#i' , // Ending delimiter & modifier
96
	) );
97
98
	// Add filter for specific themes that may need to tweak the regex a bit.
99
	$credit_regex = apply_filters( 'wpcom_better_footer_credit_regex', $credit_regex, $theme );
100
101
	// Get the full matches of the credit regular expression, proceed if match.
102
	if ( preg_match_all( $credit_regex, $footer, $matches, PREG_OFFSET_CAPTURE ) ) {
103
104
		// Get last match and offset.
105
		$match = array_pop( $matches[0] );
106
		$offset = $match[1];
107
108
		// Split the content into two parts, which we will join later on.
109
		$before = substr( $footer, 0, $offset );
110
		$after = substr( $footer, $offset );
111
112
		// Replace on the last part. Ensure we only do one replacement to avoid duplicates.
113
		$after = preg_replace( $credit_regex, $credit_link, $after, 1 );
114
115
		// Join the two parts.
116
		$footer = $before . $after;
117
118
	}
119
120
	// Themes that have duplicate footer credit links (e.g. "Powered by WordPress.com" + another credit link).
121
	$powered_by_themes = array(
122
		'pub/toujours',
123
	);
124
125
	// Remove "Proudly powered by WordPress" on selected themes.
126
	if ( in_array( $theme->stylesheet, $powered_by_themes ) ) {
127
		$powered_string = preg_quote( __( 'Proudly powered by WordPress' ), '#' );
128
		$powered_regex = sprintf( '#<a[^>]*href="http(s?)://(([a-z]{2}|www)\.)?wordpress\.(com|org)/?"([^>]+)?>%s</a>\.?#i', $powered_string );
129
		$footer = preg_replace( $powered_regex, '', $footer );
130
	}
131
132
	// Only add theme and colophon link for pub and premium themes.
133
	if ( wpcom_is_vip_theme() ) {
134
		return $footer;
135
	}
136
137
	// Handle adding Theme Name and colophon link to footer text.
138
	$theme_match = sprintf(
139
		'(?:\s*\|\s*)?'       . // Optional pipe with spaces (non-capturing)
140
		'(?:<span\s[^>]+>)?'  . // Optional opening span tag (non-capturing)
141
		'(Theme|%s)'          . // $1: "Theme" or the localized equivalent
142
		'\s*(?:&nbsp;)?:\s*'  . // Zero or more whitespace characters, a colon, zero or more whitespace characters
143
		'(%s|<a[^>]+>%s</a>)' . // $2: The theme name, or link
144
		'\.?'                 . // Optional period
145
		'(?:</span>)?'        . // Optional closing span tag (non-capturing)
146
		'\.?'                   // Optional period
147
148
		, preg_quote( __( 'Theme' ), '#' )
149
		, preg_quote( $theme->name, '#' )
150
		, preg_quote( $theme->name, '#' )
151
	);
152
153
	// Theme designer match.
154
	$designer_match = $theme_match . sprintf(
155
		'('                       . // Start $3
156
		    '\s*'                 . // Zero or more whitespace characters
157
		    '(?:<span\s[^>]+>)?'  . // Optional opening span tag (non-capturing)
158
		    '(?:by|%s)'           . // "by" or the localized equivalent (non-capturing)
159
		    '(?:</span>)?'        . // Optional closing span tag (non-capturing)
160
		    '\s*'                 . // Zero or more whitespace characters
161
		    '(<a[^>]+>.+?</a>)?'  . // $4: Maybe a full <a> element
162
		')'                       . // End $3
163
		'\.?'                       // Optional period
164
165
		, preg_quote( __( 'by' ), '#' ) // localized "by" preposition
166
	);
167
168
	// Match "Design by <shop>".
169
	$design_by = preg_quote( $credit_link, '#' ) . sprintf(
170
		'\.?'                . // Optional period
171
		'\s*'                . // Optional whitespace
172
		'(Design by|%s)'     . // "Design by" or localized equivalent
173
		'\s*'                . // Optional whitespace
174
		'(<a[^>]+>.+?</a>)'  . // Full link element
175
		'\.?'                  // Optional period
176
177
		, preg_quote( __( 'Design by' ), '#' )
178
	);
179
180
	if ( preg_match( "#$designer_match#i", $footer ) ) {
181
		$footer = preg_replace( "#$designer_match#i", '', $footer, 1 );
182
	}
183
184
	if ( preg_match( "#$theme_match#i", $footer ) ) {
185
		$footer = preg_replace( "#$theme_match#i", '', $footer, 1 );
186
	}
187
188
	if ( preg_match( "#$design_by#i", $footer ) ) {
189
		$footer = preg_replace( "#$design_by#i", $credit_link, $footer, 1 );
190
	}
191
192
	return $footer;
193
}
194
195
// Enable filters for footer content for all themes, except VIP sites.
196
function better_wpcom_link_init() {
197
	if ( ! wpcom_is_vip() )
198
		ob_start( 'wpcom_better_footer_links_buffer' );
199
}
200
add_action( 'get_footer', 'better_wpcom_link_init' );
201
202
// Enable filters on those themes that need special treatment.
203
function better_wpcom_link_workarounds_init() {
204
	if ( function_exists( 'blogly_widgets_init' ) && 'premium/blogly' === wp_get_theme()->stylesheet ) {
205
		add_action( 'get_sidebar', 'better_wpcom_link_init' );
206
	}
207
	if ( function_exists( 'designer_widgets_init' ) && 'premium/designer' === wp_get_theme()->stylesheet ) {
208
		add_action( 'get_header', 'better_wpcom_link_init' );
209
	}
210
}
211
add_action( 'init', 'better_wpcom_link_workarounds_init' );
212
213
// Enable filters Infinite Scroll footer conntent, except VIP sites.
214
if ( ! wpcom_is_vip() ) {
215
	add_filter( 'infinite_scroll_credit', 'wpcom_better_footer_links' );
216
}
217
218
/**
219
 * Filters the default footer credits regex.
220
 *
221
 * @param string $credit_regex The regular expression for the footer credit.
222
 * @param object $theme The object returned by `wp_get_theme()`
223
 * @return string
224
 */
225
function wpcom_better_footer_credit_regex_filter( $credit_regex, $theme ) {
226
	// Twotone renders the social menu after the credit links. If there is a WordPress.com link in the menu,
227
	// it will break the footer credits. Adding a space before the actual link fixes this.
228
	if ( 'premium/twotone' === $theme->stylesheet ) {
229
		$credit_regex = str_replace( '#<a', '#\s<a', $credit_regex );
230
	}
231
	return $credit_regex;
232
}
233
add_filter( 'wpcom_better_footer_credit_regex', 'wpcom_better_footer_credit_regex_filter', 10, 2 );
234
235
/**
236
 * Add an HTML comment flag for wp_footer output so that our footer replacement
237
 * script knows when to stop looking for more footer content.
238
 */
239
function wpcom_footer_html_comment_flag() {
240
	echo "<!-- wpcom_wp_footer -->\n";
241
}
242
add_action( 'wp_footer', 'wpcom_footer_html_comment_flag', 9 );
243
244
/**
245
 * Add theme name to Twenty Ten footer
246
 */
247
function wpcomthemes_twentyten_credits() {
248
	echo 'Theme: Twenty Ten'; // leave untranslated for regex match, will be translated in final output
249
}
250
add_action( 'twentyten_credits', 'wpcomthemes_twentyten_credits' );
251
252
/**
253
 * Add theme name to Twenty Eleven footer
254
 */
255
function wpcomthemes_twentyeleven_credits() {
256
	echo 'Theme: Twenty Eleven <span class="sep"> | </span>'; // leave untranslated for regex match, will be translated in final output
257
}
258
add_action( 'twentyeleven_credits', 'wpcomthemes_twentyeleven_credits' );
259
260
/**
261
 * Add theme name to Twenty Twelve footer
262
 */
263
function wpcomthemes_twentytwelve_credits() {
264
	echo 'Theme: Twenty Twelve.'; // leave untranslated for regex match, will be translated in final output
265
}
266
add_action( 'twentytwelve_credits', 'wpcomthemes_twentytwelve_credits' );
267
268
/**
269
 * Add theme name to Twenty Thirteen footer
270
 */
271
function wpcomthemes_twentythirteen_credits() {
272
	echo 'Theme: Twenty Thirteen.'; // leave untranslated for regex match, will be translated in final output
273
}
274
add_action( 'twentythirteen_credits', 'wpcomthemes_twentythirteen_credits' );
275
276
/**
277
 * Add theme name to Twenty Fourteen footer
278
 */
279
function wpcomthemes_twentyfourteen_credits() {
280
	echo 'Theme: Twenty Fourteen.'; // leave untranslated for regex match, will be translated in final output
281
}
282
add_action( 'twentyfourteen_credits', 'wpcomthemes_twentyfourteen_credits' );
283
284
/**
285
 * Add theme name to Twenty Fifteen footer
286
 */
287
function wpcomthemes_twentyfifteen_credits() {
288
	echo 'Theme: Twenty Fifteen.'; // leave untranslated for regex match, will be translated in final output
289
}
290
add_action( 'twentyfifteen_credits', 'wpcomthemes_twentyfifteen_credits' );
291
292
/**
293
 * Add theme name to Twenty Sixteen footer
294
 */
295
function wpcomthemes_twentysixteen_credits() {
296
	echo 'Theme: Twenty Sixteen.'; // leave untranslated for regex match, will be translated in final output
297
}
298
add_action( 'twentysixteen_credits', 'wpcomthemes_twentysixteen_credits' );
299
300
/**
301
 * Prevent widows in post titles
302
 *
303
 * Isn't applied when the user is on a non-tablet mobile device, the title contains three or fewer words, or words are over a certain (filterable) length.
304
 *
305
 * A multi-byte aware re-implementation of this - http://www.shauninman.com/post/heap/2006/08/22/widont_wordpress_plugin
306
 *
307
 * DEVELOPER NOTE: Please run the units at bin/tests/content-filters/widont.php when updating this function!
308
 *
309
 * @param string $str
310
 * @uses jetpack_is_mobile()
311
 * @uses Jetpack_User_Agent_Info::is_tablet()
312
 * @uses apply_filters()
313
 * @filter the_title
314
 * @return string
315
 */
316
function widont( $str = '' ) {
317
	// Don't apply on non-tablet mobile devices so the browsers can fit to the viewport properly.
318
	if ( jetpack_is_mobile() && ! Jetpack_User_Agent_Info::is_tablet() ) {
319
		return $str;
320
	}
321
322
	// We're dealing with whitespace from here out, let's not have any false positives. :)
323
	$str = trim( $str );
324
325
	// If string contains three or fewer words, don't join.
326
	if ( count( preg_split( '#\s+#', $str ) ) <= 3 ) {
327
		return $str;
328
	}
329
330
	// Don't join if words exceed a certain length: minimum 10 characters, default 15 characters, filterable via `widont_max_word_length`.
331
	$widont_max_word_length = max( 10, absint( apply_filters( 'widont_max_word_length', 15 ) ) );
332
	$regex = '#\s+(\P{Z}{1,' . $widont_max_word_length . '})\s+(\P{Z}{1,' . $widont_max_word_length . '})$#u';
333
334
	return preg_replace( $regex, ' $1&nbsp;$2', $str );
335
}
336
add_filter( 'the_title', 'widont' );
337
338
function wido( $str = '' ) {
339
	return str_replace( '&#160;', ' ', $str );
340
}
341
add_filter( 'the_title_rss', 'wido' );
342
343
// Remove extra non-breaking spaces from menu titles - see #1718-wpcom
344
function wido_menu_titles( $content ) {
345
	return str_replace( '&nbsp;', ' ', $content );
346
}
347
add_filter( 'walker_nav_menu_start_el', 'wido_menu_titles' );
348
349
/**
350
 * Filter links to the Edit Post screen in the admin.
351
 *
352
 * These links now point to WP Admin, but we want users to be redirected to the new WP.com editor.
353
 */
354
function wpcom_edit_post_admin_url_redirect( $url, $post_id ) {
355
	$_blog_id = get_current_blog_id();
356
357
	if ( ! $post = get_post( $post_id ) ) {
358
		return $url;
359
	}
360
361
	if ( wpcom_is_vip( $_blog_id ) || ( is_super_admin() && ! is_user_member_of_blog( get_current_user_id(), $_blog_id ) ) ) {
362
		return $url;
363
	}
364
365
	$post_type = $post->post_type;
366
367
	if ( in_array( $post_type, array( 'post', 'page' ) ) ) {
368
		$path_prefix = $post_type;
369
	} else if ( in_array( $post_type, apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) ) ) ) {
370
		$path_prefix = sprintf( 'edit/%s', $post_type );
371
	}
372
373
	if ( ! isset( $path_prefix ) ) {
374
		return $url;
375
	}
376
377
	$site_slug = WPCOM_Masterbar::get_calypso_site_slug( $_blog_id );
378
	return esc_url_raw( sprintf( 'https://wordpress.com/%s/%s/%d', $path_prefix, $site_slug, $post_id ) );
379
}
380
381
function wpcom_edit_post_admin_url_redirect_add_hook() {
382
	add_filter( 'get_edit_post_link', 'wpcom_edit_post_admin_url_redirect', 10, 2 );
383
}
384
add_action( 'wp_head', 'wpcom_edit_post_admin_url_redirect_add_hook' );
385
386
function wpcom_edit_post_admin_url_redirect_remove_hook() {
387
	remove_filter( 'get_edit_post_link', 'wpcom_edit_post_admin_url_redirect', 10, 2 );
388
}
389
add_action( 'wp_footer', 'wpcom_edit_post_admin_url_redirect_remove_hook' );
390
391
/**
392
* Filter links to the New Post screen in the admin.
393
*
394
* These links now point to WP Admin, but we want users to be redirected to the new WP.com editor.
395
*/
396
function wpcom_new_post_admin_url_redirect( $url, $path ) {
397
	if ( 'post-new.php' !== $path || ( is_super_admin() && ! is_user_member_of_blog() ) ) {
398
		return $url;
399
	}
400
401
	$site_slug = WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
402
	return esc_url_raw( sprintf( 'https://wordpress.com/post/%s', $site_slug ) );
403
}
404
405
function wpcom_new_post_admin_url_redirect_add_hook() {
406
	add_filter( 'admin_url', 'wpcom_new_post_admin_url_redirect', 10, 2 );
407
}
408
add_action( 'wp_head', 'wpcom_new_post_admin_url_redirect_add_hook' );
409
410
function wpcom_new_post_admin_url_redirect_remove_hook() {
411
	remove_filter( 'admin_url', 'wpcom_new_post_admin_url_redirect', 10, 2 );
412
}
413
add_action( 'wp_footer', 'wpcom_new_post_admin_url_redirect_remove_hook' );
414
415
/**
416
 * When a default theme is enabled at signup (new blog creation), ensure that
417
 * it's mobile setting is turned off -- if the theme is responsive.
418
 *
419
 * See track_signup_default_theme() in wp-content/mu-plugins/usage.php
420
 *
421
 * @param int $_blog_id
422
 * @return void
423
 */
424
function wpcom_disable_mobile_theme_on_signup( $_blog_id ) {
425
 	global $wpdb;
426
 	$stylesheet = get_blog_option( (int) $_blog_id, 'stylesheet' );
427
428
 	// Avoid processing for signups that aren't new, like blog name changes.
429
 	if ( empty( $stylesheet ) || 'dashboard' == $stylesheet || 'h4' == $stylesheet ) {
430
 		return;
431
 	}
432
433
	// Disable mobile theme.
434
	if ( in_array( 'responsive-layout', wp_get_theme( $stylesheet )->get( 'Tags' ) ) ) {
435
		update_blog_option( $_blog_id, 'wp_mobile_disable', 1 );
436
	}
437
}
438
add_action( 'wpmu_new_blog', 'wpcom_disable_mobile_theme_on_signup', 10, 1 );
439