WP Meta SEO - Version 4.0.7

Version Description

  • Add : Link editor & Image editor compatible with Gutenberg blocks
    • Fix : The sitemap generated ignore anchor links
Download this release

Release Info

Developer JoomUnited
Plugin Icon 128x128 WP Meta SEO
Version 4.0.7
Comparing to
See all releases

Code changes from version 4.0.6 to 4.0.7

assets/css/style.css CHANGED
@@ -360,4 +360,18 @@ span.hz-loading {
360
  .wrap_sendemail {
361
  width: 100%;
362
  float: left;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  }
360
  .wrap_sendemail {
361
  width: 100%;
362
  float: left;
363
+ }
364
+
365
+ .wpms-material-icons-gutenberg {
366
+ color: #ff8726;
367
+ opacity: 1;
368
+ margin: 0 5px;
369
+ font-size: 26px;
370
+ cursor: pointer;
371
+ height: 45px;
372
+ line-height: 45px;
373
+ }
374
+
375
+ .wpms-blocks-active {
376
+ background-color: #EEEEEE !important;
377
  }
assets/js/metaseo_admin.js CHANGED
@@ -1332,4 +1332,7 @@ jQuery(document).ready(function ($) {
1332
  $('a.show-popup').bind('click', function () {
1333
  $(this).showPopup($(this));
1334
  });
 
 
 
1335
  });
1332
  $('a.show-popup').bind('click', function () {
1333
  $(this).showPopup($(this));
1334
  });
1335
+
1336
+
1337
+ $(".wpms-blocks-active").attr('disabled','disabled');
1338
  });
assets/js/wp-metaseo-metabox.js CHANGED
@@ -443,4 +443,23 @@ jQuery(document).ready(function ($) {
443
  }
444
 
445
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
  });
443
  }
444
 
445
  });
446
+ });
447
+
448
+ $(document).on("click",".editor-post-permalink-editor__save", function () {
449
+ var url;
450
+ if ($('.editor-post-permalink-editor__edit').length) {
451
+ var slug = $('.editor-post-permalink-editor__edit').val();
452
+ url = wpmseoMetaboxL10n.wpmseo_permalink_template.replace('%postname%', slug).replace('http://', '');
453
+ }
454
+
455
+ $('#wpmseosnippet').find('.url').html(url);
456
+ });
457
+
458
+ $(document).on("keypress",".editor-post-permalink-editor__edit", function (e) {
459
+ if(e.which === 13){
460
+ var slug = $(this).val();
461
+ console.log(wpmseoMetaboxL10n.wpmseo_permalink_template);
462
+ url = wpmseoMetaboxL10n.wpmseo_permalink_template.replace('%postname%', slug).replace('http://', '');
463
+ $('#wpmseosnippet').find('.url').html(url);
464
+ }
465
  });
inc/class.metaseo-admin.php CHANGED
@@ -1606,45 +1606,39 @@ class MetaSeoAdmin
1606
  public function updateLink1($type, $link_detail, $title, $link_id)
1607
  {
1608
  global $wpdb;
 
 
 
 
 
 
1609
  $value = array('meta_title' => $title);
1610
  $wpdb->update(
1611
  $wpdb->prefix . 'wpms_links',
1612
  $value,
1613
  array('id' => (int) $link_id)
1614
  );
1615
-
1616
  $post = get_post($link_detail->source_id);
1617
- if (!empty($post)) {
1618
- $content = $post->post_content;
1619
- $links = wpmsExtractTags($post->post_content, 'a', false, true);
1620
- foreach ($links as $link) {
1621
- if ($link['contents'] === $link_detail->link_text) {
1622
- $new_html = '<a';
1623
-
1624
- foreach ($link['attributes'] as $name => $value) {
1625
- //Skip special keys like '#raw' and '#offset'
1626
- if (substr($name, 0, 1) === '#') {
1627
- continue;
1628
- }
1629
-
1630
- if (!isset($link['attributes']['title'])) {
1631
- $new_html .= sprintf(' %s="%s"', 'title', esc_attr($title));
1632
- }
1633
 
1634
- if ($name === 'title') {
1635
- $new_html .= sprintf(' %s="%s"', $name, esc_attr($title));
1636
- } else {
1637
- $new_html .= sprintf(' %s="%s"', $name, esc_attr($value));
1638
- }
 
 
 
 
1639
  }
1640
- $new_html .= '>' . $link_detail->link_text . '</a>';
1641
- $content = str_replace($link['full_tag'], $new_html, $content);
1642
  }
 
 
 
1643
  }
1644
 
1645
  $my_post = array(
1646
  'ID' => (int) $link_detail->source_id,
1647
- 'post_content' => $content
1648
  );
1649
  remove_action('post_updated', array('MetaSeoBrokenLinkTable', 'updatePost'));
1650
  wp_update_post($my_post);
@@ -1654,6 +1648,97 @@ class MetaSeoAdmin
1654
  }
1655
  }
