Wordpress set default title when creating a new custom post - wordpress

I have a custom post type with just two (text)fields: an ISBN number and a youtube url by using 'supports' => array('title') when creating my custom post type.
The problem is, I don't need a title. So when I save my post, I made it so that the title becomes the ISBN number.
add_filter('wp_insert_post_data', array($this, 'change_title'), 99, 2);
function change_title($data, $postarr) {
if ($data['post_type'] == 'book_video') {
// If it is our form has not been submitted, so we dont want to do anything
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $data;
// Verify this came from the our screen and with proper authorization because save_post can be triggered at other times
if (!isset($_POST['wp_meta_box_nonce']))
return $data;
// Combine address with term
$title = $_POST['_bv_isbn'];
$data['post_title'] = $title;
}
return $data;
}
This works, but the problem is, when I save the post WITHOUT prefilling a title (anything at all) the post is not saved, the title change function is not called, and all of my fields are reset.
Is it possible to set a default value to the title and hide it ?

When you register your custom post type, you can set what it supports, including the title.
When you call register_post_type(), add another entry to $args called supports and set it's value to an array. You can then pass a list of elements you want that post type to support. The default is 'title' and 'editor', but there are a host of options to choose from.
For example:
<?php
register_post_type(
"myCustomPostType",
array(
'supports' : array(
'editor',
'author',
'custom-fields'
)
)
)
?>
So long as you miss out title then you won't have to define one for each post.
For more information, visit this page: http://codex.wordpress.org/Function_Reference/register_post_type#Arguments

Related

wp_link_query: Classic editor link popup adds custom CPT links again and again

When I integrate my CPT into the link search of the Classic Editor, it is at first displayed correctly.
But if there are more links in the list than can be displayed at the same time (overflow) and I then scroll up and down again, the list is updated by Wordpress via Ajax and my CPT links are appended again, so that the link list becomes longer and longer.
The default Wordpress links (post, page) on the other hand do not, even though my ID and the permalink in the $results array are unique.
There is nothing more than ID, title, permalink and info in the original $results array.
How can I prevent the appending?
add_filter('wp_link_query', array($this, 'wp_link_query'), 10, 2);
[...]
public function wp_link_query($results, $query) {
[...]
$results[] = array(
'ID' => $id,
'title' => $title,
'permalink' => $permalink,
'info' => $info
);
return $results;
}
The solution was to add the custom post type to the link query args first:
add_filter('wp_link_query_args', array($this, 'wp_link_query_args'), 10, 1);
[...]
public function wp_link_query_args($query) {
$query['post_type'][] = 'my_cpt';
return $query;
}
ยดยดยดยด
But you have to still use the 'wp_link_query' filter to add the "info" of the link popup table. Otherwise Wordpress outputs "Null" for the custom post type.

Call function in Wordpress after a custom post type updated/created with ACF

I want to call a function every time there is a change in a custom post type. Either publish, update or delete. In that function, I fetch all posts from that custom post type and create a json file that I export in a file.
add_action( 'transition_post_status', 'get_resources_data', 10, 3 );
function get_resources_data($new_status, $old_status, $post ) {
if ($post->post_type == 'resources') {
$args = array (
'post_type' => 'resources',
'post_status' => 'publish',
'posts_per_page' => -1
);
$queryResults = new WP_Query( $args );
if ( $queryResults->have_posts() ) {
//do my stuff here
//fetch acf fields with get_field()
//create json file
//export json file
}
}
}
The problem is that the custom post type has a few advanced custom fields which I include in the JSON file. However, when a new post is created, all ACF are null, while fields such as title and creation data are available. If I update a post, all ACF are fetched.
My impression is that transition_post_status is hooked before the ACF are stored in the Database. Should I use another action or do it with another way?
ACF actually supplies you with an action hook for exactly just that.
add_action('acf/save_post', 'get_resources_data'); - if you set the priority to below 10, the action is applied before the data is saved, if you emit the prio, or have it above 10, it is applied after the data is saved.
You can read more about the hook here : https://www.advancedcustomfields.com/resources/acf-save_post/

Creating page with custom url / meta tags using Wordpress REST API

