How do I get a list of items in the Wordpress media library on a plugin options page? - wordpress

I'm writing a Wordpress plugin which injects a grid of images just above the footer on all frontend pages. The application is to display sponsor's logos. I'd like to harness the WP Media Library since the logos are already uploaded for use on the 'sponsorship' page and in posts.
Essentially I'm stuck at accessing the media library interface on the plugin's options page. All of the legwork is done in terms of creating the options page, using the action hook to place content on frontend pages from the plugin, etc. What I need now is to be able to display all the files in the media library in a list on the options page, and provide a checkbox or something to allow the user to select certain files for insertion above the footer.
The Media Library API seems to be aimed at people writing themes or media plugins. Help understanding what to make use of would be great!

I think you'd be much better off adding your own column into the existing media library, rather than try re-coding it yourself;
function my_media_col($cols)
{
$cols['my_col'] = 'Footer';
return $cols;
}
add_filter('manage_media_columns', 'my_media_col');
function handle_my_media_col($name, $id)
{
if ($name !== 'my_col')
return false;
$in_footer = get_option('in_footer', array());
?>
<input type="checkbox" name="in_footer[]" value="<?php echo $id; ?>" <?php checked(in_array($id, $in_footer)); ?> />
<?php
}
add_action('manage_media_custom_column', 'handle_my_media_col', 10, 2);
Then just hook onto the load-upload.php (the library page) and save changes when POST'ed;
function save_my_col()
{
if (!isset($_POST['in_footer']))
return false;
$in_footer = $_POST['in_footer'];
if (is_array($in_footer))
$in_footer = array_map('absint', $in_footer); // sanitize
else
$in_footer = array();
$in_footer = array_merge(get_option('in_footer', array()), $in_footer);
$in_footer = array_unique(array_filter($in_footer));
update_option('in_footer', $in_footer);
}
add_action('load-upload.php', 'save_my_col');
Note this is just an example, and I may have one or two typos.
UPDATED:
My code example should store an array of IDs in the options table, under the key 'in_footer'.
Put in practice, you can get all media items marked 'in footer' like so;
$query = new WP_Query(array('post__in' => get_option('in_footer', array()) ));
if ($query->have_posts()): while ($query->have_posts()): $query->the_post();
?>
<?php the_title(); ?>
<?php endwhile; endif; ?>

Related

Switch Between Multiple Headers in WordPress Theme

