I want to get the permalinks of all published pages and export it to an excel file.
What is the best solution?
Should I go to wp-admin panel and copy-paste the permalinks from the on Page editor?
Can I get the export data using a mysql query?
It is possible but very difficult to do via a SQL query, because WordPress allows you to change your Permalink structure - so the SQL query would need to regard all permalink options to build the correct permalink when the query is executed.
And I guess you are looking for a way that does not require you to copy paste links from the admin page ;-)
By far the best and easiest thing to do is write a small script that runs the export for you within WordPress and uses the functions get_pages and get_permalink:
// Get a list of all published pages from WordPress.
$pages = get_pages( 'post_status=publish' );
// Loop through all pages and fetch the permalink for each page.
foreach ( $pages as $page ) { //fixed this too
$permalink = get_permalink( $page->ID );
// Do something with the permalink now...
}
Note: This code will only run inside WordPress, i.e. as as Plugin or inside a Theme. Also how to do the excel export is beyond the scope of my answer...
Personally I'd create a WordPress plugin (there are many guides out there on how this works, like this one).
In the plugin you could simply check for a URL param, and if this param is present then export the data. Additionally I would check if the user that requests the export has admin permissions before exporting the data.
A bit like this:
/**
* The WordPress plugin header...
*/
$allowed = false;
$requested = false;
// Check if the current user has admin capabilies.
if ( current_user_can( 'manage_options' ) ) { $allowed = true; }
// Check if the user requested the export.
// i.e. by calling URL http://yoursite.com?export_permalinks=1
if ( 1 == $_GET['export_permalinks'] ) { $requested = true; }
if ( $requested && $allowed ) {
// 1. Get a list of all published pages from WordPress.
$pages = get_pages( 'post_status=publish' );
// 2. Build the export data.
$export = array();
foreach ( $pages as $page ) {
$permalink = get_permalink( $page->ID );
$export[] = array( $page->ID, $permalink );
}
// 3. Export the data (I just var_dump it as example).
var_dump( $export );
// We're done, so don't execute anything else.
exit;
}
Please note that this code should only explain my suggested workflow. It does not use best practices and I don't recommend to use it like this on a live site
Related
Currently, I have my permalink structure set up such as https://example.com/blog/%postname%/ which makes it so that whenever a blog post is loaded, the URL shows /blog/. I would also like to add the subdirectory /try/ for specific pages. I have tried to use a plugin to add categories to pages so I can create a category and add it that way, but it seems that this is not possible because the "Custom Structure" is already set as noted above.
Does anyone know of a way to add a subdirectory /try/ to specific pages for a WordPress website so the URL for certain pages would be such as https://example.com/try/page-title
Thanks.
First we have to add rewrite_rule
add_rewrite_rule(
'^try/([^/]+)/?',
'index.php?name=$matches[1]',
'top'
);
Then we need to use the post_link filter to change the link format for certain posts
add_filter( 'post_link', 'custom_post_permalink', 10, 4 );
function custom_post_permalink( $link, $post = 0 ) {
$post_cur_id = $post->ID;
$post_cur_slug = $post->post_name;
//array of post_ids with try in permalink
$try_array = array(1,7,22,78);
if(in_array($post_cur_id, $try_array)) {
$slug = '/try/' . $post_cur_slug . '/';
$link = home_url($slug, 'https');
}
return $link;
}
The array $try_array should contain post_id's in which we change the link format
Background
I'm building a course catalog for a school and am trying to make friendly, dynamic URLs. It has three custom post types:
catalog.
course. This post type contains a title, course number, and course description.
section. This post type contains a cost, start and end dates and times, etc. A section is an instance of a course; for example, there might be two sections of Drawing for Beginners, one on Thursday morning and one on Monday night and taught by two different faculty.
There is a one-to-many relationship between course and section. When viewing a section, it displays the parent course's course name, course number, and course description. It also displays that section's cost, start and end dates and times, etc.
The current URL for a section is this:
http://website.org/section/section-slug/
I would like it to be this:
http://website.org/class/spring-2019/drawing-for-beginners/01/
...where "class" is a 'virtual' folder / synthetic prefix
...where "spring-2019" corresponds to a "catalog" custom post type
...where "drawing-for-beginners" corresponds to a slug for the parent "course" custom post type
...where "01" corresponds to the section of the course.
WordPress should display the section post type that matches these criteria.
Research
I've read quite a bit about both the Rewrite API and the Endpoints API. The best article I could find on a topic closest to what I'm trying to accomplish is this one. Sadly, the example code on the page didn't work for me, resulting in a "too many redirects error." I can provide more details about exactly which portion didn't work, if desired. I also read this article on Make WordPress Plugins but it doesn't cover dynamic lookups.
What I'm trying to accomplish
http://website.org/class/spring-2019/drawing-for-beginners/01/
When the virtual URL is supplied to WordPress, I need the system to perform a query to look up the section whose number is "01" and which belongs to the "spring-2019" catalog and whose parent course has a slug of "drawing-for-beginners." That query isn't a challenge, it's all of the hooks that need to be called to execute that code and return the correct template (for the section page). I'm not sure whether I need to create an Endpoint or can just get away with adding rewrite rules.
Can someone offer some guidance?
--
As a "bonus," I'm also trying to accomplish this:
http://website.org/class/spring-2019/drawing-for-beginners/01/faculty_name
...where "faculty_name" is dynamic and is the name of the person teaching that section (and corresponds to a "faculty" custom post type).
http://website.org/class/spring-2019/drawing-for-beginners/01/gallery
...where "gallery" is a static name and shows a gallery custom post type.
After much investigation, I've found an answer to my question. Here it goes.
This is how to create truly dynamic URLs / slugs in WordPress. The URLs don't correspond to a page. Instead, the parts of the slug are used to look up a post ID and then render that post accordingly.
Step 1: Add the rewrite rule
function pce_rewrite_rules ( ) {
add_rewrite_rule ( '^class/([^/]*)/([^/]*)/([^/]*)/?', 'index.php?post_type=section&catalog_name=$matches[1]&course_name=$matches[2]§ion_no=$matches[3]','top' ) ;
add_action ( 'init', 'pce_rewrite_rules', 10, 0 ) ;
Step 2: Register the query variables
function pce_register_query_vars ( $vars ) {
$vars[] = 'course_name';
$vars[] = 'catalog_name';
$vars[] = 'section_no';
return $vars;
}
add_filter ( 'query_vars', 'pce_register_query_vars' );
Step 3: Modify the WP query
Use pre_get_posts to modify the main query. But you have to force some variables in the query so that WordPress loads the template that you need. To find the variables I needed to manually set, I used a WP plugin (Query Monitor) to examine the contents of the WP query, and I used var_dump on the type of post I wanted to "copy."
function pce_dynamic_section_lookup ( $wp ) {
if ( is_admin() || ! $wp->is_main_query() ){
return;
}
if ( $wp->is_main_query() ) {
// Only defined if we're looking at a "fake" URL.
// Example: http://pce.local/class/spring-2019/handmade-books/01/
if ( get_query_var ('course_name' ) ) {
// These are some of the variables I needed to set manually.
$wp->query_vars['post_type'] = 'section' ;
$wp->query_vars['is_single'] = true ;
$wp->query_vars['is_singular'] = true;
$wp->query_vars['is_archive'] = false;
$course_name = get_query_var ('course_name' ) ;
$catalog_name = get_query_var ('catalog_name' ) ;
$section_no = get_query_var ('section_no' ) ;
// More code is here to look up the post ID I need.
// Set the post ID here. This makes the magic happen.
$wp->query_vars['p'] = $post_id ;
// This also makes the magic happen. It forces the template I need to be selected.
$wp->is_single = true ;
$wp->is_singular = true ;
$wp->is_archive = false ;
$wp->is_post_type_archive = false ;
}
}
}
add_action ( 'pre_get_posts', 'pce_dynamic_section_lookup', 0, 2 ) ;
I had a post with this original URL:
http://pce.local/section/handmade-books-01/
And now I can load it at this URL (and it loads it, it does not forward it):
http://pce.local/class/spring-2019/handmade-books/01/
I needed to do this because multiple sections are going to be added in future catalogs and I wanted to keep the URLs friendly. In the summer if the class is offered, it will be...
http://pce.local/class/summer-2019/handmade-books/01/
Instead of...
http://pce.local/section/handmade-books-01-2/
or whatever slug WordPress assigns it. Having only a couple of sections isn't a big deal, but there will be several in the future.
If i understood good, this might help you.
I am not sure how did you make relationship but i will put the code that i usually use. And lets say that catalog-course also have a relationship.
function add_rewrite_rules( $wp_rewrite )
{
$section_rules = array(
'class/(.+?)/?$' => 'index.php?post_type=post&name='. $wp_rewrite->preg_index(1),
);
$wp_rewrite->rules = $section_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');
function change_section_links($post_link, $id=0){
$courses = new WP_Query( array(
'post_type' => 'course',
'post__in' => get_post_meta( $catalog_id, '_course', true ),
) );
if ( $courses-> have_posts() ) { while ( $courses->have_posts() ) {
$courses->the_post();
$catalog_name = get_the_title();
}
$sections = new WP_Query( array(
'post_type' => 'section',
'post__in' => get_post_meta( $course_id, '_section', true ),
) );
if ( $sections-> have_posts() ) { while ( $sections->have_posts() ) {
$sections->the_post();
$course_name = get_the_title();
}
$post = get_post($id);
if( is_object($post) && $post->post_type == 'section'){
return home_url('/class/'. $catalog_name. '/'. $course_name. '/'. $post->post_name.'/');
}
return $post_link;
}
add_filter('post_link', 'change_section_links', 1, 3);
I hope that it would help you. If it doesnt, tell me how did you make relationship.
I am having some issue on my wordpress site.
The site url is http://www.sharedmachine.in/.
On the home page there is search option.
Now the permalink structure right now is like this - http://www.sharedmachine.in/?p=123.
Now after clicking the search button, it suppose to redirect to the 'advanced search' page. but it doesn't.
So I changed the permalink structure to custom - /%postname%/.
Still it doesn't work.
The URL it should redirect to is
http://www.sharedmachine.in/advanced-search/?filter_search_type (some filters)
But instead it shows-
http://www.sharedmachine.in/?filter_search_type (filters)
The page name is not coming in the URL.
Now the code to get url is -
$adv_submit=wpestate_get_adv_search_link();
and the function -
function wpestate_get_adv_search_link(){
$pages = get_pages(array(
'meta_key' => '_wp_page_template',
'meta_value' => 'advanced_search_results.php'
));
if( $pages ){
$adv_submit = esc_url ( get_permalink( $pages[0]->ID) );
}else{
$adv_submit='';
}
return $adv_submit;
}
If I change the line
$adv_submit=wpestate_get_adv_search_link();
To
$adv_submit='http://www.sharedmachine.in/index.php/advanced-search/';
it works.
What can be the issue here?
aparently the $pages variable never gets populated. i would try something like:
$page = get_page_by_path('advanced-search');
if ($page) {
$adv_submit = esc_url ( get_permalink( $page->ID) );
} else {
// do something else
}
in this case you would be looking up the page by its slug as opposed to a page-meta you may or may not have set
I am updating my custom Wordpress theme, but as it is rather time consuming process I would like to launch one section at a time.
In other words there would be several versions of a theme for different parts of the website.
To keep things tidy I would like to keep them in separate folders, with all the assets such as js, images, css.
I managed to rewrite template hierarchy using conditional tags but got stuck on functions.php
I was trying to use custom filed (post meta) to switch between several functions.php files but unfortunately $post is not available there so I am unable to use get_post_meta().
I could only find a trace of a solution with custom db queries, $wpdb etc. but can't really figure it out.
Is there any fairly simple solution to hook-up into post data (wp_query) before functions.php is loaded? Or to somehow differently modify where the functions are loaded from?
To illustrate what I'm writing about I pasted my main index.php
<?
get_header();
/*
* Get theme version according to the custom field 'section'
*/
if( function_exists ( 'theme_version' ) ){
$theme = theme_version( #get_the_ID() );
} else {
$theme = 'v2';
}
include_once( 'theme/'. $theme .'/TEMPLATE_BUILDER.php' );
get_footer();
?>
Thanks!
Hopefully found a right answer (after couple of hours of research, trial and error)
I placed the below code in main (wp-native) functions.php
in attempt to keep the code and file structure tidy, works as a charm.
add_action('after_setup_theme', function(){
// parse_url tidies-up the uri
$section = get_post_meta( url_to_postid( parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ) ),'section', true);
if ( !empty( $section )){
// assign sections to the theme versions below
$theme_version = array(
'v3' => array(
'Sixth Form',
[ ... ]
),
'v3.1' => array(
'Contact',
[ ... ]
)
);
foreach($theme_version as $key => $value) { if(in_array( $section, $value )) $theme = $key; }
}
if( empty($theme) ) $theme = 'v2'; // default theme version
require_once( 'theme/' . $theme . '/functions.php' );
$GLOBALS['theme-ver'] = $theme; // set the global to use in index.php (and somewhere else perhaps)
});
The code is not complete yet – needs some conditional clauses as the functions.php is sometimes called multiple times within the loop (especially with custom wp_query)
Perhaps someone will find the above useful. By the way it's quite surprising that WP doesn't natively support some kind of 'theme version control' – I can see strong benefits of not having to upgrade the whole website at once for instance to e. g. resp.
I have a wordpress multisite with one main and four child website. i have done plugin for share woocommerce product to childsite. now child site can add or update mainsite product from child site. but when displaying in front end the media path is wrong. i want use all child site product image path to same path. how it possible ?
In woocommerce plugin and in file class-wc-admin-post-types.php
woocomerce override the WordPress upload filter through the filter 'upload_dir'
add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
public function upload_dir( $pathdata ) {
// Change upload dir for downloadable files
if ( isset( $_POST['type'] ) && 'downloadable_product' == $_POST['type'] ) {
if ( empty( $pathdata['subdir'] ) ) {
$pathdata['path'] = $pathdata['path'] . '/woocommerce_uploads';
$pathdata['url'] = $pathdata['url']. '/woocommerce_uploads';
$pathdata['subdir'] = '/woocommerce_uploads';
} else {
$new_subdir = '/woocommerce_uploads' . $pathdata['subdir'];
$pathdata['path'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['path'] );
$pathdata['url'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['url'] );
$pathdata['subdir'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['subdir'] );
}
}
return $pathdata;
}
so if you want to override it, you can create filter to this 'upload_dir' with higher priorites.
I would call this a try and error thing, I had done something similar but it takes some time customizing as your desired.
So here it's what I believe could solve your main problem:
add_action('pre_get_posts', '_my_pre_get_posts', 10, 1);
function _my_pre_get_posts( $wp ) {
global $typenow, $blog_id;
if ( 'product' == $typenow && $blog_id != 1) {
switch_to_blog(1);
}
}
if the $blog_id is not the main site (reads ID = 1) you should switch to blog ID 1, all this is happening before all post are pulled from the database.
product is the current post_type being queried, if you want this to work with orders as well you probably will check for 'shop_order'.
To know which post_type is being queried you should check the url, Ex: /edit.php?post_type=shop_order.
This probably would bring some issues such as the title of the blog in the adminbar is the one from the main site, and it's missing that at some point it needs to restore to the main site back, but at least this should do the trick.
check this Solution and Let me know how end up