I'm trying to create a custom page on my domain that has the url 'http://example.com/test/slug', however the slug does not seem to support slashes (the slug '/test/slug' turns into '/testslug'). Is it possible using the rest api to create a page on a custom url?
Also, I populate the 'meta' dictionary, however the page created does not contain a meta 'description' tag in the header. How can I correctly create custom meta tags?
import requests
url = 'http://example.com/wp-json/wp/v2/pages'
data = {'content': '<h2>test content</h2>',
'meta': {'description': 'this is a test meta field'},
'slug': 'test/slug',
'status': 'publish',
'title': 'test title'}
resp = requests.post(url, json=data, auth=('user','pass'), headers={'Content-Type':'application/json'})
the slug does not seem to support slashes (the slug '/test/slug' turns
into '/testslug').
Yes, because whether you use the REST API or the admin UI for creating Pages, the slug is limited to alphanumeric characters, plus dashes (-) and underscores (_). See https://developer.wordpress.org/rest-api/reference/pages/#schema-slug.
You can remove the limitation by adding remove_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 ); to the theme's functions.php file (or a custom plugin); however, visiting the page (URL) would by default throw a 404 (not found) error. There are ways to fix that, but in short, you should not remove the filter.
Is it possible using the rest api to create a page on a custom url?
No it's not, not by default.
However, if you want http://example.com/test/slug to serve/show a Page/Post/etc. be it created via the REST API or not, then you can use custom URL rewrite rules, e.g. via add_rewrite_rule().
the page created does not contain a meta 'description' tag in the
header. How can I correctly create custom meta tags?
You need to register the meta key, which in your case is description.
See
Working with registered meta in the REST API
Read and write a post meta field in post responses
And you can register it using the register_meta() function in wp-includes/meta.php.
Example for your description meta:
<?php
// The object type. For custom post types, this is 'post';
// for custom comment types, this is 'comment'. For user meta,
// this is 'user'.
$object_type = 'post'; // 'post' even for Pages
$args1 = array( // Validate and sanitize the meta value.
// Note: currently (4.7) one of 'string', 'boolean', 'integer',
// 'number' must be used as 'type'. The default is 'string'.
'type' => 'string',
// Shown in the schema for the meta key.
'description' => 'A meta key associated with a string meta value.',
// Return a single value of the type.
'single' => true,
// Show in the WP REST API response. Default: false.
'show_in_rest' => true,
);
register_meta( $object_type, 'description', $args1 );
To quickly test if the meta description was successfully registered and that it's being available from the REST API, perform a GET request to http://example.com/wp-json/wp/v2/pages/<id> where <id> is the Page ID.
First, make sure your Permalinks settings is "Post Name".
This can be configured under http://<yoursite.com>/wp-admin/options-permalink.php
I have studied "Custom Permalinks" plugin code to understand how to answer this question, it saves a metadata called "custom_permalink" and does heavy INNER JOINS to make WordPress core work with "fake" sub-slugs.
I came up with a different solution. The trick here is to create a fake parent page to serve as a base URL for children pages. I have written it in PHP, since I don't know Python.
<?php
require_once('helpers.php');
define('API_URL', 'http://temp.localhost');
# Let's get all pages in an array
$pages = curlGet(API_URL.'/wp-json/wp/v2/pages');
# Your usual $args
$args = array(
'title' => 'API TEST',
'status' => 'draft',
'content' => 'content',
'slug' => 'some/thing'
);
# We intercept it here, before sending to WordPress
$args = maybe_add_parent($args);
$response = curlPost( API_URL.'/wp-json/wp/v2/pages/', $args );
/**
* Receives an $args array that would be sent to WordPress API and checks if we need to add a parent page
*/
function maybe_add_parent(array $args) {
if (array_key_exists('slug', $args)) {
# Has parent?
if (strpos($args['slug'], '/') !== false) {
$parent = explode('/', $args['slug']);
# For simplicity sake let's do it parent/chidren slugs only
if (count($parent) !== 2) {
die('This script can only run parent/children slugs');
}
$slug = array_pop($parent);
# Here, we will check the parent to see if it exists.
$parent_id = slug_exists($parent[0]);
if ($parent_id === false) {
# If it does not, it will create it and return it's ID
$parent_id = create_parent($parent[0]);
}
# Add parent ID to $args.
$args['parent'] = $parent_id;
# Rename the slug
$args['slug'] = $slug;
}
}
return $args;
}
/**
* Checks if a given slug exists in $pages
*/
function slug_exists(string $slug) {
global $pages;
foreach ($pages as $page) {
# Checks if a "Parent" page with this slug exists
if ($page['slug'] == $slug && $page['parent'] == 0) {
return true;
}
}
return false;
}
/**
* Creates a parent page
*/
function create_parent(string $slug) {
$args = array(
'title' => $slug,
'status' => 'draft',
'content' => '',
'slug' => $slug
);
$response = json_decode(curlPost( API_URL.'/wp-json/wp/v2/pages/', $args ));
return $response->id;
}
The script does the following:
Send a GET request for all the pages on the website.
Intercepts an $args array that would be sent to the WordPress API.
Checks if this $args contains a slug in the format parent/child
If it does, check if parent page exists
If it doesn't, it will create this page as a draft and return it's ID
It the parent already exists, it will just return it's ID
With the Parent ID, it will modify $args adding parent key and return $args
When WordPress sees that that page has a parent, it will automatically add it's slug in the url, as in parent/child
It works:
To get the URL structure you want, the most straightforward way is to create a child page that references an already existing page as it's parent.
To amend your example above:
import requests
url = 'http://example.com/wp-json/wp/v2/pages'
parent_page = 43 # assuming that page with URL '/test' has id of 42
data = {'content': '<h2>test content</h2>',
'meta': {'description': 'this is a test meta field'},
'slug': 'slug',
'status': 'publish',
'title': 'test title'
'parent': parent_page} # <--
resp = requests.post(url, json=data, auth=('user','pass'), headers={'Content-Type':'application/json'})
Would give you a new page at example.com/test/slug
Reference to arguments for "Create a Page", (POST /wp/v2/pages) on WordPress rest API Handbook: https://developer.wordpress.org/rest-api/reference/pages/#create-a-page