I am building a custom theme for WordPress. One thing I want to do is allow myself to switch the header from the edit page.
I know I can hard code in the header to switch based on the page ID or name, like this:
<?php
if(is_page(10)) {
get_header('new');
}
else {
get_header();
}
wp_head();
?>
But I want a drop down menu similar to the Page Template option in the sidebar. (See screenshot)
Screenshot of sidebar menu
I have looked for any online tutorials that cover this type of option, but they all cover the basic ID or name setup shown above.
Does anyone know of a good tutorial to create a drop down similar to Page Templates to use for multiple headers?
You can use Custom Metaboxes. That link contains a comprehensive tutorial on creating custom metaboxes for post meta fields by hand. You can also use a plugin like Advanced Custom Fields to create them.
Doing this would allow you to check for the header style value through get_post_meta() or get_field(), respectively.
<?php
// If using the Custom Metabox/post_meta approach:
$header_style = get_post_meta( get_the_ID(), 'my_custom_header', true );
// If using ACF:
$header_style = get_field( 'my_custom_header', get_the_ID() );
if( $header_style == 'new' ){
get_header('new');
if( $header_style == 'something-else' ){
get_header('something-else');
} else {
get_header();
}
?>

Visual Composer Grid with do_action shortcode is not working

I have visual composer which is packed with total theme. When I put the following grid short code in my page in the editor it works correctly.
[vc_basic_grid post_type="post_type" max_items="10" item="masonryGrid_SlideFromLeft" grid_id="vc_gid:1458178666639-80ebf3775500c87d35de078c3422fe96-10" taxonomies="555"]
However, when I call the exact same code using do_action it gives the following javascript error. I checked the html output and it is the same using do_action like putting the short code in editor.
Error: Syntax error, unrecognized expression: {'status':'Nothing found'}
s
Any help is greatly appreciated.
Well, you can't output contents directly in your templates by using core shortcodes of VC like that.
1. Problem:
For security, besides nonce, VC uses page_id and shortcode_id to check AJAX request/respond data.
The shortcode_id is automatically generated by VC, you can not harcode it.
For example, this is the shortcode you see on admin editor screen:
[vc_basic_grid post_type="post_type" max_items="10" item="masonryGrid_SlideFromLeft" grid_id="vc_gid:1458178666639-80ebf3775500c87d35de078c3422fe96-10" taxonomies="555"]
Let say the page ID is 4269, this is the generated HTML code on front-end:
<!-- vc_grid start -->
<div class="vc_grid-container-wrapper vc_clearfix">
<div class="vc_grid-container vc_clearfix wpb_content_element vc_masonry_grid" data-initial-loading-animation="zoomIn" data-vc-grid-settings="{"page_id":4269,"style":"all-masonry","action":"vc_get_vc_grid_data","shortcode_id":"1458178666639-80ebf3775500c87d35de078c3422fe96-10","tag":"vc_masonry_grid"}" data-vc-request="http://example.com/wp-admin/admin-ajax.php" data-vc-post-id="4269" data-vc-public-nonce="0641473b09">
</div>
</div>
<!-- vc_grid end -->
Now, if page_id and shortcode_id don't match each other, {'status':'Nothing found - $shorcode_id'} will be throw out and no contents will be displayed.
You can find out more inside vc_grid.min.js file.
2. Solution:
Generate a fake page with VC, then copy generated html code to your template file.
Create a template with VC directly.
Use Shorcode Mapper to create your own shorcode.
First you build a new page and add a grid post on it,
then we get
_vc_post_settings
post meta , and try to build a new one
then update post meta data
now we can by pass VC Ajax security check
in the following code "1513628284966-37b8c3ca-d8ec-1" is VC generated guid
you should change it to yours .
$meta = get_post_meta(1365,'_vc_post_settings');
$settings = array();
#$settings['vc_grid_id'] = $meta[0]['vc_grid_id'];
$key = random_int(1513628284966,9513628284966);
$settings['vc_grid_id']['shortcodes'][''.$key.'-37b8c3ca-d8ec-1'] = $meta[0]['vc_grid_id']['shortcodes']['1513628284966-37b8c3ca-d8ec-1'];
$settings['vc_grid_id']['shortcodes'][''.$key.'-37b8c3ca-d8ec-1']['atts']['custom_query'] = "tag=shop";
$settings['vc_grid_id']['shortcodes'][''.$key.'-37b8c3ca-d8ec-1']['atts']['grid_id'] = ''.$key.'-37b8c3ca-d8ec-1';
$n = add_post_meta(1365,'_vc_post_settings',$settings);
return do_shortcode("[vc_basic_grid post_type=\"custom\" show_filter=\"yes\" filter_style=\"dropdown\" item=\"5959\" grid_id=\"vc_gid:".$key."-37b8c3ca-d8ec-1\" filter_source=\"post_tag\" custom_query='tag=".$tag."']");
I've solved.
I had the same problems, with the Visual Composer Editor offered by WpBakery
https://wpbakery.com/
and after understanding the connection between the IDs of the block, and the ID of the Post, I put more attention to the settings of the Block.
There is infact one field called "Element ID", and here we have to put our ID of the Post we are editing.
In my case the Block was a block containing some Posts.
After saving, and viewing the page without the Editor, I was finally able to see the block, and not the message
{"status":"Nothing found"}
I found a solution to this problem.
I modified the woocommerce category template and linked to the woocommerce_archive_description hook to add additional descriptions from some pages, for this I got their id, and then display the content.
echo do_shortcode($post->post_content);
The gallery(media grid) didn't work because there was a mismatch between the page id and the shortcode id. Therefore, the logical solution was to redefine the global variable $post to the $post of the page from which I get the content.
global $post;
$post = get_post( $id );
And it turns out that the post id matches.
After that, don't forget to return the normal $post value;
wp_reset_postdata();
By the way - use this option to load custom styles for wpbakery elements.
echo '<style type="text/css" data-type="vc_shortcodes-custom-css">' . get_post_meta( $id, '_wpb_shortcodes_custom_css', true ) . '</style>';
The whole code
function extra_product_category_desc(){
if( is_product_category() ){
$id = get_term_meta (get_queried_object()->term_id, 'pageId', true);
if($id !== ''){
global $post;
$post = get_post( $id );
echo do_shortcode($post->post_content);
echo '<style type="text/css" data-type="vc_shortcodes-custom-css">' . get_post_meta( $id, '_wpb_shortcodes_custom_css', true ) . '</style>';
wp_reset_postdata();
}
}
}
add_action( 'woocommerce_archive_description', 'extra_product_category_desc', 11 );
You may also try with do_shortcode('');
Like
do_shortcode('[vc_basic_grid post_type="post_type" max_items="10" item="masonryGrid_SlideFromLeft" grid_id="vc_gid:1458178666639-80ebf3775500c87d35de078c3422fe96-10" taxonomies="555"]');
Best Regards,

Wordpress: Add config option to all widget settings

In Wordpress, my goal is to be able to give a custom class to every widget that I put in the sidebar.
Preferably I would like to add this class in the widget settings of each widget. ALSO 3rd party widgets.
I was thinking of changing the classname, because the classname is already passed to the register_sidebar function (%2$s):
<?php
register_sidebar(array('before_widget' => '<aside id="%1$s" class="widget %2$s blue">'));
?>
Ofcourse I shouldn't change WP core code or 3rd party plugins. This means that I need to write a plugin that will hook into the widget configuration process.
I already found out that it's possible to modify all widgets forms, by hooking into action 'in_widget_form':
<?php
add_action('in_widget_form', 'teaserWidgetAddToForm');
function teaserWidgetAddToForm($widget_instance) {
?>
<label for="<?php echo $widget_instance->get_field_id('teaser-classname'); ?>">Custom classname(s):</label>
<input type="text" id="<?php echo $widget_instance->get_field_id('teaser-classname'); ?>" name="<?php echo $widget_instance->get_field_name('teaser-classname'); ?>">
<?php
}
?>
This data should be saved by the Widget super class, but how do you retrieve this data (so when opening the widget settings later shows what you filled in earlier)
And, this saved data should be put in the widget instance -how is this done? I guess by using something like:
<?php
$wp_registered_widgets[<widget_id>]['callback'][0]['widget_options']['classname'] = <chosen_class>;
?>
So basically I have 2 questions:
Am I using the proper way to address this problem (styling of individual widgets)
If so, how can I modify a widget instance to save and retrieve additional settings, without having to modify Wordpress or 3rd party Plugin source code.
By default each widget instance has a unique ID which can be used to style it.
In order to save data from fields added in an in_widget_form action, you need to also have a widget_update_callback filter.
function my_widget_update_callback($instance, $new_instance) {
$instance['my_classnames'] = $new_instance['my_classnames'];
return $instance;
}
To display the saved value in the form you'll need to first retrieve the instance settings.
function my_in_widget_form($instance) {
$settings = $instance->get_settings();
…
Finally, I think the simplest way to add your custom classes is in a widget_display_callback filter, which runs before a widget is displayed. You have to display the widget yourself because you can only return an instance from this filter, and instances do not control the widget CSS classes.
function my_widget_display_callback($instance, $widget, $args) {
if (!isset($instance['my_classnames'])) {
return $instance;
}
$widget_classname = $widget->widget_options['classname'];
$my_classnames = $instance['my_classnames'];
$args['before_widget'] = str_replace($widget_classname, "{$widget_classname} {$my_classnames}", $args['before_widget']);
$widget->widget($args, $instance);
return false;
}
See this article for more info on the available hooks related to widgets: http://shibashake.com/wordpress-theme/wordpress-widget-system

Protect wordpress theme with license key validation

I'm planning to develop some professional Wordpress Themes and would like to protect it using license keys, is it possible?
If so, would any one be willing to link to some posts or articles to help me get started?
You could set up a database on your own server, holding the license key and the licensed url for the theme. Then, set up an admin page for your theme. Within, first register a license settings array. Then implement a hidden settings field on that same page that gets updated whenever the license key is being updated by site admin. the update function sends a request to your server passing the license key and the $_SERVER's host and setting the hidden license_settings field to either true or false.
A really simplified code would look like this:
functions.php
<?php
// functions.php
require("myadminpage.php");
# Functions follow here...
?>
myadminpage.php
<?php
// myadminpage.php
// register settings
function my_settings_init() {
register_setting('settings_license', 'settings_license');
}
// register admin page
function my_add_admin_page() {
add_menu_page(__( '' ), __( 'Manage License' ), 'administrator', 'myadminpage', 'my_admin_page');
}
add_action('admin_init', 'my_settings_init');
add_action('admin_menu', 'my_add_admin_page' );
if(isset($_GET["settings-updated"]) && $_GET["settings-updated"] == true) {
$options = get_option('settings_license');
$key = $options["key"];
$host = parse_url($GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI'], PHP_URL_HOST);
$url = sprintf("http://you.com/check-license.php?key=%s&url=%s", $key, $host);
$options["valid"] = trim(file_get_contents($url)) == 1) ? "true" : "false";
update_option('settings_license', $options);
}
// callback function that renders your admin page
function my_admin_page() {
settings_fields('settings_license');
$options = get_option('settings_license');
?>
<form method="post" action="options.php">
<input id="settings_license[key]" type="text" name="settings_license[key]" value="<?php echo $options["key"]; ?>">
<input id="settings_license[valid]" type="hidden" name="settings_license[valid]" value="<?php echo $options["valid"]; ?>">
<input type="submit" value="Save">
</form>
<?php
}
?>
Now you can, when ever you need/want, get the license options and handle the invalid usage in any way you want. Eg (a rude way):
header.php
<?php
// very first line
$license = get_option('settings_license');
// see: http://ckon.wordpress.com/2006/08/09/server-request_uri-doesnt-always-work-correctly-heres-how-to-fix/
$ruri = $GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI'];
if(!preg_match("#wp-admin#", $ruri) && $license["valid"] != "true") {
wp_die( __('This website uses unlicensed software.<br>Administrators can update their license key here.') );
}
# rest of header.php comes here..
Finally obfuscate your php code (eg http://www.ioncube.com/sa_encoder.php) and you're done. However, make sure you're not violating any other licenses, such as WP's. If there's one single line of WordPress core functions used within your final code, you can not release it under any other license than WP, which is GPL.
I don't think so. After all, the users must have the php code to use the theme and if they have it - they may alter it in a such way that it won't need a key any more.

Programmatic Views in Drupal 7

I'm trying to create two views.
View-1 is a list of nodes.
View-2 is an image gallery associated with each node.
I basically want to pass the node title from View-1 to a programmatic View-2, so that each row in View-1 will load View-2(with a result set filtered by the title of View-1!).
I'm confused about the approach. Should this happen in a custom module, preprocess functions, or some combination thereof?
I run into this a lot - wanting to pass an argument from a primary view to a secondary view that displays with each result.
I realize that the question is a bit general, but I'm curious how folks with more experience would approach this problem.
I've done this before on D6 where basically I just create a couple template tpl.php files for my View-1.
Inside my View-1 template for Display Output (views-view--default.tpl.php in D7 now)
I would simply programmatically find the value passed or returned by View-1 for this row.
In your case on each row you would check to see which node is returned by View-1 and then I'd add code in my View-1 template to programmatically load View-2 based on the current View-1 row (ie. node in your case.)
Make sense? 5 months late on the response but I was looking for a refresher and seeing if there's a better way to do this now in D7.
UPDATE:Just did this on my new D7 install. As an example I'll explain how it relates to my Ubercart implementation.
Ubercart, when installed, has it's main "home" shop page located at mysite.com/catalog
This page, when loaded, calls a View created by Ubercart called uc_catalog_terms. It is a taxonomy based view and all it does is grab all your Catalog taxonomy categories and render them.
E.g
As a clothing store, when you navigate to mysite.com/catalog, all you'll see at this page is a grid structure like:
Sweaters Shirts Jeans
My requirement was that I needed to show the shop catalog categories/terms on this page, but ALSO show 3 random products (images) from that category/term below it each catalog category.
E.g
Sweaters
Random Sweater #1 - Random Sweater #2 - Random Sweater #3
Jeans
Random Jean #1 - Random Jean #2 - Random Jean #3
How is this accomplished?
I created my own brand new custom view (no page or lock, just default) which grabs 3 random product images based on a taxonomy term ID argument and renders 3 linked product images. I'll call this custom view random_catalog_items. If 15 is the term ID for Sweaters, when this view is called with the argument 15 it will only render 3 random linked sweater product images.
I now went back to uc_catalog_terms view and created a views-view-fields--uc-catalog-terms.tpl.php (Row Style Output) template file.
THE DEFAULT VIEW VERSION OF THIS FILE (BEFORE MODIFICATION) IS:
<?php foreach ($fields as $id => $field): ?>
<?php if (!empty($field->separator)): ?>
<?php print $field->separator; ?>
<?php endif; ?>
<?php print $field->wrapper_prefix; ?>
<?php print $field->label_html; ?>
<?php print $field->content; ?>
<?php print $field->wrapper_suffix; ?>
<?php endforeach; ?>
THE MODIFIED VERSION BECOMES:
<?php foreach ($fields as $id => $field): ?>
<?php if (!empty($field->separator)): ?>
<?php print $field->separator; ?>
<?php endif; ?>
<?php print $field->wrapper_prefix; ?>
<?php print $field->label_html; ?>
<?php
$title = str_replace('/','-',strtolower($field->raw));
print '<img src="'.drupal_get_path('theme','my_theme').'/images/catalog/'.$title.'-header.png" />';
print '<hr style="width: 100%; background: #000; height: 2px; margin-top: 3px;"/>';
// get the taxonomy term ID
$tid = $row->tid;
// render the 3 random items
if ($random_products = views_get_view('random_catalog_items' )) {
print $random_products->execute_display('default', array($tid));
}
?>
<?php print $field->wrapper_suffix; ?>
<?php endforeach; ?>
So as you can see inside the first View, for every row that is rendered I get the current taxonomy term ID being shown through the available row result object - $row->tid and then I simply call my created view for each row, passing along this Term ID as the argument for it. I leave a lot of the default code in there but inside my view configurations the LABELS and such are set to HIDDEN so they don't even render anyway.
In your case it should be very easily adaptable to just pass a Node NID instead of a Taxonomy Term ID.
VOILA IT ALL WORKS! View within a View! Hope this helps :)
It helps to have the Devel module loaded since then inside these View templates you can debug and see what variables are available to you via something like print krumo($row).
Personally I would avoid views here alltogether.
A simple module using a hook_menu to define the menu-items and two simple menu-callback-functions dealing with the required parameters.
The alternative would be to make all the custom parameters and custom query-filtering and tables known to views.
My (pseronal) rule of thumb is:
If you are certain you will re-use the code several times in future projects a view-addon is worth the investment.
If you will use the views-interface for more then one-time-setup (the general use) e.g. define or change views in an editors/webmasters workflow this makes sense.
The basics of this is really simple and most probably a lot less coding and development then writing the views extensions.
/** Implementation of hook_menu().
*/
function gallery_menu() {
$items = array();
$items['gallery'] = array(
'title' => 'Gallery',
'page callback' => '_gallery_list',
'access arguments' => array('access content'),
);
$items['gallery/%gallery'] = array(
'title' => 'For dynamic titles, see title_callback documentation',
'page callback' => '_gallery_view',
'access arguments' => array('access content'),
);
return $items;
}
/** Load a gallery from database. Name follows %parameter_load hook.
*/
function gallery_load($id) {
return db_query("SELECT * FROM {galleries} WHERE id = %d", $id);
}
/** Render a list of galleries.
*/
function _gallery_list() {
$html = "";
$galleries = pager_query("SELECT * FROM {galleries}", 10);
foreach($galleries as $gallery) {
$html .= check_plain($gallery->title); //You would actually build vars here and push them to theme layer instead.
}
$html .= theme("pager");
return $html;
}
/** Load a gallery from database. Name follows %parameter_load hook.
*/
function gallery_load($id) {
return db_query("SELECT * FROM {galleries} WHERE id = %d", $id);
}
/** Render a list of galleries.
*/
function _gallery_view($gallery) {
$html = "";
$images = pager_query("SELECT * FROM {images} WHERE gallery_id = %d", 10, $gallery->id);
foreach($images as $image) {
$html .= check_plain($image->title); //You would actually build vars here and push them to theme layer instead.
}
$html .= theme("pager");
return $html;
}
Obviously, as stated in the comments, you would additionally create a few theme functions to handle the rendering, to 1) avoid hardcoded spagetty-HTML all over your module and b) allow the frontenders to stay in their theme when creating the HTML.
This sounds like a good opportunity to use an ajax callback. You could have your primary view on a part of the page just like normal and a secondary view in a custom block or something. when focus lands on the primary item (in the form of a button click or hover or something) you can use an ajax callback to replace the content of your custom block with the secondary view using your argument.
are you using drupal 6 or 7 for this? my understanding is that they do this is different ways.

Resources