WordPress Plugin to create a React Public page on activation - php

I'm building a WordPress plugin that creates an admin menu and stores the value in the WordPress backend and then shows this stored value on a Public page. But the code is not creating a Public page where I want to load a custom react page.
In the root directory, I have wp-react-kickoff.php file like this
<?php
/**
* Plugin Name: Batmobile Design
* Author: Batman
* Author URI:
* Version: 1.0.0
* Description: WordPress React KickOff.
* Text-Domain: wp-react-kickoff
*/
if( ! defined( 'ABSPATH' ) ) : exit(); endif; // No direct access allowed.
/**
* Define Plugins Contants
*/
define ( 'WPRK_PATH', trailingslashit( plugin_dir_path( __FILE__ ) ) );
define ( 'WPRK_URL', trailingslashit( plugins_url( '/', __FILE__ ) ) );
/**
* Loading Necessary Scripts
*/
add_action( 'admin_enqueue_scripts', 'sd_scripts' );
function sd_scripts() {
wp_enqueue_script( 'wp-react-kickoff', WPRK_URL . 'dist/bundle.js', [ 'jquery', 'wp-element' ], wp_rand(), true );
wp_localize_script( 'wp-react-kickoff', 'appLocalizer', [
'apiUrl' => home_url( '/wp-json' ),
'nonce' => wp_create_nonce( 'wp_rest' ),
] );
}
require_once WPRK_PATH . 'classes/class-create-admin-menu.php';
require_once WPRK_PATH . 'classes/class-create-settings-routes.php';
require_once WPRK_PATH . 'classes/class-public-page.php';
Then I have created a folder called classes where I have
class-create-admin-menu.php,
class-create-settings-routes.php,
class-public-page.php,
wprk-public-page-template.php.
The code specific to create Public page looks like this
<?php
/**
* This file will create Public Page
*/
function wprk_create_public_page() {
$page = [
'post_type' => 'Automatic page',
'post_title' => 'WP React KickOff Public Page',
'post_content' => 'asasasas',
'post_status' => 'publish',
'post_author' => 1,
];
$page_id = wp_insert_post( $page );
update_post_meta( $page_id, '_wp_page_template', 'wprk-public-page-template.php' );
}
register_activation_hook( __FILE__, 'wprk_create_public_page' );
And my wprk-public-page-template.php
<div id="wprk-public-app"></div>
<?php
wp_enqueue_script( 'wp-react-Kickoff', WPRK_URL . 'dist/bundle.js', [], wp_rand(), true );
wp_localize_script( 'wp-react-Kickoff', 'appLocalizer', [
'apiUrl' => home_url( '/wp-json' ),
'nonce' => wp_create_nonce( 'wp_rest' ),
] );
And In the ReactFolder, I have App.js, both Settings (This is for admin menu, it is working properly) and Public Page rendered like this
import React from 'react';
import PublicPage from './components/PublicPage';
import Settings from './components/Settings';
function App() {
return(
<React.Fragment>
<Settings />
<PublicPage />
</React.Fragment>
)
}
export default App;
And for testing, let the Public page, look like this
import axios from 'axios';
const apiUrl = appLocalizer.apiUrl;
const nonce = appLocalizer.nonce;
import React from 'react';
function PublicPage(props) {
return (
<div>
<h1>hello world asasa</h1>
</div>
);
}
export default PublicPage;
I'm quite new to programming. Could someone help me identify why the Public page is not getting created?
Please let me know if you need additional information to troubleshoot?

your post_type argument in your create page function isnt valid.
If you have a custom post type you'll want to use the slug, otherwise, in your case if i understand correctly you want to create a standard wordpress page which the post type is page.
function wprk_create_public_page() {
$page = [
'post_type' => 'page',
'post_title' => 'WP React KickOff Public Page',
'post_content' => 'asasasas',
'post_status' => 'publish',
'post_author' => 1,
];
$page_id = wp_insert_post( $page );
update_post_meta( $page_id, '_wp_page_template', 'wprk-public-page-template.php' );
}
register_activation_hook( __FILE__, 'wprk_create_public_page' );

Related

