WordPress publish_{$post_type} hook works only for posts and not for custom post types or pages - wordpress

I'm trying to send push notification when any of posts, custom post types or pages is published. I'm getting enabled post types from the plugin settings and adding action via foreach loop in my class __construct method. The problem is that it only works for posts and not for any of custom post types or pages. Here is my function and action:
foreach ((array)get_option('PushPostTypes') as $postType) {
add_action("publish_{$postType}", array($this, 'doNewPostPush'), 10, 2);
}
public function doNewPostPush($id, $post) {
$pushData = array(
'title' => $post->post_title,
'body' => strip_tags($post->post_content),
'data' => array(
'url' => trailingslashit(get_permalink($id)),
),
);
if (has_post_thumbnail($id)) {
$pushData['image'] = get_the_post_thumbnail_url($id);
}
$this->sendNotification($pushData);
}
get_option('PushPostTypes') is an array of post types that user choose, for example: array('post', 'page', 'custom_post');
Any idea why it only works for post and not for pages or custom post types?

Your code worked for me, assuming your get_option('PushPostTypes') is working as intended (Obviously I had to mock that).
Try a different approach that does not rely on get_option('PushPostTypes') to see if you get the same result;
add_action('transition_post_status', function ($new_status, $old_status, $post) {
if ($new_status !== 'publish') {
return;
}
// do something
}, 10, 3);
Try the 'transition_post_status' hook that works for all posts without specifically defining them. Put that somewhere just to see if it runs. Do whatever debugging statement that suits you. Then if that works, then move it into Class code and see if that works. I'm debugging by trying to isolate where the first thing goes wrong. Keeping it very simple to get it to work, then gradually adding complexity until it breaks.

Related

How can I create custom endpoint with post and get methods on wordpress api

I'm trying to make a custom endpoint, for example:
https://localhostname.com/wp-json/company_name/settings
Where I'll keep some settings like theme colors and other things, but it seems there are many ways to do that and I just want the simplest way. All the searching on the web is making me really confused.
So basically I want to make a POST request to the above URL like this:
{
"primary_color": "0xFFFFFFFF",
"secondary_color": "0xFFFFFF11"
}
and then get these same parameters in a GET request.
It's just that. No verification at all. Sorry if it's that simple, but I'm really having a hard time with this problem as I am not used to program with php at all.
To create a custom endpoint you will need to add below snippet to your function file:
add_action( 'init', 'setup_init' );
function setup_init() {
add_action( 'rest_api_init', 'custom_endpoint' );
function custom_endpoint() {
register_rest_route( 'company_name', '/settings', array(
'methods' => 'GET',
'callback' => 'custom_callback',
));
}
function custom_callback($request_data){
return 'hello world';
}
}
Let me know if any query and do accept the answer if it works :)

Wordpress Plugin: Show html only on standard page and not in admin area

I'm writing a plugin and I need to display a piece of text in the WP page, but not in the admin area. How can I do so?
I tried this in the construct:
add_action( 'init', array( $this, 'initPage' ) )
and then:
public function initPage() {
echo 'hello';
}
but the text is displayed also in the admin area. Is there a way to do this? It would be the opposite of the action admin_init I assume.
Proper way to handle it: is_admin()
http://codex.wordpress.org/Function_Reference/is_admin
if(is_admin()) { // do nothing } else {
// function you want to execute.
}
I solved this by adding it to a shortcode action. Like this:
add_shortcode( 'myPlugin', array( $this, 'shortcode' ) );
and:
public function shortcode( $atts ) {
return 'hello';
}
With the above code, 'hello' will only display on the front-end. Not sure if that's the cleaner way to do it, but does the job.
There is no "front-end-only" version of init, however you probably don't want to be doing any output at the init action anyway.
What exactly are you trying to do? Usually, you use an action hook for specific types of things, and causing output very early at something like "init" is rare and weird.

add_menu_page() add_submenu_page() | passing a $variable with called function

