WP External Links (nofollow new tab seo) - Version 1.80

Version Description

  • Added filter hook wpel_external_link_attrs to change attributes before creating the link
  • Added filter hook wpel_ignored_external_links
  • Removed phpQuery option
  • Moved ignore selectors option
Download this release

Release Info

Developer freelancephp
Plugin Icon 128x128 WP External Links (nofollow new tab seo)
Version 1.80
Comparing to
See all releases

Code changes from version 1.70 to 1.80

includes/class-admin-external-links.php CHANGED
@@ -22,6 +22,7 @@ final class Admin_External_Links {
22
  'filter_comments' => 1,
23
  'filter_widgets' => 1,
24
  'ignore' => '//twitter.com/share',
 
25
  'ignore_subdomains' => 0,
26
  ),
27
  'seo' => array(
@@ -41,8 +42,6 @@ final class Admin_External_Links {
41
  ),
42
  'extra' => array(
43
  'fix_js' => 0,
44
- 'phpquery' => 0,
45
- 'filter_excl_sel' => '.excl-ext-link',
46
  ),
47
  'screen' => array(
48
  'menu_position' => NULL,
@@ -260,20 +259,33 @@ style;
260
  </td>
261
  </tr>
262
  <tr>
263
- <th><?php $this->_e( 'Ignore links (URL) containing...' ) ?>
 
 
 
 
 
 
 
 
264
  <?php echo $this->tooltip_help( 'This plugin will completely ignore links that contain one of the given texts in the URL. Use enter to seperate each text. This check is not case sensitive.' ) ?></th>
265
  <td><label><?php echo $this->form->textarea( 'ignore' ); ?>
266
- <span class="description"><?php _e( 'Be as specific as you want, f.e.: <code>twitter.com</code> or <code>https://twitter.com</code>. Seperate each by an enter.' ) ?></span></label>
267
  </td>
268
  </tr>
 
 
 
 
 
269
  <tr>
270
- <th style="width:250px;"><?php $this->_e( 'Ignore subdomains' ) ?>
271
- <?php echo $this->tooltip_help( 'Ignore all links to the site\'s domain and subdomains. These links will be threaded as internal links.' ) ?></th>
272
- <td>
273
- <label><?php echo $this->form->checkbox( 'ignore_subdomains', 1 ); ?>
274
- <span><?php $this->_e( 'Ignore all links to the site\'s domain and subdomains' ) ?></span> <span class="description"><?php $this->_e('These links will be threaded as internal links.') ?></span></label>
275
  </td>
276
  </tr>
 
277
  </table>
278
  </fieldset>
279
 
@@ -409,21 +421,6 @@ style;
409
  <?php echo $this->tooltip_help( 'By replacing </a> with <\/a> in JavaScript code these tags will not be processed by the plugin.' ) ?>
410
  </td>
411
  </tr>
412
- <tr>
413
- <th style="width:250px;"><?php $this->_e( 'Use phpQuery library' ) ?>
414
- <?php echo $this->tooltip_help( 'Using phpQuery library for manipulating links. This option is experimental.' ) ?></th>
415
- <td><label><?php echo $this->form->checkbox( 'phpquery', 1 ); ?>
416
- <span><?php $this->_e( 'Use phpQuery for parsing document.' ) ?></span>
417
- <span class="description">(Test it first!)</span></label>
418
- </td>
419
- </tr>
420
- <tr class="filter_excl_sel" <?php echo ( $this->form->value( 'phpquery' ) ) ? '' : 'style="display:none;"'; ?>>
421
- <th><?php $this->_e( 'Do NOT apply settings on...' ) ?>
422
- <?php echo $this->tooltip_help( 'The external links of these selection will be excluded for the settings of this plugin. Define the selection by using CSS selectors.' ) ?></th>
423
- <td><label><?php echo $this->form->textarea( 'filter_excl_sel' ); ?>
424
- <span class="description"><?php _e( 'Define selection by using CSS selectors, f.e.: <code>.excl-ext-link, .entry-title, #comments-title</code> (look <a href="http://code.google.com/p/phpquery/wiki/Selectors" target="_blank">here</a> for available selectors).' ) ?></span></label>
425
- </td>
426
- </tr>
427
  </table>
428
  </fieldset>
429
  <?php
@@ -529,85 +526,22 @@ style;
529
  $meta = get_option( 'wp_external_links-meta' );
530
  if ( $meta[ 'version' ] == WP_EXTERNAL_LINKS_VERSION )
531
  return;
532
-
533
  // set new version
534
  $meta[ 'version' ] = WP_EXTERNAL_LINKS_VERSION;
535
  update_option( 'wp_external_links-meta', $meta );
536
  $this->save_options['meta'] = $meta;
537
 
538
- // check for upgrading saved options to v1.00
539
- $old_options = get_option( 'WP_External_Links_options' );
540
-
541
- if ( ! empty( $old_options ) ) {
542
- $new_options = $this->save_options;
543
-
544
- $new_options[ 'main' ][ 'target' ] = $old_options[ 'target' ];
545
- $new_options[ 'main' ][ 'filter_page' ] = $old_options[ 'filter_whole_page' ];
546
- $new_options[ 'main' ][ 'filter_posts' ] = $old_options[ 'filter_posts' ];
547
- $new_options[ 'main' ][ 'filter_comments' ] = $old_options[ 'filter_comments' ];
548
- $new_options[ 'main' ][ 'filter_widgets' ] = $old_options[ 'filter_widgets' ];
549
- $new_options[ 'seo' ][ 'external' ] = $old_options[ 'external' ];
550
- $new_options[ 'seo' ][ 'nofollow' ] = $old_options[ 'nofollow' ];
551
- $new_options[ 'seo' ][ 'use_js' ] = $old_options[ 'use_js' ];
552
- $new_options[ 'style' ][ 'class_name' ] = $old_options[ 'class_name' ];
553
- $new_options[ 'style' ][ 'icon' ] = $old_options[ 'icon' ];
554
- $new_options[ 'style' ][ 'no_icon_class' ] = $old_options[ 'no_icon_class' ];
555
- $new_options[ 'style' ][ 'no_icon_same_window' ] = $old_options[ 'no_icon_same_window' ];
556
-
557
- // save new format option values
558
- update_option( 'wp_external_links-main', $new_options[ 'main' ] );
559
- update_option( 'wp_external_links-seo', $new_options[ 'seo' ] );
560
- update_option( 'wp_external_links-style', $new_options[ 'style' ] );
561
-
562
- // delete old format option values
563
- delete_option( 'WP_External_Links_options' );
564
- }
565
-
566
- // upgrade to v1.20
567
- // $upgrade_main = get_option( 'wp_external_links-main' );
568
- //
569
- // if ( ! isset( $upgrade_main[ 'ignore' ] ) ) {
570
- // $upgrade_main[ 'ignore' ] = $this->save_options[ 'main' ][ 'ignore' ];
571
- // update_option( 'wp_external_links-main', $upgrade_main );
572
- // }
573
-
574
- // upgrade to v1.30
575
- if ( WP_EXTERNAL_LINKS_VERSION == '1.30' ) {
576
- $new_options = $this->save_options;
577
- $general = get_option( 'wp_external_links-general' );
578
- $style = get_option( 'wp_external_links-style' );
579
-
580
- if ( isset( $general[ 'target' ] ) ) $new_options[ 'main' ][ 'target' ] = $general[ 'target' ];
581
- $new_options[ 'main' ][ 'filter_page' ] = ( isset( $general[ 'filter_page' ] ) ) ? $general[ 'filter_page' ] : 0;
582
- $new_options[ 'main' ][ 'filter_posts' ] = ( isset( $general[ 'filter_posts' ] ) ) ? $general[ 'filter_posts' ] : 0;
583
- $new_options[ 'main' ][ 'filter_comments' ] = ( isset( $general[ 'filter_comments' ] ) ) ? $general[ 'filter_comments' ] : 0;
584
- $new_options[ 'main' ][ 'filter_widgets' ] = ( isset( $general[ 'filter_widgets' ] ) ) ? $general[ 'filter_widgets' ] : 0;
585
- if ( isset( $general[ 'ignore' ] ) ) $new_options[ 'main' ][ 'ignore' ] = $general[ 'ignore' ];
586
-
587
- $new_options[ 'seo' ][ 'external' ] = ( isset( $general[ 'external' ] ) ) ? $general[ 'external' ] : 0;
588
- $new_options[ 'seo' ][ 'nofollow' ] = ( isset( $general[ 'nofollow' ] ) ) ? $general[ 'nofollow' ] : 0;
589
- $new_options[ 'seo' ][ 'use_js' ] = ( isset( $general[ 'use_js' ] ) ) ? $general[ 'use_js' ] : 0;
590
- if ( isset( $general[ 'title' ] ) ) $new_options[ 'seo' ][ 'title' ] = $general[ 'title' ];
591
-
592
- if ( isset( $general[ 'class_name' ] ) ) $new_options[ 'style' ][ 'class_name' ] = $general[ 'class_name' ];
593
-
594
- if ( isset( $style[ 'icon' ] ) ) $new_options[ 'style' ][ 'icon' ] = $style[ 'icon' ];
595
- if ( isset( $style[ 'no_icon_class' ] ) ) $new_options[ 'style' ][ 'no_icon_class' ] = $style[ 'no_icon_class' ];
596
- $new_options[ 'style' ][ 'no_icon_same_window' ] = ( isset( $style[ 'no_icon_same_window' ] ) ) ? $style[ 'no_icon_same_window' ] : 0;
597
-
598
- $new_options[ 'extra' ][ 'fix_js' ] = ( isset( $general[ 'fix_js' ] ) ) ? $general[ 'fix_js' ] : 0;
599
- $new_options[ 'extra' ][ 'phpquery' ] = ( isset( $general[ 'phpquery' ] ) ) ? $general[ 'phpquery' ] : 0;
600
- if ( isset( $general[ 'filter_excl_sel' ] ) ) $new_options[ 'extra' ][ 'filter_excl_sel' ] = $general[ 'filter_excl_sel' ];
601
-
602
- // save new format option values
603
- update_option( 'wp_external_links-main', $new_options[ 'main' ] );
604
- update_option( 'wp_external_links-seo', $new_options[ 'seo' ] );
605
- update_option( 'wp_external_links-style', $new_options[ 'style' ] );
606
- update_option( 'wp_external_links-extra', $new_options[ 'extra' ] );
607
-
608
- // delete old format
609
- delete_option( 'wp_external_links-general' );
610
- }
611
  }
612
 
613
  /**
22
  'filter_comments' => 1,
23
  'filter_widgets' => 1,
24
  'ignore' => '//twitter.com/share',
25
+ 'ignore_selectors' => '',
26
  'ignore_subdomains' => 0,
27
  ),
28
  'seo' => array(
42
  ),
43
  'extra' => array(
44
  'fix_js' => 0,
 
 
45
  ),
46
  'screen' => array(
47
  'menu_position' => NULL,
259
  </td>
260
  </tr>
261
  <tr>
262
+ <th style="width:250px;"><?php $this->_e( 'Make subdomains internal' ) ?>
263
+ <?php echo $this->tooltip_help( 'Threat all links to the site\'s domain and subdomains as internal links.' ) ?></th>
264
+ <td>
265
+ <label><?php echo $this->form->checkbox( 'ignore_subdomains', 1 ); ?>
266
+ <span><?php $this->_e( 'Threat all links to the site\'s domain and subdomains as internal links' ) ?></span></label>
267
+ </td>
268
+ </tr>
269
+ <tr>
270
+ <th><?php $this->_e( 'Ignore links with URL\'s containing...' ) ?>
271
  <?php echo $this->tooltip_help( 'This plugin will completely ignore links that contain one of the given texts in the URL. Use enter to seperate each text. This check is not case sensitive.' ) ?></th>
272
  <td><label><?php echo $this->form->textarea( 'ignore' ); ?>
273
+ <span class="description"><?php _e( 'Seperate each by an enter. No wildcards nescessary, f.e. <code>wordpress.org</code> will be threaded as <code>*wordpress.org*</code>' ) ?></span></label>
274
  </td>
275
  </tr>
276
+ <?php
277
+ // only supported for users who were using phpquery
278
+ $extra = get_option( 'wp_external_links-extra' );
279
+ if (isset($extra['phpquery']) && $extra['phpquery']):
280
+ ?>
281
  <tr>
282
+ <th><?php $this->_e( 'Ignore links by selectors...' ) ?>
283
+ <?php echo $this->tooltip_help( 'The external links of these selection will be excluded for the settings of this plugin. Define the selection by using CSS selectors.' ) ?></th>
284
+ <td><label><?php echo $this->form->textarea( 'ignore_selectors' ); ?>
285
+ <span class="description"><?php _e( 'Define selection by using CSS selectors, f.e.: <code>.excl-ext-link, .entry-title, #comments-title</code> (look <a href="http://code.google.com/p/phpquery/wiki/Selectors" target="_blank">here</a> for available selectors).' ) ?></span></label>
 
286
  </td>
287
  </tr>
288
+ <?php endif; ?>
289
  </table>
290
  </fieldset>
291
 
421
  <?php echo $this->tooltip_help( 'By replacing </a> with <\/a> in JavaScript code these tags will not be processed by the plugin.' ) ?>
422
  </td>
423
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  </table>
425
  </fieldset>
426
  <?php
526
  $meta = get_option( 'wp_external_links-meta' );
527
  if ( $meta[ 'version' ] == WP_EXTERNAL_LINKS_VERSION )
528
  return;
529
+
530
  // set new version
531
  $meta[ 'version' ] = WP_EXTERNAL_LINKS_VERSION;
532
  update_option( 'wp_external_links-meta', $meta );
533
  $this->save_options['meta'] = $meta;
534
 
535
+ // changed options in v1.80
536
+ $extra = get_option( 'wp_external_links-extra' );
537
+
538
+ if (isset($extra['phpquery']) && $extra['phpquery']) {
539
+ $main = get_option('wp_external_links-main');
540
+ $main['ignore_selectors'] = $extra['filter_excl_sel'];
541
+
542
+ update_option( 'wp_external_links-main', $main );
543
+ $this->save_options['main'] = $main;
544
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  }
546
 
547
  /**
includes/class-wp-external-links.php CHANGED
@@ -175,16 +175,11 @@ final class WP_External_Links {
175
  $content = preg_replace_callback( '/<script([^>]*)>(.*?)<\/script[^>]*>/is', array( $this, 'call_fix_js' ), $content );
176
  }
177
 
178
- if ( $this->get_opt( 'phpquery' ) ) {
179
- // Include phpQuery
180
- if ( ! class_exists( 'phpQuery' ) ) {
181
- require_once( 'phpQuery.php' );
182
- }
183
 
184
- return $this->filter_phpquery( $content );
185
- } else {
186
- return $this->filter( $content );
187
- }
188
  }
189
 
190
  /**
@@ -227,7 +222,7 @@ final class WP_External_Links {
227
  * @param string $href
228
  * @return boolean
229
  */
230
- private function is_ignored( $href ) {
231
  // check if this links should be ignored
232
  for ( $x = 0, $count = count($this->ignored); $x < $count; $x++ ) {
233
  if ( strrpos( $href, $this->ignored[ $x ] ) !== FALSE )
@@ -237,6 +232,47 @@ final class WP_External_Links {
237
  return FALSE;
238
  }
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  /**
241
  * Filter content
242
  * @param string $content
@@ -348,12 +384,12 @@ final class WP_External_Links {
348
  public function call_parse_link( $matches ) {
349
  $link = $matches[ 0 ];
350
  $label = $matches[ 2 ];
351
- $created_link = $link;
352
 
353
  // parse attributes
354
- $attrs = $matches[ 1 ];
355
- $attrs = stripslashes( $attrs );
356
- $attrs = $this->parse_attrs( $attrs );
 
357
 
358
  $rel = ( isset( $attrs[ 'rel' ] ) ) ? strtolower( $attrs[ 'rel' ] ) : '';
359
 
@@ -366,26 +402,27 @@ final class WP_External_Links {
366
  $href = '';
367
  }
368
 
369
- // checks
 
370
  $is_external = $this->is_external( $href );
371
- $is_ignored = $this->is_ignored( $href );
372
  $has_rel_external = (strpos( $rel, 'external' ) !== FALSE);
373
 
374
- // is an internal link?
375
- // rel=external will be threaded as external link
376
  if ( ! $is_external && ! $has_rel_external) {
377
- return apply_filters('wpel_internal_link', $created_link, $label, $attrs);
378
  }
379
 
380
  // is an ignored link?
381
- // rel=external will be threaded as external link
382
- if ( $is_ignored && ! $has_rel_external ) {
383
- return apply_filters('wpel_external_link', $created_link, $link, $label, $attrs, TRUE);
 
 
 
384
  }
385
 
386
  // set rel="external" (when not already set)
387
  if ( $this->get_opt( 'external' ) )
388
- $this->add_attr_value( $attrs, 'rel', 'external' );
389
 
390
  // set rel="nofollow"
391
  if ( $this->get_opt( 'nofollow' ) ) {
@@ -398,7 +435,7 @@ final class WP_External_Links {
398
  //$attrs[ 'rel' ] = ;
399
  }
400
 
401
- $this->add_attr_value( $attrs, 'rel', 'nofollow' );
402
  }
403
  }
404
 
@@ -410,7 +447,7 @@ final class WP_External_Links {
410
  // set user-defined class
411
  $class = $this->get_opt( 'class_name' );
412
  if ( $class )
413
- $this->add_attr_value( $attrs, 'class', $class );
414
 
415
  // set icon class, unless no-icon class isset or another icon class ('ext-icon-...') is found or content contains image
416
  if ( $this->get_opt( 'icon' ) > 0
@@ -418,7 +455,7 @@ final class WP_External_Links {
418
  AND strpos( $attrs[ 'class' ], 'ext-icon-' ) === FALSE
419
  AND !( $this->get_opt( 'image_no_icon' ) AND (bool) preg_match( '/<img([^>]*)>/is', $label )) ){
420
  $icon_class = 'ext-icon-'. $this->get_opt( 'icon', 'style' );
421
- $this->add_attr_value( $attrs, 'class', $icon_class );
422
  }
423
 
424
  // set target
@@ -441,7 +478,25 @@ final class WP_External_Links {
441
  }
442
  }
443
 
 
 
 
444
  // create element code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  $created_link = '<a';
446
 
447
  foreach ( $attrs AS $key => $value ) {
@@ -449,22 +504,18 @@ final class WP_External_Links {
449
  }
450
 
451
  $created_link .= '>'. $label .'</a>';
452
-
453
- // filter
454
- $created_link = apply_filters('wpel_external_link', $created_link, $link, $label, $attrs, FALSE);
455
-
456
- return $created_link;
457
- }
458
 
459
  /**
460
  * Add value to attribute
461
- * @param array $attrs
462
- * @param string $attr
463
  * @param string $value
464
- * @param string $default Optional, default NULL which means tje attribute will be removed when (new) value is empty
465
  * @return New value
466
  */
467
- public function add_attr_value( &$attrs, $attr_name, $value, $default = NULL ) {
468
  if ( key_exists( $attr_name, $attrs ) )
469
  $old_value = $attrs[ $attr_name ];
470
 
@@ -490,153 +541,6 @@ final class WP_External_Links {
490
  return $value;
491
  }
492
 
493
- /**
494
- * Experimental phpQuery...
495
- */
496
-
497
- /**
498
- * Filter content
499
- * @param string $content
500
- * @return string
501
- */
502
- private function filter_phpquery( $content ) {
503
- // Workaround: remove <head>-attributes before using phpQuery
504
- $regexp_head = '/<head(>|\s(.*?)>)>/is';
505
- $clean_head = '<head>';
506
-
507
- // set simple <head> without attributes
508
- preg_match( $regexp_head, $content, $matches );
509
-
510
- if( count( $matches ) > 0 ) {
511
- $original_head = $matches[ 0 ];
512
- $content = str_replace( $original_head, $clean_head, $content );
513
- }
514
-
515
- //phpQuery::$debug = true;
516
-
517
- // set document
518
- $doc = phpQuery::newDocument( $content );
519
-
520
- $excl_sel = $this->get_opt( 'filter_excl_sel' );
521
-
522
- // set excludes
523
- if ( ! empty( $excl_sel ) ) {
524
- $excludes = $doc->find( $excl_sel );
525
- $excludes->filter( 'a' )->attr( 'excluded', true );
526
- $excludes->find( 'a' )->attr( 'excluded', true );
527
- }
528
-
529
- // get <a>-tags
530
- $links = $doc->find( 'a' );
531
-
532
- // set links
533
- $count = count( $links );
534
-
535
- for( $x = 0; $x < $count; $x++ ) {
536
- $a = $links->eq( $x );
537
-
538
- if ( ! $a->attr( 'excluded' ) )
539
- $this->set_link_phpquery( $links->eq( $x ) );
540
- }
541
-
542
- // remove excluded
543
- if ( ! empty( $excl_sel ) ) {
544
- $excludes = $doc->find( $excl_sel );
545
- $excludes->filter( 'a' )->removeAttr( 'excluded' );
546
- $excludes->find( 'a' )->removeAttr( 'excluded' );
547
- }
548
-
549
- // remove style when no icon classes are found
550
- if ( strpos( $doc, 'ext-icon-' ) === FALSE ) {
551
- // remove icon css
552
- $css = $doc->find( 'link#wp-external-links-css' )->eq(0);
553
- $css->remove();
554
- }
555
-
556
- // get document content
557
- $content = (string) $doc;
558
-
559
- if( isset( $original_head ) ) {
560
- // recover original <head> with attributes
561
- $content = str_replace( $clean_head, $original_head, $content );
562
- }
563
-
564
- return $content;
565
- }
566
-
567
- /**
568
- * Set link...
569
- * @param Node $a
570
- * @return Node
571
- */
572
- public function set_link_phpquery( $a ) {
573
- $href = strtolower( $a->attr( 'href' ) . '' );
574
- $rel = strtolower( $a->attr( 'rel' ) . '' );
575
-
576
- // check if it is an external link and not excluded
577
- if ( ! $this->is_external( $href, $rel ) || $this->is_ignored( $href ) )
578
- return $a;
579
-
580
- // add "external" to rel-attribute
581
- if ( $this->get_opt( 'external' ) ){
582
- $this->add_attr_value_phpquery( $a, 'rel', 'external' );
583
- }
584
-
585
- // add "nofollow" to rel-attribute, when doesn't have "follow"
586
- if ( $this->get_opt( 'nofollow' ) AND strpos( $rel, 'follow' ) === FALSE ){
587
- $this->add_attr_value_phpquery( $a, 'rel', 'nofollow' );
588
- }
589
-
590
- // set title
591
- $title = str_replace( '%title%', $a->attr( 'title' ), $this->get_opt( 'title' ) );
592
- $a->attr( 'title', $title );
593
-
594
- // add icon class, unless no-icon class isset or another icon class ('ext-icon-...') is found
595
- if ( $this->get_opt( 'icon' ) > 0 AND ( ! $this->get_opt( 'no_icon_class' ) OR strpos( $a->attr( 'class' ), $this->get_opt( 'no_icon_class' ) ) === FALSE ) AND strpos( $a->attr( 'class' ), 'ext-icon-' ) === FALSE ){
596
- $icon_class = 'ext-icon-'. $this->get_opt( 'icon' );
597
- $a->addClass( $icon_class );
598
- }
599
-
600
- // add user-defined class
601
- if ( $this->get_opt( 'class_name' ) ){
602
- $a->addClass( $this->get_opt( 'class_name' ) );
603
- }
604
-
605
- // set target
606
- if ( $this->get_opt( 'target' ) != '_none' AND ! $this->get_opt( 'use_js' ) AND ( ! $this->get_opt( 'no_icon_same_window' ) OR ! $this->get_opt( 'no_icon_class' ) OR strpos( $a->attr( 'class' ), $this->get_opt( 'no_icon_class' ) ) === FALSE ) )
607
- $a->attr( 'target', $this->get_opt( 'target' ) );
608
-
609
- return $a;
610
- }
611
-
612
- /**
613
- * Add value to attribute
614
- * @param Node $node
615
- * @param string $attr
616
- * @param string $value
617
- * @return New value
618
- */
619
- private function add_attr_value_phpquery( $node, $attr, $value ) {
620
- $old_value = $node->attr( $attr );
621
-
622
- if ( empty( $old_value ) )
623
- $old_value = '';
624
-
625
- $split = explode( ' ', strtolower( $old_value ) );
626
-
627
- if ( in_array( $value, $split ) ) {
628
- $value = $old_value;
629
- } else {
630
- $value = ( empty( $old_value ) )
631
- ? $value
632
- : $old_value .' '. $value;
633
- }
634
-
635
- $node->attr( $attr, $value );
636
-
637
- return $value;
638
- }
639
-
640
  } // End WP_External_Links Class
641
 
642
  endif;
175
  $content = preg_replace_callback( '/<script([^>]*)>(.*?)<\/script[^>]*>/is', array( $this, 'call_fix_js' ), $content );
176
  }
177
 
178
+ if ( $this->get_opt( 'filter_page' ) && $this->get_opt( 'ignore_selectors' ) ) {
179
+ $content = $this->set_ignored_by_selectors( $content );
180
+ }
 
 
181
 
182
+ return $this->filter( $content );
 
 
 
183
  }
184
 
185
  /**
222
  * @param string $href
223
  * @return boolean
224
  */
225
+ private function is_ignored_by_url( $href ) {
226
  // check if this links should be ignored
227
  for ( $x = 0, $count = count($this->ignored); $x < $count; $x++ ) {
228
  if ( strrpos( $href, $this->ignored[ $x ] ) !== FALSE )
232
  return FALSE;
233
  }
234
 
235
+ /**
236
+ * Set ignored external links selections
237
+ * @param string $content
238
+ * @return string
239
+ */
240
+ private function set_ignored_by_selectors( $content ) {
241
+ // Include phpQuery
242
+ if ( ! class_exists( 'phpQuery' ) ) {
243
+ require_once( 'phpQuery.php' );
244
+ }
245
+
246
+ try {
247
+ // set document
248
+ //phpQuery::$debug = true;
249
+ $doc = phpQuery::newDocument( $content );
250
+
251
+ $ignore_selectors = $this->get_opt( 'ignore_selectors' );
252
+
253
+ // set ignored by selectors
254
+ if ( ! empty( $ignore_selectors ) ) {
255
+ $excludes = $doc->find( $ignore_selectors );
256
+
257
+ // links containing selector
258
+ $excludes->filter( 'a' )->attr( 'data-wpel-ignored', 'true' );
259
+
260
+ // links as descendant of element containing selector
261
+ $excludes->find( 'a' )->attr( 'data-wpel-ignored', 'true' );
262
+ }
263
+
264
+ $doc = (string) $doc;
265
+ } catch (Exception $e) {
266
+ $doc = '';
267
+ }
268
+
269
+ if (empty($doc)) {
270
+ return $content;
271
+ }
272
+
273
+ return $doc;
274
+ }
275
+
276
  /**
277
  * Filter content
278
  * @param string $content
384
  public function call_parse_link( $matches ) {
385
  $link = $matches[ 0 ];
386
  $label = $matches[ 2 ];
 
387
 
388
  // parse attributes
389
+ $original_attrs = $matches[ 1 ];
390
+ $original_attrs = stripslashes( $original_attrs );
391
+ $original_attrs = $this->parse_attrs( $original_attrs );
392
+ $attrs = $original_attrs;
393
 
394
  $rel = ( isset( $attrs[ 'rel' ] ) ) ? strtolower( $attrs[ 'rel' ] ) : '';
395
 
402
  $href = '';
403
  }
404
 
405
+ // is an internal link?
406
+ // rel=external will be threaded as external link
407
  $is_external = $this->is_external( $href );
 
408
  $has_rel_external = (strpos( $rel, 'external' ) !== FALSE);
409
 
 
 
410
  if ( ! $is_external && ! $has_rel_external) {
411
+ return apply_filters('wpel_internal_link', $link, $label, $attrs);
412
  }
413
 
414
  // is an ignored link?
415
+ $is_ignored = $this->is_ignored_by_url( $href ) || isset($attrs['data-wpel-ignored']);
416
+
417
+ if ( $is_ignored ) {
418
+ self::add_attr_value( $attrs, 'data-wpel-ignored', 'true' );
419
+ $created_link = self::create_link($label, $attrs);
420
+ return apply_filters('wpel_ignored_external_link', $created_link, $label, $attrs);
421
  }
422
 
423
  // set rel="external" (when not already set)
424
  if ( $this->get_opt( 'external' ) )
425
+ self::add_attr_value( $attrs, 'rel', 'external' );
426
 
427
  // set rel="nofollow"
428
  if ( $this->get_opt( 'nofollow' ) ) {
435
  //$attrs[ 'rel' ] = ;
436
  }
437
 
438
+ self::add_attr_value( $attrs, 'rel', 'nofollow' );
439
  }
440
  }
441
 
447
  // set user-defined class
448
  $class = $this->get_opt( 'class_name' );
449
  if ( $class )
450
+ self::add_attr_value( $attrs, 'class', $class );
451
 
452
  // set icon class, unless no-icon class isset or another icon class ('ext-icon-...') is found or content contains image
453
  if ( $this->get_opt( 'icon' ) > 0
455
  AND strpos( $attrs[ 'class' ], 'ext-icon-' ) === FALSE
456
  AND !( $this->get_opt( 'image_no_icon' ) AND (bool) preg_match( '/<img([^>]*)>/is', $label )) ){
457
  $icon_class = 'ext-icon-'. $this->get_opt( 'icon', 'style' );
458
+ self::add_attr_value( $attrs, 'class', $icon_class );
459
  }
460
 
461
  // set target
478
  }
479
  }
480
 
481
+ // filter hook for changing attributes
482
+ $attrs = apply_filters('wpel_external_link_attrs', $attrs, $original_attrs, $label);
483
+
484
  // create element code
485
+ $created_link = self::create_link($label, $attrs);
486
+
487
+ // filter
488
+ $created_link = apply_filters('wpel_external_link', $created_link, $link, $label, $attrs, FALSE /* only used for backwards compatibility */);
489
+
490
+ return $created_link;
491
+ }
492
+
493
+ /**
494
+ * Create a HTML link <a>
495
+ * @param string $label
496
+ * @param array $attrs
497
+ * @return string
498
+ */
499
+ public static function create_link($label, $attrs) {
500
  $created_link = '<a';
501
 
502
  foreach ( $attrs AS $key => $value ) {
504
  }
505
 
506
  $created_link .= '>'. $label .'</a>';
507
+ return $created_link;
508
+ }
 
 
 
 
509
 