Custom WPBakery elements not displaying in WP admin

I'm creating custom elements for WPBakery.
I have a folder called vc-elements which contains two files:
hero.php
text-image.php
On the WordPress admin side, I want both elements to be visible. To do this, in functions.php I'm running:
add_action( 'vc_before_init', 'vc_before_init_actions' );
function vc_before_init_actions() {
// Link to VC elements's folder
if( function_exists('vc_set_shortcodes_templates_dir') ){
vc_set_shortcodes_templates_dir( get_template_directory() . 'vc-elements' );
}
}
But in the admin side, neither of the two blocks show?
Previously I had:
function vc_before_init_actions() {
require_once( get_template_directory().'/vc-elements/hero.php' );
}
Which showed the hero block in the admin. But when I added:
function vc_before_init_actions() {
require_once( get_template_directory().'/vc-elements/hero.php' );
require_once( get_template_directory().'/vc-elements/text-image.php' );
}
In the admin side, the hero element is replaced by the text image element - only one shows at one time. Why's this?
Are you building this with a parent or child theme? I'm not sure about your markup.
Usually, when I add a custom module I need to check if the plugin exists..
<?php
/**
* Adds new shortcode "myprefix_say_hello" and registers it to
* the Visual Composer plugin
*
*/
if ( ! class_exists( 'EZ_VC_Product_Widget' ) ) {
class EZ_VC_Product_Widget {
/**
* Main constructor
*/
public function __construct() {
// Registers the shortcode in WordPress
add_shortcode( 'ez_product', array( 'EZ_VC_Product_Widget', 'output' ) );
// Map shortcode to Visual Composer
if ( function_exists( 'vc_lean_map' ) ) {
vc_lean_map( 'ez_product', array( 'EZ_VC_Product_Widget',
'map' ) );
}
}
/**
* Shortcode output
*/
public static function output( $atts, $content = null ) {
// Extract shortcode attributes (based on the vc_lean_map function - see next function)
extract( vc_map_get_attributes( 'ez_product', $atts ) );
// Define output
$product = wc_get_product($id);
if ( $id && $product) {
global $post;
$post = $product->get_post_data();
setup_postdata( $post );
ob_start();
get_template_part('template-parts/product-module');
wp_reset_postdata();
return ob_get_clean();
}
else
return '';
}
/**
* Map shortcode to VC
*
* This is an array of all your settings which become the shortcode attributes ($atts)
* for the output. See the link below for a description of all available parameters.
*
* #since 1.0.0
* #link https://kb.wpbakery.com/docs/inner-api/vc_map/
*/
public static function map() {
return array(
'name' => esc_html__( 'EZ Product', 'shopkeeper' ),
'description' => esc_html__( 'Shortcode outputs a single product.', 'shopkeeper' ),
'base' => 'ez_product',
"icon" => get_stylesheet_directory_uri() . "/vc_extend/ez_shortcode_icon.png",
'params' => array(
array(
'type' => 'autocomplete',
'heading' => esc_html__( 'Select identificator', 'js_composer' ),
'param_name' => 'id',
'description' => esc_html__( 'Input product ID or product SKU or product title to see suggestions', 'js_composer' ),
),
array(
'type' => 'hidden',
// This will not show on render, but will be used when defining value for autocomplete
'param_name' => 'sku',
),
),
);
}
}
}
add_action('vc_before_init', function(){
new EZ_VC_Product_Widget;
});
/**
* #action wp_ajax_vc_get_autocomplete_suggestion - since 4.4 used to
hook ajax requests for autocomplete suggestions
*/
add_action( 'wp_ajax_vc_get_autocomplete_suggestion',
'ez_vc_get_autocomplete_suggestion' );
/**
* #since 4.4
*/
function ez_vc_get_autocomplete_suggestion() {
vc_user_access()->checkAdminNonce()->validateDie()->wpAny(
'edit_posts', 'edit_pages' )->validateDie();
$query = vc_post_param( 'query' );
$shortcode = wp_strip_all_tags( vc_post_param( 'shortcode' ) );
if ( $shortcode == 'ez_product') {
$tag = 'product';//wp_strip_all_tags( vc_post_param( 'shortcode'
)
);
$param_name = vc_post_param( 'param' );
vc_render_suggestion( $query, $tag, $param_name );
exit;
}
}