I have added a menu page on my WordPress backend with some submenu items.
A snippet of the code i use is:
// Add to admin_menu function
add_menu_page(__('New Menu'), __('New Menu Title'), 'edit_themes', 'new_menu_item', 'functiontocallonclick', '', 3.5);
// Add to secondlevel menu
add_submenu_page('new_menu_item', __('New |Sub Menu item'), __('New Menu Title item'), 'edit_themes', 'new_menu_sub_item', 'subfunctiontocallonclick',');
As you can see above it is calling the function functiontocallonclick when you go to the New menu item in the backend.
What i am wondering now:
I would like to pass a variable with the function.
functiontocallonclick($value);
Ofcourse it can't be done that way, so what is the good way?
I use this:
switch($_GET['page']){
case 'suppliers': $type='c';
break;
case 'contractors': $type='s';
break;
default: $type='';
break;
}
but I try to find some better solution.
This answer might seem late but I'll share how I work around this because it looks like quite a few people are looking for an answer to this question.
My answer is going to be passing variables to a nested function within a class-based context so if you're using functional programming then disregard the $this.
The Main hook action:
function mainSetup(){
add_action('admin_menu', array($this, 'mainMenuSetup'));
add_action('admin_menu', array($this, 'subMenuSetup'));
}
Menu Setup:
function mainMenuSetup(){
add_menu_page('DashBoard',
'DashBoard',
'manage_options',
'[yoursitesname]-admin-menu',
function(){ $this->pageSelect("admin"); },
'',
200
);
}
Within the example of the Main menu navigation option, we are passed a string in the nested function that will be passed as an argument to the method(function) 'pageSelect', but the string is hardcoded and can't be changed easily. We'll address this problem when setting up the submenu(s).
TODO: You should replace [yoursitename].
SubMenu Setup:
For the submenu let's say we want to make it easier to go back and add new submenus and change who has access to which submenus. For this, I'm going to make an associative array called 'subMenuObjects' where the array's keys are the submenu objects and their values are the page's permissions.
function subMenuSetup(){
$subMenuObjects = array(
'Settings' => 'manage_options',
'Services' => 'manage_options'
);
foreach ($subMenuObjects as $subMenu => $value) {
add_submenu_page('[yoursitesname]-admin-menu',
$subMenu . 'Page',
$subMenu,
$value,
'[yoursitesname]' . strtolower($subMenu) . '-menu',
function() use ($subMenu){ $this->pageSelect($subMenu); }
);
}
}
Here we use the 'use' to pass the $subMenu to the nested function.
Page select:
function pageSelect($page){
switch ($page) {
case 'admin':
echo '<div>Welcome to the Admin page</div>';
break;
case 'Settings':
echo '<div>Welcome to the Settings page</div>';
break;
case 'Services':
echo '<div>Welcome to the Service page</div>';
break;
default:
echo '<div>something happened, contact dev</div>';
break;
}
}
Yes, the way you're doing it is the way WordPress does it itself. To re-use admin screens, you have to pass some query var in the URL and then show/hide elements based on that.
You can also create invisible admin screens: How to enable additional page in WordPress custom plugin?. And this may be useful too: Redirect from add_menu_page

Wordpress rss feed as post type with image/permalink

I have a friend who writes to a couple of different blogs and wants to pull stories from one that isn't so popular, onto his main blog with an rss feed and display an image from it too (since rss feeds have images, sometimes).
Displaying the rss feeds shouldn't be too hard, it's making them a custom post type that seems more difficult to me.
If anyone has any ideas, shoot.
EDIT:-
Does anyone know how to get an external rss feed to appear as a custom post type in wordpress?
A simple way may be to use Wordpress' own fetch_feed function:
http://codex.wordpress.org/Function_Reference/fetch_feed
A quick example (assuming you've already set up your custom post type):
function import_feed_items()
{
$feed = fetch_feed('http://feeds.bbci.co.uk/news/uk/rss.xml');
if( !is_wp_error($feed) )
{
if( $last_import = get_option('last_import') )
{
$last_import_time = $last_import;
} else {
$last_import_time = false;
}
$items = $feed->get_items();
$latest_item_time = false;
foreach ( $items as $item )
{
$item_date = $item->get_date('Y-m-d H:i:s');
if( $last_import_time && ($last_import_time >= strtotime($item_date)) )
{
continue;
}
$post = array(
'post_content' => $item->get_content(),
'post_date' => $item_date,
'post_title' => $item->get_title(),
'post_status' => 'publish',
'post_type' => 'custom_post_type'
);
wp_insert_post($post);
if( strtotime($item_date) > $latest_item_time )
{
$latest_item_time = strtotime($item_date);
}
}
if( false !== $latest_item_time )
{
update_option('last_import', $latest_item_time);
}
}
else
{
echo $feed->get_error_message();
}
}
add_action('wp', 'import_feed_items');
If there is an image tag in the content you could use php's DomDocument class to grab the url and upload it to your server so you can set it as the featured image.
http://codex.wordpress.org/Function_Reference/wp_insert_attachment
http://codex.wordpress.org/Function_Reference/set_post_thumbnail
Edit
corrected the timestamp check. This updated example uses the 'wp' hook to run so you can see the results quicker. It would be preferable to set this as a cron task. See http://codex.wordpress.org/Function_Reference/wp_schedule_event
The Feed to Post plugin is the perfect solution for importing multiple RSS items into your WordPress blog, you can even store them as posts or custom post types.
http://www.wprssaggregator.com/extension/feed-to-post/
Unfortunately I don't know a way off hand, but have you looked at modifying a plugin? There are tons of content curation plugins around (feedwordpress, autoblog, etc.). You could probably find the wp_insert_post() line somewhere and modify it to include your custom post type/taxonomies.
EDIT
Jumped into the plugin (feedwordpress) myself, and all the insert_post stuff is in syndicatedpost.class.php - the main wp_insert_post() on line 1538
EDIT if you fancy a giggle while reading throught that plugin code, you'll find many an instance of the f word... haha
Hey why dont you try this http://wordpress.org/extend/plugins/display-latest-rss-feeds/
It would pull rss feeds from any account and display it to your blog. Unfortunately it wont display images just the rss feeds title and its permalink to the original blog but you can easily modify the source code if you want.

Silverstripe tumblr-like Post Types

I am trying to create a back-end interface for silverstripe that gives the CMS user the option to choose between a set of Post Types (like tumblr) in Silverstripe3. So they can choose to create a News Post, Video Post, Gallery Post, etc.
I initially started off giving all Posts the necessary fields for each Type and adding an enum field that allowed the user to choose the Post Type. I then used the forTemplate method to set the template dependent upon which Post Type was chosen.
class Post extends DataObject {
static $db = array(
'Title' => 'Varchar(255),
'Entry' => 'HTMLText',
'Type' => 'enum('Video, Photo, Gallery, Music')
);
static $many_many = array(
'Videos' => 'SiteVideo',
'Photos' => 'SitePhoto,
'Songs' => 'SiteMp3'
);
public function forTemplate() {
switch ($this->Type) {
case 'Video':
return $this->renderWith('VideoPost');
break;
case 'Photo':
return $this->renderWith('ImagePost');
break;
etc...
}
function getCMSFields($params=null) {
$fields = parent::getCMSFields($params);
...
$videosField = new GridField(
'Videos',
'Videos',
$this->Videos()->sort('SortOrder'),
$gridFieldConfig
);
$fields->addFieldToTab('Root.Videos', $photosField);
$photosField = new GridField(
'Photos',
'Photos',
$this->Photos()->sort('SortOrder'),
$gridFieldConfig
);
$fields->addFieldToTab('Root.Videos', $photosField);
return $fields;
}
}
I would rather the user be able to choose the Post Type in the backend and only the appropriate tabs show up. So if you choose Video, only the Video GridField tab would show up. If you choose Photo Type only the Photo's GridField would show.Then I would like to be able to call something like
public function PostList() {
Posts::get()
}
and be able to output all PostTypes sorted by date.
Does anyone know how this might be accomplished? Thanks.
Well the first part can be accomplished using javascript. Check out this tutorial and the docs let me know if you have questions on it.
The second part would be trickier but I think you could do something with the page controller. Include a method that outputs a different template based on the enum value but you would have to set links somewhere.
I managed this with DataObjectManager in 2.4.7 as I had numerous DataObjects and all were included in one page but I'm not sure if that is feasible in SS3.
return $this->renderWith(array('CustomTemplate'));
This line of code will output the page using a different template. You need to include it in a method and then call that method when the appropriate link is clicked.

Resources