510
  /**
511
  * Add value to attribute
512
+ * @param array &$attrs
513
+ * @param string $attr_name
514
  * @param string $value
515
+ * @param string $default Optional, default NULL which means the attribute will be removed when (new) value is empty
516
  * @return New value
517
  */
518
+ public static function add_attr_value( &$attrs, $attr_name, $value, $default = NULL ) {
519
  if ( key_exists( $attr_name, $attrs ) )
520
  $old_value = $attrs[ $attr_name ];
521
 
541
  return $value;
542
  }
543
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
  } // End WP_External_Links Class
545
 
546
  endif;
js/admin-wp-external-links.js CHANGED
@@ -150,17 +150,6 @@ jQuery(function ($) {
150
  })
151
  .change();
152
 
153
- // option filter_excl_sel
154
- $('input#phpquery')
155
- .change(function () {
156
- if ($(this).attr('checked')) {
157
- $('.filter_excl_sel').fadeIn();
158
- } else {
159
- $('.filter_excl_sel').fadeOut();
160
- }
161
- })
162
- .change();
163
-
164
  // refresh page when updated menu position
165
  $('#menu_position').parents('form.ajax-form').on('ajax_saved_options', function () {
166
  var s = $(this).val() || '';
150
  })
151
  .change();
152
 
 
 
 
 
 
 
 
 
 
 
 
153
  // refresh page when updated menu position
