Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 125 |
|
0.00% |
0 / 13 |
CRAP | n/a |
0 / 0 |
|
| wpcom_better_footer_links_buffer | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
| wpcom_better_footer_links | |
0.00% |
0 / 85 |
|
0.00% |
0 / 1 |
56 | |||
| better_wpcom_link_init | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
12 | |||
| better_wpcom_link_workarounds_init | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
30 | |||
| wpcom_better_footer_credit_regex_filter | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| wpcom_footer_html_comment_flag | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentyten_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentyeleven_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentytwelve_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentythirteen_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentyfourteen_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentyfifteen_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| wpcomthemes_twentysixteen_credits | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php // phpcs:ignore Squiz.Commenting.FileComment.MissingPackageTag |
| 2 | /** |
| 3 | * This file is taken from wp-content/blog-plugins/theme-optimizations.php on wpcom and is split into this and 'theme-optimizations.php'. |
| 4 | */ |
| 5 | |
| 6 | /** |
| 7 | * Create an output buffer to capture the HTML content of the footer.php theme |
| 8 | * template. Used to change links, text, run a/b tests. Etc. |
| 9 | * |
| 10 | * @param string $page The HTML content from footer.php template file. |
| 11 | * @return string $page HTML content. |
| 12 | */ |
| 13 | function wpcom_better_footer_links_buffer( $page ) { |
| 14 | // Only add theme and colophon links for pub and premium themes, and VIP "partner" themes. |
| 15 | if ( ! apply_filters( 'wpcom_better_footer_credit_apply', true ) ) { |
| 16 | return $page; |
| 17 | } |
| 18 | |
| 19 | // Would like to only see footer content before wp_footer output. |
| 20 | $output = explode( 'wpcom_wp_footer', $page, 2 ); |
| 21 | |
| 22 | // Run "better link" filters. |
| 23 | $footer = wpcom_better_footer_links( $output[0] ); |
| 24 | |
| 25 | $remaining_content = $output[1] ?? ''; |
| 26 | |
| 27 | // Piece back together again. |
| 28 | $page = $footer . 'wpcom_wp_footer' . $remaining_content; |
| 29 | |
| 30 | // If nothing to join, return empty string. |
| 31 | if ( 'wpcom_wp_footer' === $page ) { |
| 32 | return ''; |
| 33 | } |
| 34 | |
| 35 | // Replace any dangling references of glue code. |
| 36 | $page = str_replace( 'wpcom_wp_footer', '', $page ); |
| 37 | |
| 38 | return $page; |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Better WP.com footer links. |
| 43 | * |
| 44 | * 1. Replace default "Powered by WordPress" text and link with |
| 45 | * a link to WordPress.com and custom call-out text. |
| 46 | * |
| 47 | * 2. Replace theme name in footer with a link to relevant theme page on the Theme Showcase. |
| 48 | * URL structure: http://theme.wordpress.com/themes/{theme-slug}/ |
| 49 | * |
| 50 | * 3. Link to the Vertical landing page for sites that are stickered with a vertical. |
| 51 | * |
| 52 | * @param string $footer Footer HTML content to filter. |
| 53 | * @return string $footer Filtered HTML content. |
| 54 | */ |
| 55 | function wpcom_better_footer_links( $footer ) { |
| 56 | // Only add theme and colophon links for pub and premium themes, and VIP "partner" themes. |
| 57 | if ( ! apply_filters( 'wpcom_better_footer_credit_apply', true ) ) { |
| 58 | return $footer; |
| 59 | } |
| 60 | |
| 61 | // Get current theme data. |
| 62 | $theme = wp_get_theme(); |
| 63 | |
| 64 | // Replace separator from content, since we are replacing theme and designer credits. |
| 65 | // Any span separator with a .sep class will be matched and replaced by the regular expression. |
| 66 | $footer = preg_replace( '/\s\|\s(?=\<a)|\<span class="([^"]+\s)?sep(\s[^"]+)?">.*<\/span>/i', '', $footer ); |
| 67 | |
| 68 | // Handle WP.com footer text. |
| 69 | $lang = get_bloginfo( 'language' ); |
| 70 | |
| 71 | // Replace credit link in footer, and make sure it is replaced only once, to avoid duplicates. |
| 72 | $credit_link = apply_filters( 'wpcom_better_footer_credit_link', '', $lang ); |
| 73 | |
| 74 | // The regular expression to match the credit link replacement. |
| 75 | $credit_regex = implode( |
| 76 | '', |
| 77 | array( |
| 78 | '#', // Open delimiter |
| 79 | '<a[^>]*href="http(s?)://(([a-z]{2}(-[A-Z]{2})?|www)\.)?(wordpress|wordpress-fr|wpfr)\.(com|org|net)/?"([^>]+)?>', // Opening link tag |
| 80 | '\s*', // Optional whitespace |
| 81 | '(.+?)', // Any word or sentence |
| 82 | '\s*', // Optional whitespace |
| 83 | '</a>', // Closing link tag |
| 84 | '\.?', // Optional period |
| 85 | '(\s*&[^;]+;\s*)?', // Optional HTML Entity |
| 86 | '#i', // Ending delimiter & modifier |
| 87 | ) |
| 88 | ); |
| 89 | |
| 90 | // Add filter for specific themes that may need to tweak the regex a bit. |
| 91 | $credit_regex = apply_filters( 'wpcom_better_footer_credit_regex', $credit_regex, $theme ); |
| 92 | |
| 93 | // Get the full matches of the credit regular expression, proceed if match. |
| 94 | if ( preg_match_all( $credit_regex, $footer, $matches, PREG_OFFSET_CAPTURE ) ) { |
| 95 | |
| 96 | // Get last match and offset. |
| 97 | $match = array_pop( $matches[0] ); |
| 98 | $offset = $match[1]; |
| 99 | |
| 100 | // Split the content into two parts, which we will join later on. |
| 101 | $before = substr( $footer, 0, $offset ); |
| 102 | $after = substr( $footer, $offset ); |
| 103 | |
| 104 | // Replace on the last part. Ensure we only do one replacement to avoid duplicates. |
| 105 | $after = preg_replace( $credit_regex, $credit_link, $after, 1 ); |
| 106 | |
| 107 | // Join the two parts. |
| 108 | $footer = $before . $after; |
| 109 | |
| 110 | } |
| 111 | |
| 112 | // Themes that have duplicate footer credit links (e.g. "Powered by WordPress.com" + another credit link). |
| 113 | $powered_by_themes = array( |
| 114 | 'pub/toujours', |
| 115 | ); |
| 116 | |
| 117 | // Remove "Proudly powered by WordPress" on selected themes. |
| 118 | if ( in_array( $theme->stylesheet, $powered_by_themes, true ) ) { |
| 119 | $powered_string = preg_quote( __( 'Proudly powered by WordPress', 'wpcomsh' ), '#' ); |
| 120 | // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText |
| 121 | $powered_regex = sprintf( '#<a[^>]*href="http(s?)://(([a-z]{2}|www)\.)?wordpress\.(com|org)/?"([^>]+)?>%s</a>\.?#i', $powered_string ); |
| 122 | $footer = preg_replace( $powered_regex, '', $footer ); |
| 123 | } |
| 124 | |
| 125 | // Handle adding Theme Name and colophon link to footer text. |
| 126 | $theme_regex = array( |
| 127 | '(?:\s*\|\s*)?', // Optional pipe with spaces (non-capturing) |
| 128 | '(?:<span\s[^>]+>)?', // Optional opening span tag (non-capturing) |
| 129 | '(Theme|%s)', // $1: "Theme" or the localized equivalent |
| 130 | '\s*(?: )?:?\s*', // Zero or more whitespace characters, an optional colon, zero or more whitespace characters |
| 131 | '(%s|<a[^>]+>%s</a>)', // $2: The theme name, or link |
| 132 | '\.?', // Optional period |
| 133 | '(?:</span>)?', // Optional closing span tag (non-capturing) |
| 134 | '\.?', // Optional period |
| 135 | ); |
| 136 | $theme_match = sprintf( |
| 137 | implode( $theme_regex ), |
| 138 | preg_quote( __( 'Theme', 'wpcomsh' ), '#' ), |
| 139 | preg_quote( $theme->name, '#' ), |
| 140 | preg_quote( $theme->name, '#' ) |
| 141 | ); |
| 142 | |
| 143 | // Theme designer match. |
| 144 | $designer_regex = array( |
| 145 | '(', // Start $3 |
| 146 | '\s*', // Zero or more whitespace characters |
| 147 | '(?:<span\s[^>]+>)?', // Optional opening span tag (non-capturing) |
| 148 | '(?:by|%s)', // "by" or the localized equivalent (non-capturing) |
| 149 | '(?:</span>)?', // Optional closing span tag (non-capturing) |
| 150 | '\s*', // Zero or more whitespace characters |
| 151 | '(<a[^>]+>.+?</a>)?', // $4: Maybe a full <a> element |
| 152 | ')', // End $3 |
| 153 | '\.?', // Optional period |
| 154 | ); |
| 155 | $designer_match = $theme_match . sprintf( |
| 156 | implode( $designer_regex ), |
| 157 | preg_quote( __( 'by', 'wpcomsh' ), '#' ) // localized "by" preposition |
| 158 | ); |
| 159 | |
| 160 | // Match "Design by <shop>". |
| 161 | $design_by_regex = array( |
| 162 | '\.?', // Optional period |
| 163 | '\s*', // Optional whitespace |
| 164 | '(Design by|%s)', // "Design by" or localized equivalent |
| 165 | '\s*', // Optional whitespace |
| 166 | '(<a[^>]+>.+?</a>)', // Full link element |
| 167 | '\.?', // Optional period |
| 168 | ); |
| 169 | $design_by = preg_quote( $credit_link, '#' ) . sprintf( |
| 170 | implode( $design_by_regex ), |
| 171 | preg_quote( __( 'Design by', 'wpcomsh' ), '#' ) |
| 172 | ); |
| 173 | |
| 174 | if ( preg_match( "#$designer_match#i", $footer ) ) { |
| 175 | $footer = preg_replace( "#$designer_match#i", '', $footer, 1 ); |
| 176 | } |
| 177 | |
| 178 | if ( preg_match( "#$theme_match#i", $footer ) ) { |
| 179 | $footer = preg_replace( "#$theme_match#i", '', $footer, 1 ); |
| 180 | } |
| 181 | |
| 182 | if ( preg_match( "#$design_by#i", $footer ) ) { |
| 183 | $footer = preg_replace( "#$design_by#i", $credit_link, $footer, 1 ); |
| 184 | } |
| 185 | |
| 186 | return $footer; |
| 187 | } |
| 188 | |
| 189 | /** |
| 190 | * Enable filters for footer content for all themes, except VIP sites. |
| 191 | */ |
| 192 | function better_wpcom_link_init() { |
| 193 | if ( apply_filters( 'wpcom_better_footer_credit_apply', true ) && ! wp_is_json_request() ) { |
| 194 | ob_start( 'wpcom_better_footer_links_buffer' ); |
| 195 | } |
| 196 | } |
| 197 | add_action( 'get_footer', 'better_wpcom_link_init' ); |
| 198 | |
| 199 | /** |
| 200 | * Enable filters on those themes that need special treatment. |
| 201 | */ |
| 202 | function better_wpcom_link_workarounds_init() { |
| 203 | if ( function_exists( 'blogly_widgets_init' ) && 'premium/blogly' === wp_get_theme()->stylesheet ) { |
| 204 | add_action( 'get_sidebar', 'better_wpcom_link_init' ); |
| 205 | } |
| 206 | if ( function_exists( 'designer_widgets_init' ) && 'premium/designer' === wp_get_theme()->stylesheet ) { |
| 207 | add_action( 'get_header', 'better_wpcom_link_init' ); |
| 208 | } |
| 209 | } |
| 210 | add_action( 'init', 'better_wpcom_link_workarounds_init' ); |
| 211 | |
| 212 | // Enable filters Infinite Scroll footer conntent, except VIP sites. |
| 213 | if ( ! apply_filters( 'wpcom_better_footer_credit_apply', true ) ) { |
| 214 | add_filter( 'infinite_scroll_credit', 'wpcom_better_footer_links' ); |
| 215 | } |
| 216 | |
| 217 | /** |
| 218 | * Filters the default footer credits regex. |
| 219 | * |
| 220 | * @param string $credit_regex The regular expression for the footer credit. |
| 221 | * @param object $theme The object returned by `wp_get_theme()`. |
| 222 | * @return string |
| 223 | */ |
| 224 | function wpcom_better_footer_credit_regex_filter( $credit_regex, $theme ) { |
| 225 | // Twotone renders the social menu after the credit links. If there is a WordPress.com link in the menu, |
| 226 | // it will break the footer credits. Adding a space before the actual link fixes this. |
| 227 | if ( 'premium/twotone' === $theme->stylesheet ) { |
| 228 | $credit_regex = str_replace( '#<a', '#\s<a', $credit_regex ); |
| 229 | } |
| 230 | return $credit_regex; |
| 231 | } |
| 232 | add_filter( 'wpcom_better_footer_credit_regex', 'wpcom_better_footer_credit_regex_filter', 10, 2 ); |
| 233 | |
| 234 | /** |
| 235 | * Add an HTML comment flag for wp_footer output so that our footer replacement |
| 236 | * script knows when to stop looking for more footer content. |
| 237 | */ |
| 238 | function wpcom_footer_html_comment_flag() { |
| 239 | echo "<!-- wpcom_wp_footer -->\n"; |
| 240 | } |
| 241 | add_action( 'wp_footer', 'wpcom_footer_html_comment_flag', 9 ); |
| 242 | |
| 243 | /** |
| 244 | * Add theme name to Twenty Ten footer |
| 245 | */ |
| 246 | function wpcomthemes_twentyten_credits() { |
| 247 | echo 'Theme: Twenty Ten'; // leave untranslated for regex match, will be translated in final output |
| 248 | } |
| 249 | add_action( 'twentyten_credits', 'wpcomthemes_twentyten_credits' ); |
| 250 | |
| 251 | /** |
| 252 | * Add theme name to Twenty Eleven footer |
| 253 | */ |
| 254 | function wpcomthemes_twentyeleven_credits() { |
| 255 | echo 'Theme: Twenty Eleven <span class="sep"> | </span>'; // leave untranslated for regex match, will be translated in final output |
| 256 | } |
| 257 | add_action( 'twentyeleven_credits', 'wpcomthemes_twentyeleven_credits' ); |
| 258 | |
| 259 | /** |
| 260 | * Add theme name to Twenty Twelve footer |
| 261 | */ |
| 262 | function wpcomthemes_twentytwelve_credits() { |
| 263 | echo 'Theme: Twenty Twelve.'; // leave untranslated for regex match, will be translated in final output |
| 264 | } |
| 265 | add_action( 'twentytwelve_credits', 'wpcomthemes_twentytwelve_credits' ); |
| 266 | |
| 267 | /** |
| 268 | * Add theme name to Twenty Thirteen footer |
| 269 | */ |
| 270 | function wpcomthemes_twentythirteen_credits() { |
| 271 | echo 'Theme: Twenty Thirteen.'; // leave untranslated for regex match, will be translated in final output |
| 272 | } |
| 273 | add_action( 'twentythirteen_credits', 'wpcomthemes_twentythirteen_credits' ); |
| 274 | |
| 275 | /** |
| 276 | * Add theme name to Twenty Fourteen footer |
| 277 | */ |
| 278 | function wpcomthemes_twentyfourteen_credits() { |
| 279 | echo 'Theme: Twenty Fourteen.'; // leave untranslated for regex match, will be translated in final output |
| 280 | } |
| 281 | add_action( 'twentyfourteen_credits', 'wpcomthemes_twentyfourteen_credits' ); |
| 282 | |
| 283 | /** |
| 284 | * Add theme name to Twenty Fifteen footer |
| 285 | */ |
| 286 | function wpcomthemes_twentyfifteen_credits() { |
| 287 | echo 'Theme: Twenty Fifteen.'; // leave untranslated for regex match, will be translated in final output |
| 288 | } |
| 289 | add_action( 'twentyfifteen_credits', 'wpcomthemes_twentyfifteen_credits' ); |
| 290 | |
| 291 | /** |
| 292 | * Add theme name to Twenty Sixteen footer |
| 293 | */ |
| 294 | function wpcomthemes_twentysixteen_credits() { |
| 295 | echo 'Theme: Twenty Sixteen.'; // leave untranslated for regex match, will be translated in final output |
| 296 | } |
| 297 | add_action( 'twentysixteen_credits', 'wpcomthemes_twentysixteen_credits' ); |