woocommerce edit-account shortcode

I saw in this question that is possible create a shortcode from my-orders page, I am trying create something similar to display the edit account page via shortcodes.
Reference: in woocommerce, is there a shortcode/page to view all orders?
function shortcode_my_orders( $atts ) {
extract( shortcode_atts( array(
'order_count' => -1
), $atts ) );
ob_start();
wc_get_template( 'myaccount/my-orders.php', array(
'current_user' => get_user_by( 'id', get_current_user_id() ),
'order_count' => $order_count
) );
return ob_get_clean();
}
add_shortcode('my_orders', 'shortcode_my_orders');
I created this shortcode to add the HTML contents of the Edit Account page in another page. I believe that's what you are asking for.
// Paste this in the function.php file of your active child theme or theme.
function wc_customer_edit_account_html_shortcode( $atts ) {
// Attributes
extract( shortcode_atts( array(
'text' => 'Edit Account' ), $atts ) );
return wc_get_template_html( 'myaccount/form-edit-account.php', array( 'user' => get_user_by( 'id', get_current_user_id() ) ) );;
}
add_shortcode( 'wc_customer_edit_account_html', 'wc_customer_edit_account_html_shortcode' );
You can also put this in a New Snippet in the Snippets plugin instead of editing the functions.php page.
You can display the edit account form, wherever you want, with this code:
function clket_edit_account_form(){
ob_start();
wc_get_template( 'myaccount/form-edit-account.php', array( 'user' => get_user_by( 'id', get_current_user_id() ) ) );
return ob_get_clean();
}
add_shortcode('clket_edit_account', 'clket_edit_account_form');
Shortcode: [clket_edit_account]
Ref: https://woocommerce.wp-a2z.org/oik_api/wc_shortcode_my_accountedit_account/

Error in adding extra meta box for woocommerce

I'm adding extra meta boxes to be called inside tabs in front end. This is added inside add new product page.But it gives error saying: Warning:
call_user_func() expects parameter 1 to be a valid callback, class
'WC_Meta_Box_Product_Features_Advantages' not found in
C:\wamp\www\mysite\wp-admin\includes\template.php on line 1048
screenshot:
I simply followed the way short description meta box added. Thus, I created a class file in this location:
C:\wamp\www\mysite\wp-content\plugins\woocommerce\includes\admin\meta-boxes\class-wc-meta-box-features-advantages-.php
and the content looks like:
<?php
/**
* Product Features Advantages
*
* Replaces the standard excerpt box.
*
* #author WooThemes
* #category Admin
* #package WooCommerce/Admin/Meta Boxes
* #version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* WC_Meta_Box_Product_Features_Advantages Class.
*/
class WC_Meta_Box_Product_Features_Advantages {
/**
* Output the metabox.
*
* #param WP_Post $post
*/
public static function output( $post ) {
$settings = array(
'textarea_name' => 'features_advantages',
'quicktags' => array( 'buttons' => 'em,strong,link' ),
'tinymce' => array(
'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
'theme_advanced_buttons2' => '',
),
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
);
wp_editor( htmlspecialchars_decode( $post->post_excerpt ), 'features_advantages', apply_filters( 'woocommerce_product_features_advantages_editor_settings', $settings ) );
}
}
Also added few more lines here: C:\wamp\www\mysite\wp-content\plugins\woocommerce\includes\admin\class-wc-admin-meta-boxes.php inside add_meta_boxes() function.
add_meta_box( 'features_advantages', __( 'Product Features and Advantages', 'woocommerce' ), 'WC_Meta_Box_Product_Features_Advantages::output', 'product', 'normal' );
and this line inside remove_meta_boxes()
remove_meta_box( 'features_advantages', 'product', 'normal' );
you should add in functions.php file not in plugin folder
add this code in your current active theme functions.php:
add_action( 'add_meta_boxes', 'product_details_add' );
add_action( 'save_post', 'product_details_save' );
function product_details_add() {
add_meta_box( 'product_details', 'Product Details', 'product_details_call', 'product', 'normal', 'high' );
}
function product_details_call( $post ) {
// Use nonce for verification
wp_nonce_field( plugin_basename( __FILE__ ), 'product_details_noncename' );
$field_value = get_post_meta( $post->ID, 'product_details_meta', false );
wp_editor( $field_value[0], 'product_details_meta' );
}