154
  $('#menu_position').parents('form.ajax-form').on('ajax_saved_options', function () {
155
  var s = $(this).val() || '';
js/src/admin-wp-external-links.js CHANGED
@@ -150,17 +150,6 @@ jQuery(function ($) {
150
  })
151
  .change();
152
 
153
- // option filter_excl_sel
154
- $('input#phpquery')
155
- .change(function () {
156
- if ($(this).attr('checked')) {
157
- $('.filter_excl_sel').fadeIn();
158
- } else {
159
- $('.filter_excl_sel').fadeOut();
160
- }
161
- })
162
- .change();
163
-
164
  // refresh page when updated menu position
165
  $('#menu_position').parents('form.ajax-form').on('ajax_saved_options', function () {
166
  var s = $(this).val() || '';
@@ -185,3 +174,59 @@ jQuery(function ($) {
185
  });
186
 
187
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  })
151
  .change();
152
 
 
 
 
 
 
 
 
 
 
 
 
153
  // refresh page when updated menu position
154
  $('#menu_position').parents('form.ajax-form').on('ajax_saved_options', function () {
155
  var s = $(this).val() || '';
174
  });
175
 
176
  });
177
+
178
+ /* WP Options Form */
179
+ /*global jQuery, ajaxurl*/
180
+ jQuery(function ($) {
181
+ 'use strict';
182
+
183
+ // save function
184
+ var saveAjaxForm = function (target) {
185
+ var $this = $(target),
186
+ $form = $this.parents('form'),
187
+ // get ajax post values
188
+ vals = $form.serializeArray();
189
+
190
+ // disable button
191
+ $this.attr('disabled', true);
192
+
193
+ // show ajax loader
194
+ $form.find('.ajax-feedback').css('visibility', 'visible');
195
+
196
+ // save option values
197
+ $.post(ajaxurl, vals, function (result) {
198
+ var $msg = $('<strong>').insertBefore($this);
199
+
200
+ if (result === '1') {
201
+ $msg.html('Saved');
202
+ } else {
203
+ // save options, non-ajax fallback
204
+ $form.find('[name="action"]').val('update');
205
+ // normal submit
206
+ $form.submit();
207
+ }
208
+
209
+ $msg.css({ margin: '0 5px' })
210
+ .delay(1000)
211
+ .fadeOut(function () {
212
+ $(this).remove();
213
+ });
214
+
215
+ // enable button
216
+ $this.attr('disabled', false);
217
+
218
+ // hide ajax loader
219
+ $form.find('.ajax-feedback').css('visibility', 'hidden');
220
+
221
+ // trigger ajax_saved_options
222
+ $form.trigger('ajax_saved_options', [result]);
223
+ });
224
+ };
225
+
226
+ // add ajax post
227
+ $('form.ajax-form input[type="submit"]').click(function (e) {
228
+ saveAjaxForm(this);
229
+ e.preventDefault();
230
+ });
231
+
232
+ });
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: freelancephp
3
  Tags: links, external, icon, target, _blank, _new, _none, rel, nofollow, new window, new tab, javascript, xhtml, seo