1656
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1657
  /**
1658
  * Ajax update link meta title and content editor
1659
  *
1606
  public function updateLink1($type, $link_detail, $title, $link_id)
1607
  {
1608
  global $wpdb;
1609
+ global $wp_version;
1610
+ // Purge title
1611
+ $title = strip_tags($title);
1612
+ $title = str_replace("'", '', $title);
1613
+ $title = str_replace('"', '', $title);
1614
+
1615
  $value = array('meta_title' => $title);
1616
  $wpdb->update(
1617
  $wpdb->prefix . 'wpms_links',
1618
  $value,
1619
  array('id' => (int) $link_id)
1620
  );
 
1621
  $post = get_post($link_detail->source_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1622
 
1623
+ if (!empty($post)) {
1624
+ if (version_compare($wp_version, '5.0', '>=')) {
1625
+ if (function_exists('has_blocks')) {
1626
+ if (has_blocks((int)$link_detail->source_id)) {
1627
+ // Gutenberg
1628
+ $post_content = $this->gutenbergUpdateContent($post->post_content, $link_detail, $title);
1629
+ } else {
1630
+ // Classic editor
1631
+ $post_content = $this->replaceNewTitle($post->post_content, $link_detail, $title);
1632
  }
 
 
1633
  }
1634
+ } else {
1635
+ // Classic editor
1636
+ $post_content = $this->replaceNewTitle($post->post_content, $link_detail, $title);
1637
  }
1638
 
1639
  $my_post = array(
1640
  'ID' => (int) $link_detail->source_id,
1641
+ 'post_content' => $post_content
1642
  );
1643
  remove_action('post_updated', array('MetaSeoBrokenLinkTable', 'updatePost'));
1644
  wp_update_post($my_post);
1648
  }
1649
  }
1650
 
1651
+ /**
1652
+ * Update link meta title and content editor in gutenberg
1653
+ *
1654
+ * @param string $post_content Content of posts
1655
+ * @param string $link_detail Link details
1656
+ * @param string $title Title value
1657
+ *
1658
+ * @return string
1659
+ */
1660
+ public function gutenbergUpdateContent($post_content, $link_detail, $title)
1661
+ {
1662
+ $blocks = parse_blocks($post_content);
1663
+ $allowed_blocks = array(
1664
+ // Classic blocks have their blockName set to null.
1665
+ null,
1666
+ 'core/button',
1667
+ 'core/paragraph',
1668
+ 'core/heading',
1669
+ 'core/list',
1670
+ 'core/quote',
1671
+ 'core/cover',
1672
+ 'core/html',
1673
+ 'core/verse',
1674
+ 'core/preformatted',
1675
+ 'core/pullquote',
1676
+ 'core/table',
1677
+ 'core/media-text'
1678
+ );
1679
+
1680
+ foreach ($blocks as $block) {
1681
+ // Gutenberg block
1682
+ if (in_array($block['blockName'], $allowed_blocks, true)) {
1683
+ if (!empty($block['innerBlocks'])) {
1684
+ // Skip the block if it has disallowed or nested inner blocks.
1685
+ foreach ($block['innerBlocks'] as $inner_block) {
1686
+ if (!in_array($inner_block['blockName'], $allowed_blocks, true) ||
1687
+ !empty($inner_block['innerBlocks'])
1688
+ ) {
1689
+ continue;
1690
+ }
1691
+ }
1692
+ }
1693
+
1694
+ if (strpos($block['innerHTML'], $link_detail->link_text) !== false) {
1695
+ $post_content = $this->replaceNewTitle($post_content, $link_detail, $title);
1696
+ }
1697
+ }
1698
+ }
1699
+
1700
+ return $post_content;
1701
+ }
1702
+
1703
+ /**
1704
+ * Filter and replace new title
1705
+ *
1706
+ * @param string $post_content Content of posts
1707
+ * @param string $link_detail Link details
1708
+ * @param string $title Title value
1709
+ *
1710
+ * @return string
1711
+ */
1712
+ protected function replaceNewTitle($post_content, $link_detail, $title)
1713
+ {
1714
+ $links = wpmsExtractTags($post_content, 'a', false, true);
1715
+ $title_tag = sprintf('%s="%s"', 'title', esc_attr($title));
1716
+ if (!empty($links)) {
1717
+ foreach ($links as $link) {
1718
+ if ($link['contents'] === $link_detail->link_text) {
1719
+ if (!isset($link['attributes']['title'])) {
1720
+ // Not titlte, add new
1721
+ $new_html = preg_replace(
1722
+ '/<a/is',
1723
+ '<a '.$title_tag,
1724
+ $link['full_tag']
1725
+ );
1726
+ } else {
1727
+ $new_html = preg_replace(
1728
+ '/title=(["\'])(.*?)["\']/is',
1729
+ $title_tag,
1730
+ $link['full_tag']
1731
+ );
1732
+ }
1733
+ // Replace tag
1734
+ $post_content = str_replace($link['full_tag'], $new_html, $post_content);
1735
+ }
1736
+ }
1737
+ }
1738
+
1739
+ return $post_content;
1740
+ }
1741
+
1742
  /**
1743
  * Ajax update link meta title and content editor
1744
  *
inc/class.metaseo-image-list-table.php CHANGED
@@ -914,6 +914,76 @@ class MetaSeoImageListTable extends WP_List_Table
914
  return $new_sizes;
915
  }
916
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
917
  /**
918
  * Display page fix meta list
919
  *
@@ -939,6 +1009,29 @@ class MetaSeoImageListTable extends WP_List_Table
939
  //Get default meta information of the image
940
  $alt = get_post_meta($img_post_id, '_wp_attachment_image_alt', true);
941
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
942
  <h3 class="content-header"><?php echo esc_html($header) ?></h3>
943
  <div class="content-box">
944
  <table class="wp-list-table widefat fixed posts">
@@ -993,13 +1086,19 @@ class MetaSeoImageListTable extends WP_List_Table
993
  } else {
994
  $placeholder = '';
995
  }
 
 
 
 
 
 
996
 
997
  ?>
998
  <div>
999
  <label class="metaseo-img-lb m-r-10 wpms-text"><?php echo esc_html($lb); ?></label>
1000
  <input type="text" value="<?php echo esc_attr($value) ?>"
1001
  id="<?php echo esc_attr('metaseo-img-' . $type . '-' . $post['ID']) ?>"
1002
- class="<?php echo esc_attr('metaseo-fix-meta metaseo-img-' . $type) ?>"
1003
  data-meta-key="_metaseo_fix_metas"
1004
  data-post-id="<?php echo esc_attr($post['ID']) ?>"
1005
  data-img-post-id="<?php echo esc_attr($img_post_id) ?>"
@@ -1009,6 +1108,12 @@ class MetaSeoImageListTable extends WP_List_Table
1009
  placeholder="<?php echo esc_attr($placeholder) ?>"
1010
  onfocus="metaseo_fix_meta(this);" onblur="updateInputBlur(this)"
1011
  onkeydown="return checkeyCode(event)"/>
 
 
 
 
 
 
1012
  </div>
1013
 
1014
  <?php if (trim($value) === '' && trim($alt) !== '') : ?>
@@ -1526,7 +1631,7 @@ class MetaSeoImageListTable extends WP_List_Table
1526
  self::autoUpdatePostContent($post_id, $meta_type, $meta_value);
1527
  $response->type = 'auto_override';
1528
  $response->pid = $post_id;
1529
- $response->imgname = $_POST['img_name'];
1530
  }
1531
 
1532
  $response->updated = true;
@@ -1557,7 +1662,10 @@ class MetaSeoImageListTable extends WP_List_Table
1557
  }
1558
 
1559
  $_POST = stripslashes_deep($_POST);
1560
- $img = trim($_POST['img_name']);
 
 
 
1561
  if ($post_id && !empty($img)) {
1562
  $fn = 'display_fix_metas_list';
1563
  if (method_exists('MetaSeoImageListTable', $fn)) {
@@ -1571,11 +1679,11 @@ class MetaSeoImageListTable extends WP_List_Table
1571
  foreach ($posts as $ID => &$post) {
1572
  $img_counter += count($post['meta']);
1573
  foreach ($post['meta'] as $order => $meta) {
1574
- if ($meta['type']['alt'] === '' || $meta['type']['title'] === '') {
1575
  $toEdit = true;
1576
  }
1577
 
1578
- if ($meta['type']['alt'] !== '' && $meta['type']['title'] !== '') {
1579
  $pIDs[$ID][] = $order;
1580
  }
1581
  }
@@ -1815,6 +1923,7 @@ class MetaSeoImageListTable extends WP_List_Table
1815
  */