How to add multiple featured images without a plugin?

This other Stack Overflow question is exactly what I need, but the answer on it is a link that is 5+ years outdated.
It tells me to change the following code:
public function enqueue_admin_scripts() {
wp_enqueue_script("featured-image-custom", plugins_url(basename(dirname(__FILE__)) . '/js/multi-post-thumbnails-admin.js'), array('jquery'));
}
to this:
public function enqueue_admin_scripts() {
$template_url = get_bloginfo('template_url') . '/js/multi-post-thumbnails-admin.js';
wp_enqueue_script("featured-image-custom", $template_url, array('jquery'));
}
but the updated plugin now has this instead:
public function enqueue_admin_scripts( $hook ) {
global $wp_version, $post_ID;
// only load on select pages
if ( ! in_array( $hook, array( 'post-new.php', 'post.php', 'media-upload-popup' ) ) )
return;
if (version_compare($wp_version, '3.5', '<')) {
add_thickbox();
wp_enqueue_script( "mpt-featured-image", $this->plugins_url( 'js/multi-post-thumbnails-admin.js', __FILE__ ), array( 'jquery', 'media-upload' ) );
} else { // 3.5+ media modal
wp_enqueue_media( array( 'post' => ( $post_ID ? $post_ID : null ) ) );
wp_enqueue_script( "mpt-featured-image", $this->plugins_url( 'js/multi-post-thumbnails-admin.js', __FILE__ ), array( 'jquery', 'set-post-thumbnail' ) );
wp_enqueue_script( "mpt-featured-image-modal", $this->plugins_url( 'js/media-modal.js', __FILE__ ), array( 'jquery', 'media-models' ) );
}
wp_enqueue_style( "mpt-admin-css", $this->plugins_url( 'css/multi-post-thumbnails-admin.css', __FILE__ ) );
}
I've tried leaving it as is, changing all of them like the blog link says, and adding the $template_url variable every time is says $this. In the back end of WordPress, I see the 2nd featured image, but the only thing it does is add a number sign (#) to the editor's url.
Here's also my code added to the functions.php file:
// Load external file to add support for MultiPostThumbnails. Allows you to set more than one "feature image" per post.
require_once('library/multi-post-thumbnails.php');
// Define additional "post thumbnails". Relies on MultiPostThumbnails to work
if (class_exists('MultiPostThumbnails')) {
new MultiPostThumbnails(array(
'label' => '2nd Feature Image',
'id' => 'feature-image-2',
'post_type' => 'page'
)
);
new MultiPostThumbnails(array(
'label' => '3rd Feature Image',
'id' => 'feature-image-3',
'post_type' => 'home'
)
);
};
Please and thank you for your time.

How to make output of a select list be dependant on parent list?