4
  Requires at least: 3.6.0
5
- Tested up to: 4.2.2
6
- Stable tag: 1.70
7
 
8
  Open external links in a new window or tab, adding "nofollow", set link icon, styling, SEO friendly options and more. Easy install and go.
9
 
@@ -49,7 +49,8 @@ You could add `rel="external"` to those internal links that should be treated as
49
 
50
  = Why are links to my own domain treated as external links? =
51
 
52
- Only links pointing to your WordPress site (`wp_url`) are internal links. All other links will be treated as external links.
 
53
 
54
  = How to treat links to subdomains as internal links? =
55
 
@@ -156,34 +157,57 @@ The plugin also has a hook when ready, f.e. to add extra filters:
156
  add_action('wpel_ready', 'extra_filters');`
157
 
158
  = Filter hook 1: wpel_external_link =
159
- The wpel_external_link filter gives you the possibility to manipulate output of all external links, like:
160
- `function special_external_link($created_link, $original_link, $label, $attrs, $is_ignored_link) {
 
 
161
  // skip links that contain the class "not-external"
162
  if (isset($attrs['class']) && strpos($attrs['class'], 'not-external') !== false) {
163
  return $original_link;
164
  }
165
 
166
  return '<b>'. $created_link .'</b>';
167
- }
168
-
169
- add_filter('wpel_external_link', 'special_external_link', 10, 5);`
170
 
171
  Now all external links will be processed and wrapped around a `<b>`-tag. And links containing the class "not-external" will not be processed by the plugin at all (and stay the way they are).
172
 
173
- See [FAQ](https://wordpress.org/plugins/wp-external-links/faq/) for more possibilities of using this filter.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- = Filter hook 2: wpel_internal_link =
176
- With the internal filter you can manipulate the output of all internal links on your site. F.e.:
177
- `
178
  function special_internal_link($link, $label, $attrs) {
179
  return '<b>'. $link .'</b>';
180
- }
181
-
182
- add_filter('wpel_internal_link', 'special_internal_link', 10, 3);`
183
 
184
  In this case all internal links will be made bold.
185
 
186
- See [FAQ](https://wordpress.org/plugins/wp-external-links/faq/) for more possibilities of using this filter.
 
187
 
188
 
189
  = Credits =
@@ -193,6 +217,12 @@ See [FAQ](https://wordpress.org/plugins/wp-external-links/faq/) for more possibi
193
 
194
  == Changelog ==
195
 
 
 
 
 
 
 
196
  = 1.70 =
197
  * Added option to ignore all subdomains
198
 
2
  Contributors: freelancephp
3
  Tags: links, external, icon, target, _blank, _new, _none, rel, nofollow, new window, new tab, javascript, xhtml, seo
4
  Requires at least: 3.6.0
5
+ Tested up to: 4.2.3
6
+ Stable tag: 1.80
7
 
8
  Open external links in a new window or tab, adding "nofollow", set link icon, styling, SEO friendly options and more. Easy install and go.
9
 
49
 
50
  = Why are links to my own domain treated as external links? =
51
 
52
+ Only links pointing to your WordPress site (`wp_url`) are by default threaded as internal links.
53
+ There is an option to mark all links to your domain (and subdomains) as internal links.
54
 
55
  = How to treat links to subdomains as internal links? =
56
 
157
  add_action('wpel_ready', 'extra_filters');`