1816
  public static function updateImgMetaCallback($wpmspost, $return = true)
1817
  {
 
1818
  $response = new stdClass();
1819
  $response->updated = false;
1820
 
@@ -1845,64 +1954,46 @@ class MetaSeoImageListTable extends WP_List_Table
1845
  $response->msg = esc_html__('The post has been deleted before, please check again!', 'wp-meta-seo');
1846
  } else {
1847
  if ($post->post_content !== '') {
1848
- //Split content part that do not contain img tag
1849
- $post_content_split = preg_split(
1850
- '/(<img[\s]+[^>]*src\s*=\s*)([\"\'])([^>]+?)\2([^<>]*>)/i',
1851
- $post->post_content
1852
- );
1853
- //Get all img tag from the content
1854
- preg_match_all(
1855
- '/(<img[\s]+[^>]*src\s*=\s*)([\"\'])([^>]+?)\2([^<>]*>)/i',
1856
- $post->post_content,
1857
- $matches
1858
- );
1859
- $img_tags = $matches[0];
1860
- if (isset($img_tags[$meta_order])) {
1861
- // remove attr
1862
- preg_match_all('/(alt)=("[^"]*")/i', $img_tags[$meta_order], $atts);
1863
- if (isset($atts[0][0])) {
1864
- $img_tags[$meta_order] = str_replace($atts[0][0], '', $img_tags[$meta_order]);
1865
- }
1866
- $img_tags[$meta_order] = preg_replace('/alt\s*=\s*(\'|").+(\'|")/i', '', $img_tags[$meta_order]);
1867
- // update attr
1868
- $img_tags[$meta_order] = preg_replace(
1869
- '/(<img\b[^><]*)>/i',
1870
- '$1 ' . $meta_type . '="' . $meta_value . '">',
1871
- $img_tags[$meta_order]
1872
- );
1873
- // create new post content
1874
- $post_content = '';
1875
- foreach ($post_content_split as $key => $split) {
1876
- if (isset($img_tags[$key])) {
1877
- $img_tag = $img_tags[$key];
1878
  } else {
1879
- $img_tag = '';
 
1880
  }
1881
- $post_content .= $split . $img_tag;
1882
  }
 
 
 
 
1883
 
1884
- remove_action('post_updated', array('MetaSeoBrokenLinkTable', 'updatePost'));
1885
 
1886
- $is_elementor_edit = (! !get_post_meta($post->ID, '_elementor_edit_mode', true));
1887
 
1888
- //Update content of this post.
1889
- if (!wp_update_post(array('ID' => $post->ID, 'post_content' => $post_content))) {
1890
- $response->msg = esc_html__('The post haven\'t been updated, please check again!', 'wp-meta-seo');
1891
- } else {
1892
- // compatible with elementor plugin (alt tag not display on frontend)
1893
- delete_post_meta($post->ID, '_elementor_edit_mode');
1894
- // Fix elementor change when edit alt image
1895
- if ($is_elementor_edit) {
1896
- update_post_meta($post->ID, '_elementor_edit_mode', 'builder');
1897
- }
1898
- update_option('wpms_last_update_post', time());
1899
- $response->updated = true;
1900
- $response->type_change = 'edit_meta_alt';
1901
- $response->msg = ucfirst($meta_type) . esc_html__(' was saved', 'wp-meta-seo');
1902
- }
1903
  } else {
1904
- $response->msg = esc_html__('This image has been removed from
1905
- the post, please check again!', 'wp-meta-seo');
 
 
 
 
 
 
 
 
1906
  }
1907
  } else {
1908
  $response->msg = esc_html__('Content of the post is empty, please check again', 'wp-meta-seo');
@@ -1915,6 +2006,113 @@ class MetaSeoImageListTable extends WP_List_Table
1915
  }
1916
  }
1917
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1918
  /**
1919
  * Scan image metas
1920
  *
914
  return $new_sizes;
915
  }
916
 
917
+ /**
918
+ * Check post has blocks.
919
+ *
920
+ * @param integer $postId Id of post
921
+ * @param string $linkUrl Link value
922
+ * @param string $value Value of alt
923
+ *
924
+ * @return boolean
925
+ */
926
+ private static function checkBlocks($postId, $linkUrl, $value)
927
+ {
928
+ global $wp_version;
929
+ $allowed_blocks = array(
930
+ // Classic blocks have their blockName set to null.
931
+ null,
932
+ 'core/media-text',
933
+ 'core/image',
934
+ 'core/gallery',
935
+ 'core/html',
936
+ 'core/heading',
937
+ 'core/list',
938
+ 'core/quote',
939
+ 'core/verse',
940
+ 'core/preformatted',
941
+ 'core/pullquote',
942
+ 'core/columns',
943
+ 'core/column',
944
+ );
945
+ $output = true;
946
+ if (version_compare($wp_version, '5.0', '>=')) {
947
+ if (function_exists('has_blocks')) {
948
+ if (has_blocks((int)$postId)) {
949
+ $post = get_post((int)$postId);
950
+ $blocks = parse_blocks($post->post_content);
951
+
952
+ foreach ($blocks as $block) {
953
+ if (in_array($block['blockName'], $allowed_blocks, true)) {
954
+ if (!empty($block['innerBlocks'])) {
955
+ // Skip the block if it has disallowed or nested inner blocks.
956
+ foreach ($block['innerBlocks'] as $inner_block) {
957
+ if (!in_array($inner_block['blockName'], $allowed_blocks, true) ||
958
+ !empty($inner_block['innerBlocks'])
959
+ ) {
960
+ continue;
961
+ }
962
+ }
963
+ }
964
+
965
+ if (empty($value)) {
966
+ $output = false;
967
+ break;
968
+ }
969
+
970
+ if (strpos($block['innerHTML'], $linkUrl) !== false && strpos($block['innerHTML'], $value) !== false) {
971
+ $output = false;
972
+ }
973
+ }
974
+ }
975
+ } else {
976
+ $output = false;
977
+ }
978
+ }
979
+ } else {
980
+ $output = false;
981
+ }
982
+
983
+ return $output;
984
+ }
985
+
986
+
987
  /**
988
  * Display page fix meta list
989
  *
1009
  //Get default meta information of the image
1010
  $alt = get_post_meta($img_post_id, '_wp_attachment_image_alt', true);
1011
  ?>
1012
+ <script>
1013
+ jQuery(".wpms-blocks-active").attr('disabled','disabled');
1014
+ jQuery('.wpms-material-icons-gutenberg').qtip({
1015
+ content: {
1016
+ attr: 'data-alt'
1017
+ },
1018
+ position: {
1019
+ my: 'bottom left',
1020
+ at: 'top center'
1021
+ },
1022
+ style: {
1023
+ tip: {
1024
+ corner: true
1025
+ },
1026
+ classes: 'wpms-widgets-qtip'
1027
+ },
1028
+ show: 'hover',
1029
+ hide: {
1030
+ fixed: true,
1031
+ delay: 10
1032
+ }
1033
+ });
1034
+ </script>
1035
  <h3 class="content-header"><?php echo esc_html($header) ?></h3>
1036
  <div class="content-box">
1037
  <table class="wp-list-table widefat fixed posts">
1086
  } else {
1087
  $placeholder = '';
1088
  }
1089
+ $has_block = self::checkBlocks($post['ID'], $meta['img_src'], $value);
1090
+
1091
+ $blocks_class = '';
1092
+ if ($has_block) {
1093
+ $blocks_class = 'wpms-blocks-active';
1094
+ }
1095
 
1096
  ?>
1097
  <div>
1098
  <label class="metaseo-img-lb m-r-10 wpms-text"><?php echo esc_html($lb); ?></label>
1099
  <input type="text" value="<?php echo esc_attr($value) ?>"
1100
  id="<?php echo esc_attr('metaseo-img-' . $type . '-' . $post['ID']) ?>"
1101
+ class="<?php echo esc_attr('metaseo-fix-meta metaseo-img-' . $type.' '.$blocks_class) ?>"
1102
  data-meta-key="_metaseo_fix_metas"
1103
  data-post-id="<?php echo esc_attr($post['ID']) ?>"
1104
  data-img-post-id="<?php echo esc_attr($img_post_id) ?>"
1108
  placeholder="<?php echo esc_attr($placeholder) ?>"
1109
  onfocus="metaseo_fix_meta(this);" onblur="updateInputBlur(this)"
1110
  onkeydown="return checkeyCode(event)"/>
1111
+ <?php
1112
+ if ($has_block) {
1113
+ echo '<i class="material-icons wpms-material-icons-gutenberg label-dash-widgets"
1114
+ data-alt="'.esc_attr__('We can\'t update this link title because it\'s in a Gutenberg block and it has no alt/title attribute', 'wp-meta-seo').'">info</i>';
1115
+ }
1116
+ ?>
1117
  </div>
1118
 
1119
  <?php if (trim($value) === '' && trim($alt) !== '') : ?>
1631
  self::autoUpdatePostContent($post_id, $meta_type, $meta_value);
1632
  $response->type = 'auto_override';
1633
  $response->pid = $post_id;
1634
+ $response->imgname = (isset($_POST['img_name']) ? $_POST['img_name'] : '');
1635
  }
1636
 
1637
  $response->updated = true;
1662
  }
1663
 
1664
  $_POST = stripslashes_deep($_POST);
1665
+ if (isset($_POST['img_name'])) {
1666
+ $img = trim($_POST['img_name']);
1667
+ }
1668
+
1669
  if ($post_id && !empty($img)) {
1670
  $fn = 'display_fix_metas_list';
1671
  if (method_exists('MetaSeoImageListTable', $fn)) {
1679
  foreach ($posts as $ID => &$post) {
1680
  $img_counter += count($post['meta']);
1681
  foreach ($post['meta'] as $order => $meta) {
1682
+ if ((isset($meta['type']['alt']) && $meta['type']['alt'] === '') || (isset($meta['type']['title']) && $meta['type']['title'] === '')) {
1683
  $toEdit = true;
1684
  }
1685
 
1686
+ if ((isset($meta['type']['alt']) && $meta['type']['alt'] !== '') && (isset($meta['type']['title']) && $meta['type']['title'] !== '')) {
1687
  $pIDs[$ID][] = $order;
1688
  }
1689
  }
1923
  */
1924
  public static function updateImgMetaCallback($wpmspost, $return = true)
1925
  {
1926
+ global $wp_version;
1927
  $response = new stdClass();
1928
  $response->updated = false;
1929
 
1954
  $response->msg = esc_html__('The post has been deleted before, please check again!', 'wp-meta-seo');
1955
  } else {
1956
  if ($post->post_content !== '') {
1957
+ $post_content = $post->post_content;
1958
+ $img_link = '';
1959
+ if (isset($meta[$post_id]['meta'][$meta_order]['img_src'])) {
1960
+ $img_link = $meta[$post_id]['meta'][$meta_order]['img_src'];
1961
+ }
1962
+ if (version_compare($wp_version, '5.0', '>=')) {
1963
+ if (function_exists('has_blocks')) {
1964
+ if (has_blocks($post_content)) {
1965
+ // Gutenberg
1966
+ $post_content = self::gutenbergImgUpdateContent($post_content, $meta_order, $meta_type, $meta_value, $img_link);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1967
  } else {
1968
+ // Classic editor
1969
+ $post_content = self::classicImgUpdateContent($post_content, $meta_order, $meta_type, $meta_value);
1970
  }
 
1971
  }
1972
+ } else {
1973
+ // Classic editor
1974
+ $post_content = self::classicImgUpdateContent($post_content, $meta_order, $meta_type, $meta_value);
1975
+ }
1976
 
 
1977
 
 
1978
 
1979
+ remove_action('post_updated', array('MetaSeoBrokenLinkTable', 'updatePost'));
1980
+
1981
+ $is_elementor_edit = (! !get_post_meta($post->ID, '_elementor_edit_mode', true));
1982
+
1983
+ //Update content of this post.
1984
+ if (!wp_update_post(array('ID' => $post->ID, 'post_content' => $post_content))) {
1985
+ $response->msg = esc_html__('The post haven\'t been updated, please check again!', 'wp-meta-seo');
 
 
 
 
 
 
 
 
1986
  } else {
1987
+ // compatible with elementor plugin (alt tag not display on frontend)
1988
+ delete_post_meta($post->ID, '_elementor_edit_mode');
1989
+ // Fix elementor change when edit alt image
1990
+ if ($is_elementor_edit) {
1991
+ update_post_meta($post->ID, '_elementor_edit_mode', 'builder');
1992
+ }
1993
+ update_option('wpms_last_update_post', time());
1994
+ $response->updated = true;
1995
+ $response->type_change = 'edit_meta_alt';
1996
+ $response->msg = ucfirst($meta_type) . esc_html__(' was saved', 'wp-meta-seo');
1997
  }
1998
  } else {
1999
  $response->msg = esc_html__('Content of the post is empty, please check again', 'wp-meta-seo');
2006
  }
2007
  }
2008
 
2009
+ /**
2010
+ * Update image in blocks content
2011
+ *
2012
+ * @param array $post_content Content of post
2013
+ * @param string $meta_order Meta order
2014
+ * @param string $meta_type Meta type
2015
+ * @param string $meta_value Meta value
2016
+ * @param string $img_link Link image
2017
+ *
2018
+ * @return string
2019
+ */
2020
+ public static function gutenbergImgUpdateContent($post_content, $meta_order, $meta_type, $meta_value, $img_link)
2021
+ {
2022
+ $blocks = parse_blocks($post_content);
2023
+ $allowed_blocks = array(
2024
+ // Classic blocks have their blockName set to null.
2025
+ null,
2026
+ 'core/media-text',
2027
+ 'core/image',
2028
+ 'core/gallery',
2029
+ 'core/html',
2030
+ 'core/heading',
2031
+ 'core/list',
2032
+ 'core/quote',
2033
+ 'core/verse',
2034
+ 'core/preformatted',
2035
+ 'core/pullquote',
2036
+ 'core/columns',
2037
+ 'core/column',
2038
+ );
2039
+
2040
+ foreach ($blocks as $block) {
2041
+ // Gutenberg block
2042
+ if (in_array($block['blockName'], $allowed_blocks, true)) {
2043
+ if (!empty($block['innerBlocks'])) {
2044
+ // Skip the block if it has disallowed or nested inner blocks.
2045
+ foreach ($block['innerBlocks'] as $inner_block) {
2046
+ if (!in_array($inner_block['blockName'], $allowed_blocks, true) ||
2047
+ !empty($inner_block['innerBlocks'])
2048
+ ) {
2049
+ continue;
2050
+ }
2051
+ }
2052
+ }
2053
+
2054
+ if (strpos($block['innerHTML'], $img_link) !== false) {
2055
+ $new_blocks = self::classicImgUpdateContent($block['innerHTML'], $meta_order, $meta_type, $meta_value);
2056
+ $post_content = str_replace($block['innerHTML'], $new_blocks, $post_content);
2057
+ }
2058
+ }
2059
+ }
2060
+
2061
+ return $post_content;
2062
+ }
2063
+
2064
+ /**
2065
+ * Update image in classic content
2066
+ *
2067
+ * @param array $post_content Content of post
2068
+ * @param string $meta_order Meta order
2069
+ * @param string $meta_type Meta type
2070
+ * @param string $meta_value Meta value
2071
+ *
2072
+ * @return string
2073
+ */
2074
+ public static function classicImgUpdateContent($post_content, $meta_order, $meta_type, $meta_value)
2075
+ {
2076
+ //Split content part that do not contain img tag
2077
+ $post_content_split = preg_split(
2078
+ '/(<img[\s]+[^>]*src\s*=\s*)([\"\'])([^>]+?)\2([^<>]*>)/i',
2079
+ $post_content
2080
+ );
2081
+ //Get all img tag from the content
2082
+ preg_match_all(
2083
+ '/(<img[\s]+[^>]*src\s*=\s*)([\"\'])([^>]+?)\2([^<>]*>)/i',
2084
+ $post_content,
2085
+ $matches
2086
+ );
2087
+ $img_tags = $matches[0];
2088
+ if (isset($img_tags[$meta_order])) {
2089
+ // remove attr
2090
+ preg_match_all('/(alt)=("[^"]*")/i', $img_tags[$meta_order], $atts);
2091
+ if (isset($atts[0][0])) {
2092
+ $img_tags[$meta_order] = str_replace($atts[0][0], '', $img_tags[$meta_order]);
2093
+ }
2094
+ $img_tags[$meta_order] = preg_replace('/alt\s*=\s*(\'|").+(\'|")/i', '', $img_tags[$meta_order]);
2095
+ // update attr
2096
+ $img_tags[$meta_order] = preg_replace(
2097
+ '/(<img\b[^><]*)>/i',
2098
+ '$1 ' . $meta_type . '="' . $meta_value . '">',
2099
+ $img_tags[$meta_order]
2100
+ );
2101
+ // create new post content
2102
+ $post_content = '';
2103
+ foreach ($post_content_split as $key => $split) {
2104
+ if (isset($img_tags[$key])) {
2105
+ $img_tag = $img_tags[$key];
2106
+ } else {
2107
+ $img_tag = '';
2108
+ }
2109
+ $post_content .= $split . $img_tag;
2110
+ }
2111
+ }
2112
+
2113
+ return $post_content;
2114
+ }
2115
+
2116
  /**
2117
  * Scan image metas
2118
  *
inc/class.metaseo-link-list-table.php CHANGED
@@ -263,9 +263,9 @@ class MetaSeoLinkListTable extends WP_List_Table
263
  protected function get_sortable_columns() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
264
  {
265
  $sortable = array(
266
- 'post_id' => array('post_title', true),
267
  'col_link_url' => array('link_url', true),
268
  'col_link_title' => array('meta_title', true),
 
269
  'col_follow' => array('follow', true),
270
  );
271
 
@@ -612,6 +612,69 @@ class MetaSeoLinkListTable extends WP_List_Table
612
  <?php
613
  }
614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  /**
616
  * Generate the table rows
617
  *
@@ -623,6 +686,12 @@ class MetaSeoLinkListTable extends WP_List_Table
623
  list($columns) = $this->get_column_info();
624
  if (!empty($records)) {
625
  foreach ($records as $rec) {
 
 
 
 
 
 
626
  echo '<tr id="' . esc_attr('record_' . $rec->id) . '" data-link="' . esc_attr($rec->id) . '"
627
  data-post_id="' . esc_attr($rec->source_id) . '">';
628
  foreach ($columns as $column_name => $column_display_name) {
@@ -670,7 +739,11 @@ class MetaSeoLinkListTable extends WP_List_Table
670
  case 'col_link_title':
671
  echo '<td colspan="3">';
672
  echo '<input type="text" data-post_id="' . esc_attr($rec->source_id) . '" name="metaseo_link_title"
673
- id="metaseo_link_title" class="metaseo_link_title" value="' . esc_attr($rec->meta_title) . '">';
 
 
 
 
674
  echo '<button type="button" data-post_id="' . esc_attr($rec->source_id) . '"
675
  class="wpms_update_link ju-button orange-button wpms-small-btn">' . esc_html__('Update', 'wp-meta-seo') . '</button>';
676
  echo '<strong class="wpms_mesage_link">' . esc_html__('Saved.', 'wp-meta-seo') . '</strong>';
263
  protected function get_sortable_columns() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
264
  {
265
  $sortable = array(
 
266
  'col_link_url' => array('link_url', true),
267
  'col_link_title' => array('meta_title', true),
268
+ 'col_link_label' => array('link_text', true),
269
  'col_follow' => array('follow', true),
270
  );
271
 
612
  <?php
613
  }
614
 
615
+ /**
616
+ * Check post has blocks.
617
+ *
618
+ * @param integer $postId Id of post
619
+ * @param string $linkUrl Link value
620
+ *
621
+ * @return boolean
622
+ */
623
+ public function checkBlocks($postId, $linkUrl)
624
+ {
625
+ global $wp_version;
626
+ $allowed_blocks = array(
627
+ // Classic blocks have their blockName set to null.
628
+ null,
629
+ 'core/button',
630
+ 'core/paragraph',
631
+ 'core/heading',
632
+ 'core/list',
633
+ 'core/quote',
634
+ 'core/cover',
635
+ 'core/html',
636
+ 'core/verse',
637
+ 'core/preformatted',
638
+ 'core/pullquote',
639
+ 'core/table',
640
+ 'core/media-text'
641
+ );
642
+ $output = true;
643
+ if (version_compare($wp_version, '5.0', '>=')) {
644
+ if (function_exists('has_blocks')) {
645
+ if (has_blocks((int)$postId)) {
646
+ $post = get_post((int)$postId);
647
+ $blocks = parse_blocks($post->post_content);
648
+
649
+ foreach ($blocks as $block) {
650
+ if (in_array($block['blockName'], $allowed_blocks, true)) {
651
+ if (!empty($block['innerBlocks'])) {
652
+ // Skip the block if it has disallowed or nested inner blocks.
653
+ foreach ($block['innerBlocks'] as $inner_block) {
654
+ if (!in_array($inner_block['blockName'], $allowed_blocks, true) ||
655
+ !empty($inner_block['innerBlocks'])
656
+ ) {
657
+ continue;
658
+ }
659
+ }
660
+ }
661
+
662
+ if (strpos($block['innerHTML'], $linkUrl) !== false) {
663
+ $output = false;
664
+ }
665
+ }
666
+ }
667
+ } else {
668
+ $output = false;
669
+ }
670
+ }
671
+ } else {
672
+ $output = false;
673
+ }
674
+
675
+ return $output;
676
+ }
677
+
678
  /**
679
  * Generate the table rows
680
  *
686
  list($columns) = $this->get_column_info();
687
  if (!empty($records)) {
688
  foreach ($records as $rec) {
689
+ $has_block = $this->checkBlocks($rec->source_id, $rec->link_url);
690
+ $blocks_class = '';
691
+ if ($has_block) {
692
+ $blocks_class = 'wpms-blocks-active';
693
+ }
694
+
695
  echo '<tr id="' . esc_attr('record_' . $rec->id) . '" data-link="' . esc_attr($rec->id) . '"
696
  data-post_id="' . esc_attr($rec->source_id) . '">';
697
  foreach ($columns as $column_name => $column_display_name) {
739
  case 'col_link_title':
740
  echo '<td colspan="3">';
741
  echo '<input type="text" data-post_id="' . esc_attr($rec->source_id) . '" name="metaseo_link_title"
742
+ id="metaseo_link_title" class="metaseo_link_title '.esc_attr($blocks_class).'" value="' . esc_attr($rec->meta_title) . '">';
743
+ if ($has_block) {
744
+ echo '<i class="material-icons wpms-material-icons-gutenberg label-dash-widgets"
745
+ data-alt="'.esc_attr__('We can\'t update this link title because it\'s in a Gutenberg block and it has no alt/title attribute', 'wp-meta-seo').'">info</i>';
746
+ }
747
  echo '<button type="button" data-post_id="' . esc_attr($rec->source_id) . '"
748
  class="wpms_update_link ju-button orange-button wpms-small-btn">' . esc_html__('Update', 'wp-meta-seo') . '</button>';
749
  echo '<strong class="wpms_mesage_link">' . esc_html__('Saved.', 'wp-meta-seo') . '</strong>';
inc/class.metaseo-sitemap.php CHANGED
@@ -631,6 +631,10 @@ class MetaSeoSitemap
631
  $check_type = get_post_meta($id, '_menu_item_object', true);
632
  $permalink = $this->getPermalinkSitemap($check_type, $val->ID);
633
  if ($permalink !== '#') {
 
 
 
 
634
  if (!in_array($permalink, $list_links)) {
635
  $list_links[] = $permalink;
636
  if ($type !== 'taxonomy') {
@@ -703,7 +707,10 @@ class MetaSeoSitemap
703
  if (empty($permalink)) {
704
  $permalink = get_permalink($id);
705
  }
706
-
 
 
 
707
  if (!in_array($permalink, $list_links)) {
708
  $list_links[] = $permalink;
709
  if ($type === 'taxonomy') {
@@ -756,6 +763,10 @@ class MetaSeoSitemap
756
  foreach ($res as $val) {
757
  /* get translation post id */
758
  $permalink = get_permalink($val->ID);
 
 
 
 
759
  if (!in_array($permalink, $list_links)) {
760
  $list_links[] = $permalink;
761
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
@@ -823,6 +834,10 @@ class MetaSeoSitemap
823
  if (!empty($posts)) {
824
  foreach ($posts as $val) {
825
  $permalink = get_permalink($val->ID);
 
 
 
 
826
  if (!in_array($permalink, $list_links)) {
827
  $list_links[] = $permalink;
828
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
@@ -874,6 +889,10 @@ class MetaSeoSitemap
874
  if (!empty($settings['wpms_sitemap_customUrl']) && $settings['wpms_sitemap_customUrl'] !== '{}') {
875
  foreach ($settings['wpms_sitemap_customUrl'] as $key => $customUrl) {
876
  if (!empty($listUrls[$key])) {
 
 
 
 
877
  if (!in_array($listUrls[$key]['link'], $list_links)) {
878
  $list_links[] = $listUrls[$key]['link'];
879
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
@@ -912,6 +931,10 @@ class MetaSeoSitemap
912
  foreach ($res as $val) {
913
  /* get translation post id */
914
  $permalink = get_permalink($val->ID);
 
 
 
 
915
  if (!in_array($permalink, $list_links)) {
916
  $list_links[] = $permalink;
917
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
@@ -957,6 +980,10 @@ class MetaSeoSitemap
957
  if (!empty($terms) && !is_wp_error($terms)) {
958
  foreach ($terms as $term_value) {
959
  $permalink = get_term_link((int) $term_value->term_id, $value);
 
 
 
 
960
  if (!in_array($permalink, $list_links)) {
961
  $list_links[] = $permalink;
962
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
631
  $check_type = get_post_meta($id, '_menu_item_object', true);
632
  $permalink = $this->getPermalinkSitemap($check_type, $val->ID);
633
  if ($permalink !== '#') {
634
+ if (strpos($permalink, '#') !== false) {
635
+ // Check anchor links
636
+ $permalink = strstr($permalink, '#', true);
637
+ }
638
  if (!in_array($permalink, $list_links)) {
639
  $list_links[] = $permalink;
640
  if ($type !== 'taxonomy') {
707
  if (empty($permalink)) {
708
  $permalink = get_permalink($id);
709
  }
710
+ if (strpos($permalink, '#') !== false) {
711
+ // Check anchor links
712
+ $permalink = strstr($permalink, '#', true);
713
+ }
714
  if (!in_array($permalink, $list_links)) {
715
  $list_links[] = $permalink;
716
  if ($type === 'taxonomy') {
763
  foreach ($res as $val) {
764
  /* get translation post id */
765
  $permalink = get_permalink($val->ID);
766
+ if (strpos($permalink, '#') !== false) {
767
+ // Check anchor links
768
+ $permalink = strstr($permalink, '#', true);
769
+ }
770
  if (!in_array($permalink, $list_links)) {
771
  $list_links[] = $permalink;
772
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
834
  if (!empty($posts)) {
835
  foreach ($posts as $val) {
836
  $permalink = get_permalink($val->ID);
837
+ if (strpos($permalink, '#') !== false) {
838
+ // Check anchor links
839
+ $permalink = strstr($permalink, '#', true);
840
+ }
841
  if (!in_array($permalink, $list_links)) {
842
  $list_links[] = $permalink;
843
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
889
  if (!empty($settings['wpms_sitemap_customUrl']) && $settings['wpms_sitemap_customUrl'] !== '{}') {
890
  foreach ($settings['wpms_sitemap_customUrl'] as $key => $customUrl) {
891
  if (!empty($listUrls[$key])) {
892
+ if (strpos($listUrls[$key]['link'], '#') !== false) {
893
+ // Check anchor links
894
+ $listUrls[$key]['link'] = strstr($listUrls[$key]['link'], '#', true);
895
+ }
896
  if (!in_array($listUrls[$key]['link'], $list_links)) {
897
  $list_links[] = $listUrls[$key]['link'];
898
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
931
  foreach ($res as $val) {
932
  /* get translation post id */
933
  $permalink = get_permalink($val->ID);
934
+ if (strpos($permalink, '#') !== false) {
935
+ // Check anchor links
936
+ $permalink = strstr($permalink, '#', true);
937
+ }
938
  if (!in_array($permalink, $list_links)) {
939
  $list_links[] = $permalink;
940
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
980
  if (!empty($terms) && !is_wp_error($terms)) {
981
  foreach ($terms as $term_value) {
982
  $permalink = get_term_link((int) $term_value->term_id, $value);
983
+ if (strpos($permalink, '#') !== false) {
984
+ // Check anchor links
985
+ $permalink = strstr($permalink, '#', true);
986
+ }
987
  if (!in_array($permalink, $list_links)) {
988
  $list_links[] = $permalink;
989
  $gglstmp_url = $gglstmp_urlset->appendChild($xml->createElement('url'));
inc/class.metaseo-snippet-preview.php CHANGED
@@ -148,6 +148,12 @@ class WPMSEOSnippetPreview
148
  $this->url .= esc_html($this->slug);
149
  }
150
  }
 
 
 
 
 
 
151
  }
152
 
153
  /**
@@ -157,11 +163,15 @@ class WPMSEOSnippetPreview
157
  */
158
  protected function setContent()
159
  {
 
 
 
160
  $content = '<div id="wpmseosnippet">
161
  <a class="title" id="wpmseosnippet_title" href="#">' . esc_html($this->title) . '</a>
162
- <a class="url m-t-20">' . esc_url($this->url) . '</a><br />
163
  <p class="desc m-t-20">' . esc_html($this->date) . '<span class="autogen"></span><span class="content">' . esc_html($this->description) . '</span></p>
164
  </div>';
 
165
  $this->setContentThroughFilter($content);
166
  }
167
 
148
  $this->url .= esc_html($this->slug);
149
  }
150
  }
151
+
152
+ if (isset($this->post->post_status) && ($this->post->post_status !== 'auto-draft' && $this->post->post_status !== 'draft')) {
153
+ if (!empty($this->post->ID)) {
154
+ $this->url = get_permalink((int)$this->post->ID);
155
+ }
156
+ }
157
  }
158
 
159
  /**
163
  */
164
  protected function setContent()
165
  {
166
+ $url = esc_url($this->url);
167
+ $url = str_replace('http://', '', $url);
168
+ // phpcs:disable WordPress.Security.EscapeOutput -- Content escaped before line 167
169
  $content = '<div id="wpmseosnippet">
170
  <a class="title" id="wpmseosnippet_title" href="#">' . esc_html($this->title) . '</a>
171
+ <a class="url m-t-20">' . $url . '</a><br />
172
  <p class="desc m-t-20">' . esc_html($this->date) . '<span class="autogen"></span><span class="content">' . esc_html($this->description) . '</span></p>
173
  </div>';
174
+ //phpcs:enable
175
  $this->setContentThroughFilter($content);
176
  }
177
 
inc/install-wizard/install-wizard.php CHANGED
@@ -204,6 +204,7 @@ class WpmsInstallWizard
204
  */
205
  public function setHeader()
206
  {
 
207
  ?>
208
  <!DOCTYPE html>
209
  <html <?php language_attributes(); ?>>
204
  */
205
  public function setHeader()
206
  {
207
+ set_current_screen();
208
  ?>
209
  <!DOCTYPE html>
210
  <html <?php language_attributes(); ?>>
inc/pages/link-meta.php CHANGED
@@ -5,6 +5,9 @@ if (!class_exists('MetaSeoLinkListTable')) {
5
  require_once(WPMETASEO_PLUGIN_DIR . '/inc/class.metaseo-link-list-table.php');
6
  }
7
 
 
 
 
8
  add_thickbox();
9
  $metaseo_list_table = new MetaSeoLinkListTable();
10
  $metaseo_list_table->processAction();
5
  require_once(WPMETASEO_PLUGIN_DIR . '/inc/class.metaseo-link-list-table.php');
6
  }
7
 
8
+ wp_enqueue_style('m-style-qtip');
9
+ wp_enqueue_script('jquery-qtip');
10
+ wp_enqueue_script('my-qtips-js');
11
  add_thickbox();
12
  $metaseo_list_table = new MetaSeoLinkListTable();
13
  $metaseo_list_table->processAction();
languages/wp-meta-seo-en_US.mo CHANGED
Binary file
readme.txt CHANGED
@@ -2,13 +2,13 @@
2
  Contributors: JoomUnited
3
  Tags: google, webmaster tools, keywords, meta, meta description, meta keywords, meta title, robots meta, search engine optimization, seo, wordpress seo, yahoo, image optimization, image resize, custom post seo, redirect, redirection, 301, broken link
4
  Requires at least: 4.0
5
- Tested up to: 5.2.0
6
- Stable tag: 4.0.6
7
  Requires PHP: 5.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- WP Meta SEO gives you the control over all your meta content and images. Bulk SEO content and image optimization, SEO on page, 404 & redirect
12
 
13
  == Description ==
14
 
@@ -258,6 +258,10 @@ Yes WP Meta SEO is compatible with Gutenberg editor since 3.7 version.
258
 
259
  == Changelog ==
260
 
 
 
 
 
261
  = 4.0.6 =
262
  * Add : Quick SEO content preview style for WordPress 5.2
263
  * Fix : Bulk action and meta bulk apply to all images
@@ -605,4 +609,4 @@ Site-wide SEO: it's more about your whole site and structure between multiple ar
605
 
606
  And... don't forget to check each month your SEO dashboard :)
607
 
608
- PHP 5.3+, WP 4.3+
2
  Contributors: JoomUnited
3
  Tags: google, webmaster tools, keywords, meta, meta description, meta keywords, meta title, robots meta, search engine optimization, seo, wordpress seo, yahoo, image optimization, image resize, custom post seo, redirect, redirection, 301, broken link
4
  Requires at least: 4.0
5
+ Tested up to: 5.2.2
6
+ Stable tag: 4.0.7
7
  Requires PHP: 5.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ WP Meta SEO gives you the control over all your SEO optimization. Bulk SEO content and image SEO, on page content check, 404 and redirect
12
 
13
  == Description ==
14
 
258
 
259
  == Changelog ==
260
 
261
+ = 4.0.7 =
262
+ * Add : Link editor & Image editor compatible with Gutenberg blocks
263
+ * Fix : The sitemap generated ignore anchor links
264
+
265
  = 4.0.6 =
266
  * Add : Quick SEO content preview style for WordPress 5.2
267
  * Fix : Bulk action and meta bulk apply to all images
609
 
610
  And... don't forget to check each month your SEO dashboard :)
611
 
612
+ PHP 5.6+, WordPress 5.x
wp-meta-seo.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: WP Meta SEO
5
  * Plugin URI: http://www.joomunited.com/wordpress-products/wp-meta-seo
6
  * Description: WP Meta SEO is a plugin for WordPress to fill meta for content, images and main SEO info in a single view.
7
- * Version: 4.0.6
8
  * Text Domain: wp-meta-seo
9
  * Domain Path: /languages
10
  * Author: JoomUnited
@@ -121,7 +121,7 @@ if (!defined('WPMSEO_VERSION')) {
121
  /**
122
  * Plugin version
123
  */
124
- define('WPMSEO_VERSION', '4.0.6');
125
  }
126
 
127
  if (!defined('WPMS_CLIENTID')) {
4
  * Plugin Name: WP Meta SEO
5
  * Plugin URI: http://www.joomunited.com/wordpress-products/wp-meta-seo
6
  * Description: WP Meta SEO is a plugin for WordPress to fill meta for content, images and main SEO info in a single view.
7
+ * Version: 4.0.7
8
  * Text Domain: wp-meta-seo
9
  * Domain Path: /languages
10
  * Author: JoomUnited
121
  /**
122
  * Plugin version
123
  */
124
+ define('WPMSEO_VERSION', '4.0.7');
125
  }
126
 
127
  if (!defined('WPMS_CLIENTID')) {