Custom-Field option not found in custom post type WP 4.6.1

I have created a custom post type call 'Movie'.Now,I want to add custom meta field in this call Movie Reviews.I have following code for custom post type.
function Create_Movies_Posttype()
{
register_post_type('Movies',
array(
'labels'=>array('name'=>__('Movies'),'singular_name'=>__('Movie')),
'public'=>true,
'has_archive'=>true,
'rewrite'=>array('slug'=>'movies'),
'support'=>array('title','custom-fields','edit'),
)
);
}
add_action('init','Create_Movies_Posttype');
Added Meta Box
function adding_custom_meta_boxes( $post ) {
add_meta_box(
'my-meta-box',
__( 'My Meta Box' ),
'render_my_meta_box',
'post',
'normal',
'default'
);
}
add_action( 'add_meta_boxes_post', 'adding_custom_meta_boxes' );
Any one please help me with this custom field.
You need to use add_meta_boxes() action to register metaboxes for a post type.
add_meta_box() function to define the box, and save_post action to save it.
You'll find everything you need by reading example on Codex add_meta_boxes
You need also to add supports parameter to the register post type arguments and add custom-field in the array defining the supports for it, all the native supports can be found here

Woocommerce custom fields for shipping calculator

I'm building a custom shipping method for Woocommerce, and the one thing I'm totally hung up on is how to pass custom values to the calculate_shipping() function, either when it's being used on the Cart page or Checkout page.
I need to pass a handful of user-defined variables that will impact the quote -- ie "Is Residential Address", "Is Trade Show", etc etc.
calculate_shipping receives the $package array which contains a 'destination' array, but this only includes the standard add1, add2, city, state, zip, country info. I've added custom fields to the checkout page under both billing and shipping but I still can't figure out how to make these values accessible to the calculate_shipping function.
I've added a custom field like so:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['is_residential'] = array(
'label' => __('Residential Address?', 'woocommerce'),
'type' => 'checkbox',
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
And I see this field show up on the Shipping section of the checkout form. However, I'm not seeing how I can access it anywhere. Even doing a print_r($_POST) on the checkout page doesn't show this field as being part of the post data, even after I know the form has been updated and re-posted.
But most importantly, I need to add the contents of the submitted field into the $package object which Woocommerce passes to a shipping method's calculate_shipping() function.
I'm just really not sure where to even start with this.
You can't expect to add checkout fields and have them available at the cart page.
The correct way is to use cart packages.
Check function get_shipping_packages() from class-wc-cart.php
public function get_shipping_packages() {
// Packages array for storing 'carts'
$packages = array();
$packages[0]['contents'] = $this->get_cart(); // Items in the package
$packages[0]['contents_cost'] = 0; // Cost of items in the package, set below
$packages[0]['applied_coupons'] = $this->applied_coupons;
$packages[0]['destination']['country'] = WC()->customer->get_shipping_country();
$packages[0]['destination']['state'] = WC()->customer->get_shipping_state();
$packages[0]['destination']['postcode'] = WC()->customer->get_shipping_postcode();
$packages[0]['destination']['city'] = WC()->customer->get_shipping_city();
$packages[0]['destination']['address'] = WC()->customer->get_shipping_address();
$packages[0]['destination']['address_2'] = WC()->customer->get_shipping_address_2();
foreach ( $this->get_cart() as $item )
if ( $item['data']->needs_shipping() )
if ( isset( $item['line_total'] ) )
$packages[0]['contents_cost'] += $item['line_total'];
return apply_filters( 'woocommerce_cart_shipping_packages', $packages );
}
You gotta hook into woocommerce_cart_shipping_packages filter and add your fields there.
Most likely you will need to add them (your fields) at the shipping calculator and checkout pages.
Hope this helps.

Resources