I have two arrays that have a parent category and sub category each appear in a select list, how do I make the sub category show items only from its parent category?
<?php $carMakes = array(
'show_option_all' => '',
'show_option_none' => ('All Makes'),
'orderby' => 'ID',
'order' => 'ASC',
'show_count' => 0,
'hide_empty' => 1,
'child_of' => 25,
'exclude' => 0,
'echo' => 1,
'selected' => 0,
'hierarchical' => 0,
'name' => 'cat',
'id' => '',
'class' => 'postform',
'depth' => 0,
'tab_index' => 0,
'taxonomy' => 'category',
'hide_if_empty' => false
); ?>
<?php $carModels = array(
'name' => 'subcat',
'hierarchical' => 1,
'parent' => get_cat_id('model'),
'show_option_none' => ('All Models'),
'hide_empty' => 0 );
?>
<?php wp_dropdown_categories($carMakes); ?>
<?php wp_dropdown_categories($carModels); ?>
need to only show car models that belong to car makes for example
Make=Toyota Model=Supra
Model=Corolla
Model=Tundra
Here is an example of the category structure
Make (parent category)
-Toyota
-Nissan
-Mazda
-Ford
Model (parent category)
-Supra
-Skyline
-Mustang
-Rx7
-Corolla
Always wanted to do an exercise on chained selections using Ajax, so, here we go ;)
This is a full plugin and should be installed in wp-content/plugins/your-plugin-name folder. Consists of three files, the plugin itself, the Javascript file and the Ajax loader image.
Install the plugin and activate, and insert the following in some theme template file:
<?php
if( class_exists( 'BRSFL_Chained_Selection' ) ) {
// Parameters: ( $cat_id, $dropdown_text )
BRSFL_Chained_Selection::print_cats( 1, 'All Makes' );
}
?>
Also, adjust the two calls to wp_dropdown_categories as desired. Check the code comments for details.
The sub-categories dropdown is modified in response to changes in the categories dropdown:
chained-categories.php
<?php
/**
* Plugin Name: Chained Categories
* Plugin URI: http://stackoverflow.com/q/15748968/1287812
* Description: Demonstration of chained categories with Ajax.
* Plugin structure based on Plugin Class Demo, by Thomas Scholz.
* Use the dropdowns in the theme with this PHP method call: BRSFL_Chained_Selection::print_cats();
* Author: Rodolfo Buaiz
* Author URI: http://wordpress.stackexchange.com/users/12615/brasofilo
*/
add_action(
'plugins_loaded',
array ( BRSFL_Chained_Selection::get_instance(), 'plugin_setup' )
);
class BRSFL_Chained_Selection
{
/**
* Plugin instance.
*
* #see get_instance()
* #type object
*/
protected static $instance = NULL;
/**
* URL to this plugin's directory.
*
* #type string
*/
public $plugin_url = '';
/**
* Path to this plugin's directory.
*
* #type string
*/
public $plugin_path = '';
/**
* Access this plugin’s working instance
*
* #wp-hook plugins_loaded
* #since 2012.09.13
* #return object of this class
*/
public static function get_instance()
{
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
/**
* Used for regular plugin work.
*
* #wp-hook plugins_loaded
* #since 2012.09.10
* #return void
*/
public function plugin_setup()
{
$this->plugin_url = plugins_url( '/', __FILE__ );
$this->plugin_path = plugin_dir_path( __FILE__ );
$this->load_language( 'chainedselections' );
add_action( 'wp_enqueue_scripts', array( $this, 'script_enqueuer' ) );
add_action( 'wp_ajax_custom_query', array( $this, 'custom_query' ) );
add_action( 'wp_ajax_nopriv_custom_query', array( $this, 'custom_query' ) );
}
/**
* Constructor. Intentionally left empty and public.
*
* #see plugin_setup()
* #since 2012.09.12
*/
public function __construct() {}
/**
* Enqueue frontend scripts
*/
public function script_enqueuer()
{
wp_register_script(
'ajax-quote'
, plugin_dir_url( __FILE__ ) . '/ajax.js'
, array( 'jquery' )
);
wp_enqueue_script( 'ajax-quote' );
wp_localize_script(
'ajax-quote'
, 'wp_ajax'
, array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
, 'ajaxnonce' => wp_create_nonce( 'ajax_chained_selection_validate' )
, 'icon' => plugin_dir_url( __FILE__ ) . '/ajax-loader.gif'
)
);
}
/**
* Ajax create sub-categories dropdown
*/
public function custom_query()
{
// Security
check_ajax_referer( 'ajax_chained_selection_validate', 'security' );
// Check if jQuery posted the data
if( !isset( $_POST[ 'chained_subcat_id' ] ) )
return false;
// Adjust parameters
$carMakes = array(
'show_option_all' => '',
'show_option_none' => 'All ' . $_POST[ 'chained_subcat_name' ],
'orderby' => 'ID',
'order' => 'ASC',
'show_count' => 0,
'hide_empty' => 0,
'exclude' => 0,
'echo' => 1,
'selected' => 0,
'child_of' => $_POST[ 'chained_subcat_id' ],
'hierarchical' => 1,
'name' => 'chained-subcontainer',
'id' => '',
'class' => 'postform',
'depth' => 1,
'tab_index' => 0,
'taxonomy' => 'category',
'hide_if_empty' => false
);
// Print sub-categories
wp_dropdown_categories( $carMakes );
exit();
}
/**
* Loads translation file.
*
* Accessible to other classes to load different language files (admin and
* front-end for example).
*
* #wp-hook init
* #param string $domain
* #since 2012.09.11
* #return void
*/
public function load_language( $domain )
{
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
// Load translation from wp-content/languages if exist
load_textdomain(
$domain, WP_LANG_DIR . $domain . '-' . $locale . '.mo'
);
// Load regular plugin translation
load_plugin_textdomain(
$domain,
FALSE,
$this->plugin_path . '/languages'
);
}
/**
* Print the dropdown in the frontend
*/
public static function print_cats( $cat_id, $dropdown_text )
{
// Adjust parameters
$carMakes = array(
'show_option_all' => '',
'show_option_none' => $dropdown_text,
'orderby' => 'ID',
'order' => 'ASC',
'show_count' => 0,
'hide_empty' => 0,
'exclude' => 0,
'echo' => 1,
'selected' => 0,
'child_of' => $cat_id,
'hierarchical' => 1,
'name' => 'chained-categories',
'id' => '',
'class' => 'postform',
'depth' => 1,
'tab_index' => 0,
'taxonomy' => 'category',
'hide_if_empty' => false
);
// Print categories
wp_dropdown_categories( $carMakes );
// Empty dropdown for sub-categories
echo '<div id="chained-subcontainer">
<select name="chained-subcategories" id="chained-subcategories">
<option value="">- Select a category first -</option>
</select>
</div>';
}
}
ajax.js
jQuery( document ).ready( function( $ )
{
var data = {
action: 'custom_query',
security: wp_ajax.ajaxnonce
};
$( "#chained-categories" ).on( "change", function( e )
{
// Add specific data to the variable, used to query the sub-categories
data[ 'chained_subcat_id' ] = $( this ).val();
data[ 'chained_subcat_name' ] = $(
'#chained-categories option[value='
+ $( this ).val()
+ ']'
).text();
// A sub-category was selected
if( $( this ).val() > 0 )
{
// Ajax loader icon
$( '#chained-subcontainer' ).html( '<img src="' + wp_ajax.icon + '">' );
// Ajax call
$.post(
wp_ajax.ajaxurl,
data,
// No error checking is being done with the response
function( response )
{
$( '#chained-subcontainer' ).html( response );
}
);
}
// No selection, show default
else
{
$( '#chained-subcontainer' ).html( '<select name="chained-subcategories" id="chained-subcategories"><option value="">- Select a category first -</option></select>' );
}
});
} );
ajax-loader.gif
Why not use objects?
You need a factory to make cars.
a great reference: http://sourcemaking.com/creational_patterns
I also like to think about keep objects small, simple, and to do as little as possible. Break functions down to simple concepts like "make" and "show". That makes them interchangable and extensible. You will eventually be able to just ask for $this->model->
I would approach like this:
1 object to organize the data //model
another to build your rows//controller
another to display //view
To start looking at it like that, write some functions first to gain an understanding of what you are wanting to know.
foreach (make)->show(models);
You may discover you need to query the data differently... In other words, ask the db a more specific question up front rather than filter it after you've received it. Maybe filtering now seems quicker, but how many other questions and filtering will you have to do later?
One more comment: php is more controllerish and javascript feels more viewish. I say solve the problems in their most appropriate and simplest context- stick with php on this issue.
The only way to do this without AJAX is to get a list of all your "Make" categories, then generate a dropdown for each "Model" of each "Make" using wp_dropdown_categories() with the child_of parameter. Hide all the "Make" dropdowns upon page load, attach a change event handler to the "Make" dropdown and when it's called, show the appropriate "Model" dropdown while hiding all the rest. The showing/hiding can be done with jQuery or pure JS. Each "Model" dropdown will have to have a unique ID that can be used to identify which "Make" it belongs to.

Categories