158
 
159
  = Filter hook 1: wpel_external_link =
160
+ The `wpel_external_link` filter gives you the possibility to manipulate output of all external links, like:
161
+ `add_filter('wpel_external_link', 'wpel_special_external_link', 10, 5);
162
+
163
+ function wpel_special_external_link($created_link, $original_link, $label, $attrs, $is_ignored_link) {
164
  // skip links that contain the class "not-external"
165
  if (isset($attrs['class']) && strpos($attrs['class'], 'not-external') !== false) {
166
  return $original_link;
167
  }
168
 
169
  return '<b>'. $created_link .'</b>';
170
+ }`
 
 
171
 
172
  Now all external links will be processed and wrapped around a `<b>`-tag. And links containing the class "not-external" will not be processed by the plugin at all (and stay the way they are).
173
 
174
+ = Filter hook 2: wpel_external_link_attrs =
175
+
176
+ The `wpel_external_link_attrs` filter can be used to manipulate attributes of external links.
177
+ `add_filter('wpel_external_link_attrs', 'wpel_custom_title', 10, 3);
178
+
179
+ function wpel_custom_title($attrs, $original_attrs, $label) {
180
+ if (empty($attrs['title']) && isset($attrs['href'])) {
181
+ $attrs['title'] = $attrs['href'];
182
+ }
183
+
184
+ return $attrs;
185
+ }`
186
+
187
+ In this example when an external links has an empty title, the title will contain the url.
188
+
189
+ = Filter hook 3: wpel_ignored_external_link =
190
+ With the `wpel_ignored_external_link` filter you can manipulate the output of the ignored external links.
191
+ `add_filter('wpel_ignored_external_link', 'wpel_custom_ignored_link', 10, 3);
192
+
193
+ function wpel_custom_ignored_link($link, $label, $attrs) {
194
+ return '<del>'. $link .'</del>';
195
+ }`
196
+
197
+ In this case all ignored links will be marked as deleted (strikethrough).
198
+
199
+ = Filter hook 4: wpel_internal_link =
200
+ With the `wpel_internal_link` filter you can manipulate the output of all internal links on your site. F.e.:
201
+ `add_filter('wpel_internal_link', 'special_internal_link', 10, 3);
202
 
 
 
 
203
  function special_internal_link($link, $label, $attrs) {
204
  return '<b>'. $link .'</b>';
205
+ }`
 
 
206
 
