I'm trying to learn something about WordPress plug-in development. Here is my first attemp to write something. This should create an input field on "page" pages to store a custom value.
This is the code I written, but something doesn't work. I can't save my data.
<?php
/*
Plugin Name: nw_Page_Gallery
*/
class nw_Page_Gallery {
public function __construct(){
$this->add_meta_boxes();
}
public function add_meta_boxes(){
add_action("add_meta_boxes", array($this, "add_meta_box_images"));
}
public function add_meta_box_images(){
add_meta_box("nw_page_image", "Sfondo pagina", array($this, "add_image_box"), "page");
}
public function add_image_box($post){
$back_url = get_post_meta($post->ID, 'nw_page_image', true);
echo "Il valore รจ".$back_url;
?>
<label>Lenght:</label>
<input type="text" class="widefat" name="nw_page_image" id="nw_page_image" value="<?php echo $back_url; ?>" />
<?php
add_action("save_post", function($id){
if(isset($_POST['nw_page_image'])){
update_post_meta(
$id,
'nw_page_image',
strip_tags($_POST['nw_page_image'])
);
}
});
}
}
add_action("admin_init", function(){
$PG = new nw_Page_Gallery();
});
Can someone tells me what is wrong?
You are doing your add_action("save_post", in the last place it should be...
That belongs to the __construct, or as you're doing:
public function add_meta_boxes(){
add_action("add_meta_boxes", array($this, "add_meta_box_images"));
add_action("save_post", function($id){
if(isset($_POST['nw_page_image'])){
update_post_meta(
$id,
'nw_page_image',
strip_tags($_POST['nw_page_image'])
);
}
});
}
Note that you are hooking into save_post without checking for a bunch of things (if it is revision, if doing autosave) and more problematic, without security checks: wp_nonce_field.
You can find plenty of good examples at WordPress Answers, check this search query.
Related
I have created a CPT called 'encyclopedia' in WordPress. I am then creating a couple of Meta Fields inside that, just some simple Text Fields, but they are not saving at the moment and I cannot figure out why. Can someone help?
/*
=========================================================================
Custom Meta Fields - English version
=========================================================================
*/
function custom_meta_box_markup()
{
wp_nonce_field(basename(__FILE__), "meta-box-nonce");
?>
<div>
<label for="english_version">Description</label>
<input name="english_version" type="text" value="<?php echo get_post_meta($object->ID, "english_version", true); ?>">
</div>
<?php }
function add_custom_meta_box()
{
add_meta_box("english_version", "English Version", "custom_meta_box_markup", "encyclopedia", "advanced", "high", null);
//add_meta_box("german-version", "German Version", "custom_meta_box_markup", "encyclopedia", "advanced", "high", null);
}
add_action("add_meta_boxes", "add_custom_meta_box");
function save_custom_meta_box($post_id, $post, $update)
{
if (!isset($_POST["meta-box-nonce"]) || !wp_verify_nonce($_POST["meta-box-nonce"], basename(__FILE__))){
return $post_id;
}
if(!current_user_can("edit_post", $post_id)){
return $post_id;
}
if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE){
return $post_id;
}
$slug = "post";
if($slug != $post->post_type){
return $post_id;
}
$meta_box_text_value = "";
if(isset($_POST["english_version"]))
{
$meta_box_text_value = $_POST["english_version"];
}
update_post_meta($post_id, "english_version", $meta_box_text_value);
}
add_action("save_post_encyclopedia", "save_custom_meta_box", 10, 3);
The relevant code is above and I currently have it stored in the functions.php file of my child theme.
Thanks
As per my comment on your question, after fixing the post slug, you still have something wrong on the code.
On your meta box output function custom_meta_box_markup, you are using get_post_meta($object->ID, "english_version", true) without defining $object.
I have tested your code and your data is being saved in DB. But as $object->ID is returning nothing, it's not showing anything on the input textfield. custom_meta_box_markup receives a $post object, which you have missed. Update your code like this:
function custom_meta_box_markup($post) {
wp_nonce_field(basename(__FILE__), "meta-box-nonce");
?>
<div>
<label for="english_version">Description</label>
<input name="english_version" type="text" value="<?php echo get_post_meta($post->ID, "english_version", true); ?>">
</div>
<?php }
I have an function action hook which collects subscriptions from our database. I want to use this so that I can display the subscriptions on the page, but I also want to use this function in another function that calculates the new subscription price. Is this possible?
My code looks somewhat like this
add_action( 'wp_ajax_get_get_subs_with_type', 'get_subs_with_type' );
add_action( 'wp_ajax_nopriv_get_get_subs_with_type', 'get_subs_with_type' );
function get_subs_with_type($sub_type) {
$subs = //get alot of info from database......
echo $subs;
}
But I also want to use this function with a return statement instead of echo to be used in another function.
functon calc_subs(){
$subs = get_subs_with_type();
return $subs[1]->price + 1;
}
So can I use a function tied to an action hook as a 'normal' function as well? Or what should I do?
EDIT:
If there is no good way of doing this, I made a little hacky solution:
add_action( 'wp_ajax_get_get_subs_with_type', 'get_subs_with_type' );
add_action( 'wp_ajax_nopriv_get_get_subs_with_type', 'get_subs_with_type' );
function get_subs_with_type($sub_type) {
$subs = get_sub_from_db()
echo $subs;
}
function get_sub_from_db() {
$subs = //get alot of info from database......
return $subs;
}
Now I can use get_sub_from_db() in my other function as well.
functon calc_subs(){
$subs = get_sub_from_db();
return $subs[1]->price + 1;
}
What do you think of this?
You can for example do something like:
/**
* Returns bla bla bla
* #return array
*/
function get_subs_with_type($sub_type) {
$subs = //get alot of info from database......
return $subs;
}
add_action( 'wp_ajax_get_get_subs_with_type', function () {
echo get_subs_with_type();
});
but remember that while using anonymous function you will not be able to remove this action with remove_action.
The solution you proposed, by creating two different function, one returning the database call & the other calling the first one looks quite good.
Don't forget to add a wp_die(); function after you echoed all this information to the ajax handler. This is required to terminate any ajax call immediately and return a proper response.
add_action('wp_ajax_ybr_client_results', 'ybr_client_results');
add_action( 'wp_ajax_nopriv_ybr_client_results', 'ybr_client_results' );
function ybr_client_results() {
$client_details = $_POST[ 'client_details' ];
return $client_details;
die();
}
echo ybr_client_results();
it returns value with 0. how to fix it.
You can try the below following snippet to fetech data from database and encode it by using json_encode() and then call wp_die()
add_action('wp_ajax_ybr_client_results', 'ybr_client_results');
add_action( 'wp_ajax_nopriv_ybr_client_results', 'ybr_client_results' );
function ybr_client_results() {
$client_details = $_POST[ 'client_details' ];
$result = getPosts();
echo json_encode($result, true);
wp_die();
}
You've correctly registered an AJAX callback; the code will execute when the AJAX action is triggered. The function shouldn't be echoed.
There are a couple of issues with the callback itself:
It's returning a variable rather than generating output
There's a return statement above die() so that line is never reached
Corrected version:
function ybr_client_results() {
/**
* I've left this unaltered for the sake of answering the question at hand.
*
* Don't forget to check the value exists and sanitize it correctly.
*/
$client_details = $_POST['client_details'];
// This AJAX callback needs to output something, not return.
echo $client_details;
// As another user mentioned, there's a WP specific die function.
wp_die();
}
add_action( 'wp_ajax_ybr_client_results', 'ybr_client_results' );
add_action( 'wp_ajax_nopriv_ybr_client_results', 'ybr_client_results' );
Documentation: https://codex.wordpress.org/AJAX_in_Plugins
How can I call specific function in plugin in admin page.
I am submitting a form in WordPress plugin. On submitting I want to check validity of key which is entered in the form. I have a function which checkes the validity of the key. I want to call that function from the function of the form.
I have tried few things but it gives me error of
Using $this when not in object context
Here is my code
class WP_Cms_Plugin{
function __construct() {
add_action( 'admin_menu', array( $this, 'cms_options_panel' ));
}
function cms_options_panel() {
add_menu_page('CMS', 'Cms', 'manage_options', 'cms-dashboard', array(__CLASS__,'cms_setting_form'), 'dashicons-building');
}
function cms_setting_form()
{
if(isset($_POST['btn_submit']))
{
$secret_key = $_POST['project_secret_key'];
if($secret_key=='' || empty($secret_key))
{
$error['project_secret_key'] = 'Please enter Secret Key.';
}
if(empty($error)){
call to cms_check_key();
echo "Key validated successfully";
}
else
{
echo "Please use proper Key";
}
}
?>
<form method="post">
<div>Secret Key</div>
<input type="text" name="project_secret_key" value="<?php echo esc_attr( get_option('cms_secret_key') ); ?>" required/>
<?php submit_button('Submit','primary','btn_submit'); ?>
</form>
<?php
}
function cms_check_key($secret_key)
{
code to check validity
}
}
$cmsservice = new WP_Cms_Plugin();
The issue is your callable specifies using the WP_Cms_Plugin class and not an instance of it (object).
Either change your cms_options_panel function to:
add_menu_page('CMS', 'Cms', 'manage_options', 'cms-dashboard', array($this,'cms_setting_form'), 'dashicons-building');
(replace __CLASS__ with $this)
Or try a static function
static function cms_check_key($secret_key)
and then call WP_Cms_Plugin::cms_check_key($secret_key) from the form.
PHP Static Keyword
I have created a wordpress plugin that has a filter on the_content, looking for a specific tag then outputting the plugin content in place of that tag.
I would now like to use rewrite rules to call the plugin and output the data within the template, but I'm not finding much help.
Can someone provide an example, or some guidance on how to add a rewrite rule using the built in wp methods and calling my methods in the plugin which outputs some content.
Ideally, I would like shop/ to be matched and then pass everything after shop to my dispatch method on my plugin so that I can have shop/category/shirts or shop/product/the-cool-shirt. My dispatch method would handle breaking apart the rest of the url and calling methods accordingly.
This can get rather interesting. I had to do this for a plugin at one point, I don't have it in front of me, so this it out of memory, but the general idea should be correct.
<?php
add_action('init', 'rewrite_rules');
function rewrite_rules() {
global $wp, $wp_rewrite;
$wp_rewrite->add_rule('(widget1|widget2|widget3)/([a-zA-Z0-9_-]{3,50})$', 'index.php?pagename=listing&category=$matches[1]&subcategory=$matches[2]', 'top' );
$wp->add_query_var( 'category' );
$wp->add_query_var( 'subcategory' );
$wp_rewrite->flush_rules();
}
?>
Using regular expressions is a monumental task in itself, I believe I used this site: http://tools.netshiftmedia.com/regexlibrary/ for help.
I also used FakePage plugin to actually display my custom "dynamic" pages, as I called them, but I suppose everything in WP is technically dynamic.
http://scott.sherrillmix.com/blog/blogger/creating-a-better-fake-post-with-a-wordpress-plugin/
Let me know if you need more help.
I did something very similar not long ago, and I did it by cheating.
If you find the built in rewrite rules too complicated or unable to do the job, you may find it easier to catch the request and filter the results. A simplified version:
add_action('parse_request', 'my_parse_request');
function my_parse_request (&$wp) {
$path = $wp->request;
$groups = array();
if (preg_match("%shop/product/([a-zA-Z0-9-]+)%", $path, $groups)) {
$code = $groups[1];
$product = get_product($code); // your own code here
if (isset($product)) {
add_filter('the_posts', 'my_product_filter_posts');
}
}
}
function my_product_filter_posts ($posts) {
ob_start();
echo "stuff goes here"; // your body here
$content = ob_get_contents();
ob_end_clean();
return array(new DummyResult(0, "Product name", $content));
}
To explain:
The action on parse_request is called before the database lookup. Based on the URL, it installs the other actions and filters.
The filter on posts replaces the results of the database lookup with fake results.
DummyResult is a simple class that has the same fields as a post, or just enough of them to get away with it:
class DummyResult {
public $ID;
public $post_title;
public $post_content;
public $post_author;
public $comment_status = "closed";
public $post_status = "publish";
public $ping_status = "closed";
public $post_type = "page";
public $post_date = "";
function __construct ($ID, $title, $content) {
$this->ID = $ID;
$this->post_title = $title;
$this->post_content = $content;
$this->post_author = get_default_author(); // implement this function
}
}
There's a lot of homework left for the reader in the above, but it's an ugly, working approach. You'll probably want to add a filter for template_redirect, to replace the normal page template with a product-specific one. And you may need to adjust the URL regex if you want pretty permalinks.