ACF Link 搭配 Rank Math nofollow, sponsored

狀況

如果你的 WordPress 有使用 ACF 並且有安裝 Rank Math,那麼你可能會發現你在使用 link 連結類型的欄位時會多出「nofollow」和「sponsored」的選項,但實際勾選後卻無法將設定儲存到資料庫裡的狀況。

解決方法

解決方法是我們需要複寫前端的 ACF JavaScript 產生對應的 hidden field,並將該資料設定到前端的欄位內,在表單送出後自然就會儲存到資料庫內。

第一步:在前端產生對應的 hidden 欄位

<?php
function acf_link_rank_math_render_field( $field ) {
?>
<script>
(function ($) {
    const nofollow = 'input[name="<?= $field['name'] ?>[nofollow]"]'
    const sponsored = 'input[name="<?= $field['name'] ?>[sponsored]"]'
    const container = $('input[name="<?= $field['name'] ?>[title]"]').parent()
    if (container.find(nofollow).length == 0)
        container.append(`<?= sprintf('<input type="hidden" class="input-nofollow" name="%s[nofollow]" value="%s"/>', $field['name'], $field['value']['nofollow'] ?? '') ?>`)
    if (container.find(sponsored).length == 0)
        container.append(`<?= sprintf('<input type="hidden" class="input-sponsored" name="%s[sponsored]" value="%s"/>', $field['name'], $field['value']['sponsored'] ?? '') ?>`)
})(jQuery)
</script>
<?php
}

add_action('acf/render_field/type=link', 'acf_link_rank_math_render_field');

第二步:複寫前端勾選和儲存的方法

function acf_load_acf_link_rank_math_js() {
?>
<script type="text/javascript">
(function($) {
acf.wpLink.getNodeValue = function () {
    var $node = this.get('node');
    return {
        title: acf.decode($node.html()),
        url: $node.attr('href'),
        target: $node.attr('target'),
        nofollow: $node.siblings('input.input-nofollow').val(),
        sponsored: $node.siblings('input.input-sponsored').val(),
    };
}

acf.wpLink.setNodeValue = function (val) {
    var $node = this.get('node');
    $node.text(val.title);
    $node.attr('href', val.url);
    $node.attr('target', val.target);
    $node.attr('nofollow', val.nofollow);
    $node.attr('sponsored', val.sponsored);
    $node.trigger('change');

    $node.siblings('input.input-nofollow').val(val.nofollow)
    $node.siblings('input.input-sponsored').val(val.sponsored)
}

acf.wpLink.getInputValue = function () {
    return {
      title: $('#wp-link-text').val(),
      url: $('#wp-link-url').val(),
      target: $('#wp-link-target').prop('checked') ? '_blank' : '',
      nofollow: $('#wp-link-nofollow').prop('checked') ? 1 : 0,
      sponsored: $('#wp-link-sponsored').prop('checked') ? 1 : 0,
    };
}

acf.wpLink.setInputValue = function (val) {
    $('#wp-link-text').val(val.title);
    $('#wp-link-url').val(val.url);
    $('#wp-link-target').prop('checked', val.target === '_blank');
    $('#wp-link-nofollow').prop('checked', val.nofollow == 1);
    $('#wp-link-sponsored').prop('checked', val.sponsored == 1);
}

})(jQuery); 
</script>
<?php
}

add_action('acf/input/admin_footer', 'acf_load_acf_link_rank_math_js', 99);