207
  In this case all internal links will be made bold.
208
 
209
+
210
+ See [FAQ](https://wordpress.org/plugins/wp-external-links/faq/) for more possibilities of using these filters.
211
 
212
 
213
  = Credits =
217
 
218
  == Changelog ==
219
 
220
+ = 1.80 =
221
+ * Added filter hook wpel_external_link_attrs to change attributes before creating the link
222
+ * Added filter hook wpel_ignored_external_links
223
+ * Removed phpQuery option
224
+ * Moved ignore selectors option
225
+
226
  = 1.70 =
227
  * Added option to ignore all subdomains
228
 
wp-external-links.php CHANGED
@@ -4,14 +4,14 @@ Plugin Name: WP External Links
4
  Plugin URI: http://www.freelancephp.net/wp-external-links-plugin
5
  Description: Open external links in a new window/tab, add "external" / "nofollow" to rel-attribute, set icon, XHTML strict, SEO friendly...
6
  Author: Victor Villaverde Laan
7
- Version: 1.70
8
  Author URI: http://www.freelancephp.net
9
  License: Dual licensed under the MIT and GPL licenses
10
  */
11
 
12
  // constants
13
  if (!defined('WP_EXTERNAL_LINKS_FILE')) { define('WP_EXTERNAL_LINKS_FILE', __FILE__); }
14
- if (!defined('WP_EXTERNAL_LINKS_VERSION')) { define('WP_EXTERNAL_LINKS_VERSION', '1.70'); }
15
  if (!defined('WP_EXTERNAL_LINKS_KEY')) { define('WP_EXTERNAL_LINKS_KEY', 'wp_external_links'); }
16
  if (!defined('WP_EXTERNAL_LINKS_DOMAIN')) { define('WP_EXTERNAL_LINKS_DOMAIN', 'wp-external-links'); }
17
  if (!defined('WP_EXTERNAL_LINKS_OPTIONS_NAME')) { define('WP_EXTERNAL_LINKS_OPTIONS_NAME', 'WP_External_Links_options'); }
4
  Plugin URI: http://www.freelancephp.net/wp-external-links-plugin
5
  Description: Open external links in a new window/tab, add "external" / "nofollow" to rel-attribute, set icon, XHTML strict, SEO friendly...
6
  Author: Victor Villaverde Laan
7
+ Version: 1.80
8
  Author URI: http://www.freelancephp.net
9
  License: Dual licensed under the MIT and GPL licenses
10
  */
11
 
12
  // constants
13
  if (!defined('WP_EXTERNAL_LINKS_FILE')) { define('WP_EXTERNAL_LINKS_FILE', __FILE__); }
14
+ if (!defined('WP_EXTERNAL_LINKS_VERSION')) { define('WP_EXTERNAL_LINKS_VERSION', '1.80'); }
15
  if (!defined('WP_EXTERNAL_LINKS_KEY')) { define('WP_EXTERNAL_LINKS_KEY', 'wp_external_links'); }
16
  if (!defined('WP_EXTERNAL_LINKS_DOMAIN')) { define('WP_EXTERNAL_LINKS_DOMAIN', 'wp-external-links'); }
17
  if (!defined('WP_EXTERNAL_LINKS_OPTIONS_NAME')) { define('WP_EXTERNAL_LINKS_OPTIONS_NAME', 'WP_External_Links_options'); }