PluginProbe ʕ •ᴥ•ʔ
External Links – nofollow, noopener & new window / 2.50
External Links – nofollow, noopener & new window v2.50
0.31 0.32 0.33 0.34 0.35 1.01 1.02 1.03 1.10 1.20 1.21 1.30 1.31 1.40 1.41 1.50 1.51 1.52 1.53 1.54 1.55 1.56 1.60 1.61 1.62 1.70 1.80 1.81 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1.0 2.1.1 2.1.2 2.1.3 2.2.0 2.3 2.32 2.35 2.40 2.42 2.43 2.45 2.46 2.47 2.48 2.50 2.51 2.55 2.56 2.57 2.58 2.59 2.60 2.61 2.62 2.63 2.64 2.65 trunk 0.10 0.11 0.12 0.20 0.21 0.30
wp-external-links / includes / class-wpel-front.php
wp-external-links / includes Last commit date
admin 5 years ago register-hooks 7 years ago class-wpel-front-ignore.php 7 years ago class-wpel-front.php 5 years ago class-wpel-link.php 7 years ago class-wpel-linkhero.php 5 years ago class-wpel-plugin.php 5 years ago class-wpel-register-scripts.php 5 years ago class-wpel-template-tags.php 7 years ago class-wpel-update.php 5 years ago index.php 6 years ago
class-wpel-front.php
481 lines
1 <?php
2 /**
3 * Class WPEL_Front
4 *
5 * @package WPEL
6 * @category WordPress Plugin
7 * @version 2.3
8 * @link https://www.webfactoryltd.com/
9 * @license Dual licensed under the MIT and GPLv2+ licenses
10 */
11 final class WPEL_Front extends WPRun_Base_1x0x0
12 {
13
14 /**
15 * @var WPEL_Settings_Page
16 */
17 private $settings_page = null;
18
19 /**
20 * Initialize
21 * @param WPEL_Settings_Page $settings_page
22 */
23 protected function init( WPEL_Settings_Page $settings_page )
24 {
25 $this->settings_page = $settings_page;
26
27 // load front ignore
28 WPEL_Front_Ignore::create( $settings_page );
29
30 // load template tags
31 WPEL_Template_Tags::create( $this );
32
33 // apply page sections
34 if ( $this->opt( 'apply_all' ) ) {
35 // create final_output filterhook
36 FWP_Final_Output_1x0x0::create();
37
38 add_action( 'final_output', $this->get_callback( 'scan' ), 10000000000 );
39 } else {
40 $filter_hooks = array();
41
42 if ( $this->opt( 'apply_post_content' ) ) {
43 array_push( $filter_hooks, 'the_title', 'the_content', 'the_excerpt', 'get_the_excerpt' );
44 }
45
46 if ( $this->opt( 'apply_comments' ) ) {
47 array_push( $filter_hooks, 'comment_text', 'comment_excerpt' );
48 }
49
50 if ( $this->opt( 'apply_widgets' ) ) {
51 // create widget_output filterhook
52 FWP_Widget_Output_1x0x0::create();
53
54 array_push( $filter_hooks, 'widget_output' );
55 }
56
57 foreach ( $filter_hooks as $hook ) {
58 add_filter( $hook, $this->get_callback( 'scan' ), 10000000000 );
59 }
60 }
61
62
63 }
64
65
66 /**
67 * Turn off output buffer for REST API calls
68 * @param type $wp_rest_server
69 */
70 protected function action_rest_api_init()
71 {
72 ob_end_flush();
73 }
74
75
76 /**
77 * Get option value
78 * @param string $key
79 * @param string|null $type
80 * @return string
81 * @triggers E_USER_NOTICE Option value cannot be found
82 */
83 protected function opt( $key, $type = null )
84 {
85 return $this->settings_page->get_option_value( $key, $type );
86 }
87
88 /**
89 * Action for "wp_enqueue_scripts"
90 */
91 protected function action_wp_enqueue_scripts()
92 {
93 $icon_type_int = $this->opt( 'icon_type', 'internal-links' );
94 $icon_type_ext = $this->opt( 'icon_type', 'external-links' );
95
96 if ( 'dashicon' === $icon_type_int || 'dashicon' === $icon_type_ext ) {
97 wp_enqueue_style( 'dashicons' );
98 }
99
100 if ( 'fontawesome' === $icon_type_int || 'fontawesome' === $icon_type_ext ) {
101 wp_enqueue_style( 'font-awesome' );
102 }
103
104 if ( $this->opt( 'icon_type', 'external-links' ) || $this->opt( 'icon_type', 'internal-links' ) ) {
105 wp_enqueue_style( 'wpel-style' );
106 }
107
108 wp_register_script(
109 'wpel-link-highlighter',
110 plugins_url('/public/js/wpel-link-highlighter.js', WPEL_Plugin::get_plugin_file()),
111 array('jquery'),
112 false,
113 true
114 );
115
116 if(isset($_GET['wpel-link-highlight'])){
117 wp_enqueue_script( 'wpel-link-highlighter' );
118 }
119 }
120
121 /**
122 * Scan content for links
123 * @param string $content
124 * @return string
125 */
126 public function scan( $content )
127 {
128 /**
129 * Filter whether the plugin settings will be applied on links
130 * @param boolean $apply_settings
131 */
132 $apply_settings = apply_filters( 'wpel_apply_settings', true );
133
134 if ( false === $apply_settings ) {
135 return $content;
136 }
137
138 /**
139 * Filters before scanning content (for internal use)
140 * @param string $content
141 */
142 $content = apply_filters( '_wpel_before_filter', $content );
143
144 $regexp_link = '/<a[^A-Za-z>](.*?)>(.*?)<\/a[\s+]*>/is';
145
146 $content = preg_replace_callback( $regexp_link, $this->get_callback( 'match_link' ), $content );
147
148 /**
149 * Filters after scanning content (for internal use)
150 * @param string $content
151 */
152 $content = apply_filters( '_wpel_after_filter', $content );
153
154 return $content;
155 }
156
157 /**
158 * Pregmatch callback for handling link
159 * @param array $matches [ 0 ] => link, [ 1 ] => atts_string, [ 2 ] => label
160 * @return string
161 */
162 protected function match_link( $matches )
163 {
164 $original_link = $matches[ 0 ];
165 $atts = $matches[ 1 ];
166 $label = $matches[ 2 ];
167
168 if(strpos($atts,'href') === false){
169 return $original_link;
170 }
171
172 $created_link = $this->get_created_link( $label, $atts );
173
174 if ( false === $created_link ) {
175 return $original_link;
176 }
177
178 return $created_link;
179 }
180
181 /**
182 * Create html link
183 * @param string $label
184 * @param string $atts
185 * @return string
186 */
187 protected function get_created_link( $label, $atts )
188 {
189 $link = new WPEL_Link( 'a', $label );
190 $link->set_atts( $atts );
191
192 /**
193 * Action triggered before link settings will be applied
194 * @param WPEL_Link $link
195 * @return void
196 */
197 do_action( 'wpel_before_apply_link', $link );
198
199 // has ignore flag
200 if ( $link->is_ignore() ) {
201 return false;
202 }
203
204 $this->set_link( $link );
205
206 return $link->get_html( false );
207 }
208
209 /**
210 * Set link
211 * @param WPEL_Link $link
212 */
213 protected function set_link( WPEL_Link $link )
214 {
215 $url = $link->get_attr( 'href' );
216
217 $excludes_as_internal_links = $this->opt( 'excludes_as_internal_links' );
218
219 // internal, external or excluded
220 $is_excluded = $link->is_exclude() || $this->is_excluded_url( $url );
221 $is_internal = $link->is_internal() || ( $this->is_internal_url( $url ) && ! $this->is_included_url( $url ) ) || ( $is_excluded && $excludes_as_internal_links );
222 $is_external = $link->is_external() || ( ! $is_internal && ! $is_excluded );
223
224 if (strpos($url,'#') === 0) {
225 // skip anchors
226 } else if ( $is_external ) {
227 $link->set_external();
228 $this->apply_link_settings( $link, 'external-links' );
229 } else if ( $is_internal ) {
230 $link->set_internal();
231 $this->apply_link_settings( $link, 'internal-links' );
232 } else if ( $is_excluded ) {
233 $link->set_exclude();
234 $this->apply_link_settings( $link, 'excluded-links' );
235 }
236
237 /**
238 * Action for changing link object
239 * @param WPEL_Link $link
240 * @return void
241 */
242 do_action( 'wpel_link', $link );
243 }
244
245 /**
246 * @param WPEL_Link $link
247 * @param string $type
248 */
249 protected function apply_link_settings( WPEL_Link $link, $type )
250 {
251 if ( ! $this->opt( 'apply_settings', $type ) ) {
252 return;
253 }
254
255 // set target
256 $target = $this->opt( 'target', $type );
257 $target_overwrite = $this->opt( 'target_overwrite', $type );
258 $has_target = $link->has_attr( 'target' );
259
260 if ( $target && ( ! $has_target || $target_overwrite ) ) {
261 $link->set_attr( 'target', $target );
262 }
263
264 // add "follow" / "nofollow"
265 $follow = $this->opt( 'rel_follow', $type );
266 $follow_overwrite = $this->opt( 'rel_follow_overwrite', $type );
267 $has_follow = $link->has_attr_value( 'rel', 'follow' ) || $link->has_attr_value( 'rel', 'nofollow' );
268
269 if ( $follow && ( ! $has_follow || $follow_overwrite ) ) {
270 if ( $has_follow ) {
271 $link->remove_from_attr( 'rel', 'follow' );
272 $link->remove_from_attr( 'rel', 'nofollow' );
273 }
274
275 $link->add_to_attr( 'rel', $follow );
276 }
277
278 // add "external"
279 if ( 'external-links' === $type && $this->opt( 'rel_external', $type ) ) {
280 $link->add_to_attr( 'rel', 'external' );
281 }
282
283 // add "noopener"
284 if ( $this->opt( 'rel_noopener', $type ) ) {
285 $link->add_to_attr( 'rel', 'noopener' );
286 }
287
288 // add "noreferrer"
289 if ( $this->opt( 'rel_noreferrer', $type ) ) {
290 $link->add_to_attr( 'rel', 'noreferrer' );
291 }
292
293 // add "sponsored"
294 if ( 'external-links' === $type && $this->opt( 'rel_sponsored', $type ) ) {
295 $link->add_to_attr( 'rel', 'sponsored' );
296 }
297
298 // add "ugc"
299 if ( 'external-links' === $type && $this->opt( 'rel_ugc', $type ) ) {
300 $link->add_to_attr( 'rel', 'ugc' );
301 }
302
303 // set title
304 $title_format = $this->opt( 'title', $type );
305
306 if ( $title_format ) {
307 $title = $link->get_attr( 'title' );
308 $text = $link->get_content();
309 $new_title = str_replace( array( '{title}', '{text}', '{text_clean}' ), array( esc_attr( $title ), esc_attr( $text ), esc_attr( strip_tags( $text ) ) ), $title_format );
310
311 if ( $new_title ) {
312 $link->set_attr( 'title', $new_title );
313 }
314 }
315
316 // add classes
317 $class = $this->opt( 'class', $type );
318
319 if ( $class ) {
320 $link->add_to_attr( 'class', $class );
321 }
322
323 // add icon
324 $icon_type = $this->opt( 'icon_type', $type );
325 $no_icon_for_img = $this->opt( 'no_icon_for_img', $type );
326 $has_img = preg_match( '/<img([^>]*)>/is', $link->get_content() );
327
328 if ( $icon_type && ! ( $has_img && $no_icon_for_img ) && ! $link->has_attr_value( 'class', 'wpel-no-icon' ) ) {
329 if ( 'dashicon' === $icon_type ) {
330 $dashicon = $this->opt( 'icon_dashicon', $type );
331 $icon = '<i class="wpel-icon dashicons-before '. $dashicon .'" aria-hidden="true"></i>';
332 } else if ( 'fontawesome' === $icon_type ) {
333 $fa = $this->opt( 'icon_fontawesome', $type );
334 $icon = '<i class="wpel-icon fa '. $fa .'" aria-hidden="true"></i>';
335 } else if ( 'image' === $icon_type ) {
336 $image = $this->opt( 'icon_image', $type );
337 $icon = '<span class="wpel-icon wpel-image wpel-icon-'. $image .'"></span>';
338 }
339
340 if ( 'left' === $this->opt( 'icon_position', $type ) ) {
341 $link->add_to_attr( 'class', 'wpel-icon-left' );
342 $link->set_content( $icon . $link->get_content() );
343 } else if ( 'right' === $this->opt( 'icon_position', $type ) ) {
344 $link->add_to_attr( 'class', 'wpel-icon-right' );
345 $link->set_content( $link->get_content() . $icon );
346 }
347 }
348 }
349
350 /**
351 * Check if url is included as external link
352 * @param string $url
353 * @return boolean
354 */
355 protected function is_included_url( $url )
356 {
357 // should be using private property, but static is more practical
358 static $include_urls_arr = null;
359
360 if ( null === $include_urls_arr ) {
361 $include_urls = $this->opt( 'include_urls' );
362 $include_urls = str_replace( "\n", ',', $include_urls );
363
364 if ( '' === trim( $include_urls ) ) {
365 $include_urls_arr = array();
366 } else {
367 $include_urls_arr = explode( ',', $include_urls );
368 }
369
370 $include_urls_arr = array_filter( $include_urls_arr, function ( $url ) {
371 return '' !== trim( $url );
372 } );
373 }
374
375 foreach ( $include_urls_arr as $include_url ) {
376 if ( false !== strpos( $url, $include_url ) ) {
377 return true;
378 }
379 }
380
381 return false;
382 }
383
384 /**
385 * Check if url is excluded as external link
386 * @param string $url
387 * @return boolean
388 */
389 protected function is_excluded_url( $url )
390 {
391 // should be using private property, but static is more practical
392 static $exclude_urls_arr = null;
393
394 if ( null === $exclude_urls_arr ) {
395 $exclude_urls = $this->opt( 'exclude_urls' );
396 $exclude_urls = str_replace( "\n", ',', $exclude_urls );
397
398 if ( '' === trim( $exclude_urls ) ) {
399 $exclude_urls_arr = array();
400 } else {
401 $exclude_urls_arr = explode( ',', $exclude_urls );
402 }
403
404 $exclude_urls_arr = array_filter( $exclude_urls_arr, function ( $url ) {
405 return '' !== trim( $url );
406 } );
407 }
408
409 foreach ( $exclude_urls_arr as $exclude_url ) {
410 if ( false !== strpos( $url, $exclude_url ) ) {
411 return true;
412 }
413 }
414
415 return false;
416 }
417
418 /**
419 * Check url is internal
420 * @param string $url
421 * @return boolean
422 */
423 protected function is_internal_url( $url )
424 {
425 // all relative url's are internal
426 if ( substr( $url, 0, 7 ) !== 'http://'
427 && substr( $url, 0, 8 ) !== 'https://'
428 && substr( $url, 0, 6 ) !== 'ftp://'
429 && substr( $url, 0, 2 ) !== '//' ) {
430 return true;
431 }
432
433 // is internal
434 $url_without_protocol = preg_replace('#^http(s)?://#', '', home_url( '' ));
435 $clean_home_url = preg_replace('/^www\./', '', $url_without_protocol);
436
437 if ( 0 === strpos( $url, 'http://'.$clean_home_url )
438 || 0 === strpos( $url, 'https://'.$clean_home_url )
439 || 0 === strpos( $url, 'http://www.'.$clean_home_url )
440 || 0 === strpos( $url, 'https://www.'.$clean_home_url )
441 ) {
442 return true;
443 }
444
445 // check subdomains
446 if ( $this->opt( 'subdomains_as_internal_links' ) && false !== strpos( $url, $this->get_domain() ) ) {
447 return true;
448 }
449
450 return false;
451 }
452
453 /**
454 * Get domain name
455 * @return string
456 */
457 protected function get_domain() {
458 // should be using private property, but static is more practical
459 static $domain_name = null;
460
461 if ( null === $domain_name ) {
462 preg_match(
463 '/[a-z0-9\-]{1,63}\.[a-z\.]{2,6}$/'
464 , parse_url( home_url(), PHP_URL_HOST )
465 , $domain_tld
466 );
467
468 if ( count( $domain_tld ) > 0 ) {
469 $domain_name = $domain_tld[ 0 ];
470 } else {
471 $domain_name = $_SERVER[ 'SERVER_NAME' ];
472 }
473 }
474
475 return $domain_name;
476 }
477
478 }
479
480 /*?>*/
481