Last active
December 9, 2022 13:06
-
-
Save doubleedesign/2fe3034c658f3e62e2d841a420bb4bc0 to your computer and use it in GitHub Desktop.
Get meta descriptions in The SEO Framework from ACF flexible content fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* The SEO Framework + ACF flexible content integration | |
* TSF will look at the excerpt and then the content to generate the default meta description. | |
* If both of those are empty, this code looks for ACF flexible modules to get it from. | |
* // TODO: Make this work with archives as well as posts | |
* @param $description | |
* @param $args | |
* | |
* @return mixed|string | |
*/ | |
function doublee_seo_framework_description($description, $args) { | |
if(empty($description) && get_the_id()) { | |
$value_to_use = ''; | |
// Find the first set of flexible modules, if there are any | |
$field_name = doublee_get_name_of_first_acf_field_of_type('flexible_content'); | |
$modules = get_field($field_name); | |
// If there's modules, find the first one with a WYSIWYG or textarea field and get its value | |
if($field_name && $modules) { | |
$value_to_use = doublee_get_first_acf_subfield_value_of_type($modules, array('wysiwyg', 'textarea'), $field_name); | |
} | |
// Tell TSF to use this value; it will take care of truncating it for us. | |
$description = strip_tags($value_to_use); | |
} | |
return $description; | |
} | |
add_filter('the_seo_framework_custom_field_description', 'doublee_seo_framework_description', 10, 2); | |
add_filter('the_seo_framework_generated_description', 'doublee_seo_framework_description', 10, 2); | |
add_filter('the_seo_framework_fetched_description_excerpt', 'doublee_seo_framework_description', 10, 2); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Utility function to get data about sub-fields that we want to use in doublee_get_first_acf_subfield_value_of_type | |
* because you can't use get_sub_field_object outside of an ACF have_rows loop which was causing headaches with nested repeaters and whatnot | |
* | |
* @param $field_name | |
* @param $post_id | |
* | |
* @return array | |
*/ | |
function doublee_get_sub_field_data($field_name, $post_id) { | |
global $wpdb; | |
$data = array(); | |
// Query the database for the field content of this field's subfields. Starts with the field slug without an underscore. | |
// Returns an indexed array of meta ID, postt ID, meta key, and meta value sub-arrays. | |
$meta_key_search = "'" . $field_name . "%'"; | |
$postmeta = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = $post_id AND meta_key LIKE $meta_key_search ORDER BY meta_key ASC", ARRAY_A); | |
// Query the database for the field keys of this field's subfields. Starts with the field slug preceded by an underscore. | |
// Field keys are not unique - e.g. repeaters will have the same field key for each instance of a subfield. | |
$meta_key_search = "'_" . $field_name . "%'"; | |
$keymeta = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = $post_id AND meta_key LIKE $meta_key_search ORDER BY meta_key ASC", ARRAY_A); | |
// Merge the results | |
$merged = array(); | |
foreach($postmeta as $index => $result_data) { | |
$merged[] = array_merge_recursive($result_data, $keymeta[$index]); | |
} | |
// Because the keys are the same in the arrays we merged, this will cause the values to be a sub-array | |
// Let's fix that, and don't include data we don't need | |
$flattened = array(); | |
foreach($merged as $merged_array) { | |
$flattened[] = array( | |
'post_id' => $merged_array['post_id'][0], | |
'value' => $merged_array['meta_value'][0], | |
'key' => $merged_array['meta_value'][1] | |
); | |
} | |
// Use this and some more processing to build an array of all the data we need | |
$i = 0; | |
foreach($flattened as $index => $raw_data) { | |
if(is_array($raw_data)) { | |
$object = get_field_object($raw_data['key']); | |
$value = $raw_data['value']; | |
$parent_key = $object['parent']; | |
$parent_name = ''; | |
if(!empty($parent_key)) { | |
$parent_object = get_field_object($parent_key); | |
$parent_name = $parent_object['name']; | |
} | |
$data[$i]['name'] = $object['name']; | |
$data[$i]['value'] = $value; | |
$data[$i]['type'] = $object['type']; | |
$data[$i]['parent_name'] = $parent_name; | |
$i++; | |
} | |
} | |
return $data; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Utility function to get the name of the first ACF field of the specified type. | |
* @param $field_type | |
* @param string $post_id | |
* | |
* @return int|string | |
*/ | |
function doublee_get_name_of_first_acf_field_name_of_type($field_type, $post_id = '') { | |
$field_name = ''; | |
if(!$post_id) { | |
$post_id = get_the_id(); | |
} | |
$acf_fields = get_fields($post_id, true); | |
if($acf_fields) { | |
foreach($acf_fields as $name => $value) { | |
$field_object = get_field_object($name); | |
if($field_object['type'] == $field_type) { | |
$field_name = $name; | |
break; | |
} | |
} | |
} | |
return $field_name; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Utility function to get the first direct subfield in an ACF set (flexible content or repeater) that is of the given type(s) | |
* Recursively checks within nested sets for their first instance of the type when applicable | |
* Returns the field (or sub-field) value ready for use by the calling function. | |
* // TODO: Test this on grouped fields too. | |
* | |
* @param array $fields Array of ACF fields or subfields, as returned by get_field() on a flexible content or repeater field | |
* @param array $types The field types we want to look for | |
* @param string $parent_field_name The name of the top level field, e.g. the flexible content field. | |
* Optional because when looking at nested fields recursively, the original value needs to be passed again. | |
* | |
* @return string | |
*/ | |
function doublee_get_first_acf_subfield_value_of_type(array $fields, array $types, string $parent_field_name = '') { | |
$all_field_data = doublee_get_sub_field_data('content_modules', get_the_id()); | |
// If no fields were provided if they're not an array, bail early | |
// Brought this out on its own to keep the main loop's nesting as simple and shallow as possible | |
if(empty($fields) && !is_array($fields)) { | |
return false; | |
} | |
// Loop through the fields | |
foreach($fields as $index => $subfield) { | |
// If the subfield's value is an array, it's a nested fieldset so we need to go another level down | |
if(is_array($subfield)) { | |
return doublee_get_first_acf_subfield_value_of_type($fields[$index], $types, $parent_field_name); | |
} | |
// We've reached content fields and can now proceed to look for our desired field types | |
foreach($all_field_data as $data) { | |
if(($data['name'] == $index) && (in_array($data['type'],$types)) && (!empty($data['value']))) { | |
return $value_to_use = $data['value']; | |
} | |
} | |
} | |
// If a value hasn't been returned yet, there isn't one | |
return false; | |
} |
Please see https://gist.github.com/sybrew/b0bd829846fc1eda24025eb9f50eb86d for a proper format of using $args
so that the filters also work on the administrative screens.
On https://gist.github.com/doubleedesign/2fe3034c658f3e62e2d841a420bb4bc0#file-acf-tsf-integration-php-L18 you call an undefined function.
This snippet is from quite some time ago and I don't use it anymore (it was for some particular projects I no longer work on) so can't be 100% sure without setting up a test site to check, but I think it's likely meant to be doublee_get_name_of_first_acf_field_name_of_type
in the data.php
file above. I probably just messed up the naming when de-identifying the client by renaming functions for this gist.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On https://gist.github.com/doubleedesign/2fe3034c658f3e62e2d841a420bb4bc0#file-acf-tsf-integration-php-L18 you call an undefined function.