1168 lines
35 KiB
PHP
Executable File
1168 lines
35 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Main file of the plugin
|
|
*
|
|
* @package categoryposts.
|
|
*
|
|
* @since 1.0
|
|
*/
|
|
|
|
/*
|
|
Plugin Name: Category Posts Widget
|
|
Plugin URI: https://wordpress.org/plugins/category-posts/
|
|
Description: Adds a widget that shows the most recent posts from a single category.
|
|
Author: TipTopPress
|
|
Version: 4.9.18
|
|
Author URI: https://tiptoppress.com
|
|
Text Domain: category-posts
|
|
Domain Path: /languages
|
|
*/
|
|
|
|
namespace categoryPosts;
|
|
|
|
// Don't call the file directly.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
const VERSION = '4.9.18';
|
|
const DOC_URL = 'https://tiptoppress.com/category-posts-widget/documentation-4-9/';
|
|
const PRO_URL = 'https://tiptoppress.com/term-and-category-based-posts-widget/';
|
|
const SUPPORT_URL = 'https://wordpress.org/support/plugin/category-posts/';
|
|
const SHORTCODE_NAME = 'catposts';
|
|
const SHORTCODE_META = 'categoryPosts-shorcode';
|
|
const WIDGET_BASE_ID = 'category-posts';
|
|
|
|
require_once __DIR__ . '/class-virtual-widget.php';
|
|
require_once __DIR__ . '/class-virtual-widgets-repository.php';
|
|
require_once __DIR__ . '/class-widget.php';
|
|
require_once __DIR__ . '/loadmore.php';
|
|
require_once __DIR__ . '/localizeddate.php';
|
|
|
|
/**
|
|
* Adds the "Customize" link to the Toolbar on edit mode.
|
|
*
|
|
* @since 4.6
|
|
*/
|
|
function wp_admin_bar_customize_menu() {
|
|
global $wp_admin_bar;
|
|
|
|
if ( ! isset( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( ! current_user_can( 'customize' ) || ! is_admin() || ! is_user_logged_in() || ! is_admin_bar_showing() ) {
|
|
return;
|
|
}
|
|
|
|
$current_url = '';
|
|
if ( isset( $_GET['post'] ) && ( '' !== $_GET['post'] ) ) {
|
|
$current_url = get_permalink( absint( $_GET['post'] ) );
|
|
}
|
|
$customize_url = add_query_arg( 'url', rawurlencode( $current_url ), wp_customize_url() );
|
|
|
|
$p = isset( $_GET['post'] ) && ! empty( $_GET['post'] ) ? get_post( absint( $_GET['post'] ) ) : false;
|
|
$names = $p ? shortcode_names( SHORTCODE_NAME, $p->post_content ) : array();
|
|
if ( empty( $names ) ) {
|
|
return;
|
|
}
|
|
|
|
$wp_admin_bar->add_menu(
|
|
array(
|
|
'id' => 'customize',
|
|
'title' => __( 'Customize' ),
|
|
'href' => $customize_url,
|
|
'meta' => array(
|
|
'class' => 'hide-if-no-customize',
|
|
),
|
|
)
|
|
);
|
|
add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
|
|
}
|
|
|
|
add_action( 'admin_bar_menu', __NAMESPACE__ . '\wp_admin_bar_customize_menu', 35 );
|
|
|
|
/**
|
|
* Print out required CSS, hooked on the wp_head hook.
|
|
*/
|
|
function wp_head() {
|
|
|
|
$widget_repository = new Virtual_Widgets_Repository();
|
|
|
|
$styles = array();
|
|
|
|
foreach ( $widget_repository->getShortcodes() as $widget ) {
|
|
$widget->getCSSRules( true, $styles );
|
|
}
|
|
|
|
foreach ( $widget_repository->getWidgets() as $widget ) {
|
|
$widget->getCSSRules( false, $styles );
|
|
}
|
|
|
|
if ( ! empty( $styles ) ) {
|
|
?>
|
|
<style>
|
|
<?php
|
|
foreach ( $styles as $rules ) {
|
|
foreach ( $rules as $rule ) {
|
|
echo "$rule\n"; // Xss ok. raw css output, can not be html escaped.
|
|
}
|
|
}
|
|
?>
|
|
</style>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
add_action( 'wp_head', __NAMESPACE__ . '\register_virtual_widgets', 0 );
|
|
|
|
/**
|
|
* Register virtual widgets for all widgets and shortcodes that are going to be displayed on the page
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function register_virtual_widgets() {
|
|
global $post;
|
|
global $wp_registered_widgets;
|
|
|
|
$repository = new Virtual_Widgets_Repository();
|
|
|
|
// check first for shortcode settings.
|
|
if ( is_singular() ) {
|
|
$names = shortcode_names( SHORTCODE_NAME, $post->post_content );
|
|
|
|
foreach ( $names as $name ) {
|
|
$meta = shortcode_settings( get_the_ID(), $name );
|
|
if ( is_array( $meta ) ) {
|
|
$id = WIDGET_BASE_ID . '-shortcode-' . get_the_ID(); // needed to make a unique id for the widget html element.
|
|
if ( '' !== $name ) { // if not default name append to the id.
|
|
$id .= '-' . sanitize_title( $name ); // sanitize to be on the safe side, not sure where when and how this will be used.
|
|
}
|
|
$repository->addShortcode( $name, new Virtual_Widget( $id, WIDGET_BASE_ID . '-shortcode', $meta ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
$sidebars_widgets = wp_get_sidebars_widgets();
|
|
|
|
if ( is_array( $sidebars_widgets ) ) {
|
|
foreach ( $sidebars_widgets as $sidebar => $widgets ) {
|
|
if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( is_array( $widgets ) ) {
|
|
foreach ( $widgets as $widget ) {
|
|
$widget_base = _get_widget_id_base( $widget );
|
|
if ( WIDGET_BASE_ID === $widget_base ) {
|
|
$class = __NAMESPACE__ . '\Widget';
|
|
$widgetclass = new $class();
|
|
$allsettings = $widgetclass->get_settings();
|
|
$settings = isset( $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] ) ? $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] : false;
|
|
$repository->addWidget( $widget, new Virtual_Widget( $widget, $widget, $settings ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
add_action( 'wp_head', __NAMESPACE__ . '\wp_head' );
|
|
|
|
/**
|
|
* Enqueue widget related scripts for the widget front-end
|
|
*
|
|
* @since 4.8
|
|
*/
|
|
function frontend_script() {
|
|
$suffix = 'min.js';
|
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
|
|
$suffix = 'js';
|
|
}
|
|
wp_enqueue_script( 'cat-posts-frontend-js', plugins_url( 'js/frontend/category-posts-frontend.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
|
|
}
|
|
|
|
/**
|
|
* Embed the front end JS in the HTML footer.
|
|
*
|
|
* @since 4.9
|
|
*/
|
|
function embed_front_end_scripts() {
|
|
$suffix = 'min.js';
|
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
|
|
$suffix = 'js';
|
|
}
|
|
echo '<script>';
|
|
include __DIR__ . '/js/frontend/category-posts-frontend.' . $suffix;
|
|
echo '</script>';
|
|
}
|
|
|
|
/**
|
|
* Enqueue widget related scripts for the widget admin page and customizer.
|
|
*
|
|
* @param string $hook the name of the admin hook for which the function was triggered.
|
|
*/
|
|
function admin_scripts( $hook ) {
|
|
|
|
if ( 'widgets.php' === $hook || 'post.php' === $hook ) { // enqueue only for widget admin and customizer. (add if post.php: fix make widget SiteOrigin Page Builder plugin, GH issue #181).
|
|
|
|
/*
|
|
* Add script to control admin UX.
|
|
*/
|
|
|
|
// Use unminified version of JS when debuging, and minified when not.
|
|
$suffix = 'min.js';
|
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
|
|
$suffix = 'js';
|
|
}
|
|
wp_register_script( 'category-posts-widget-admin-js', plugins_url( 'js/admin/category-posts-widget.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
|
|
wp_enqueue_script( 'category-posts-widget-admin-js' );
|
|
|
|
$js_data = array( 'accordion' => false );
|
|
$meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
|
|
if ( is_array( $meta ) && isset( $meta['panels'] ) ) {
|
|
$js_data['accordion'] = true;
|
|
}
|
|
$js_data['template_tags'] = get_template_tags();
|
|
$js_data[ __NAMESPACE__ ] = $js_data; // To make accessing the data in JS easier to understand.
|
|
|
|
wp_localize_script( 'category-posts-widget-admin-js', 'tiptoppress', $js_data );
|
|
wp_enqueue_media();
|
|
wp_localize_script(
|
|
'category-posts-widget-admin-js',
|
|
'cwp_default_thumb_selection',
|
|
array(
|
|
'frame_title' => __( 'Select a default thumbnail', 'category-posts' ),
|
|
'button_title' => __( 'Select', 'category-posts' ),
|
|
'none' => __( 'None', 'category-posts' ),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\admin_scripts' ); // "called on widgets.php and costumizer since 3.9.
|
|
|
|
add_action( 'admin_init', __NAMESPACE__ . '\load_textdomain' );
|
|
|
|
/**
|
|
* Load plugin textdomain.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 4.1
|
|
**/
|
|
function load_textdomain() {
|
|
load_plugin_textdomain( 'category-posts', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
|
|
}
|
|
|
|
/**
|
|
* Add styles for widget admin sections
|
|
*
|
|
* @since 4.1
|
|
**/
|
|
function admin_styles() {
|
|
wp_enqueue_style( 'cat-posts-admin-styles', plugins_url( 'styles/admin/category-posts-widget.css', __FILE__ ), array(), VERSION, false );
|
|
}
|
|
|
|
add_action( 'admin_print_styles-widgets.php', __NAMESPACE__ . '\admin_styles' );
|
|
|
|
// fix make widget SiteOrigin Page Builder plugin, GH issue #181.
|
|
add_action( 'siteorigin_panel_enqueue_admin_scripts', __NAMESPACE__ . '\admin_styles' );
|
|
|
|
/**
|
|
* Get the tags which might be used in the template.
|
|
*
|
|
* @since 4.8
|
|
*
|
|
* @return array Array of strings of the tags.
|
|
*/
|
|
function get_template_tags() {
|
|
return array( 'author', 'title', 'date', 'thumb', 'excerpt', 'commentnum', 'post_tag', 'category', 'more-link' );
|
|
}
|
|
|
|
/**
|
|
* Get a regex to parse the template in order to find the tags used in it.
|
|
*
|
|
* @since 4.8
|
|
*
|
|
* @return string The template parsing regex.
|
|
*/
|
|
function get_template_regex() {
|
|
$tags = get_template_tags();
|
|
|
|
$regexp = '';
|
|
foreach ( $tags as $t ) {
|
|
if ( ! empty( $regexp ) ) {
|
|
$regexp .= '|';
|
|
}
|
|
$regexp .= '%' . $t . '%';
|
|
}
|
|
|
|
$regexp = '@(' . $regexp . ')@i';
|
|
|
|
return $regexp;
|
|
}
|
|
|
|
/**
|
|
* The convert old data structure to current one.
|
|
*
|
|
* @param array $settings The settings to upgrade.
|
|
*
|
|
* @return array The settings matching current version standard.
|
|
*
|
|
* @since 4.8
|
|
*/
|
|
function upgrade_settings( $settings ) {
|
|
|
|
if ( isset( $setting ) && is_countable( $setting ) && 0 === count( $settings ) ) {
|
|
return default_settings();
|
|
}
|
|
|
|
if ( ! isset( $settings['ver'] ) ) {
|
|
/*
|
|
* Pre 4.9 version.
|
|
*/
|
|
|
|
// Upgrade the hide if empty option.
|
|
if ( isset( $settings['hide_if_empty'] ) && $settings['hide_if_empty'] ) {
|
|
$settings['no_match_handling'] = 'hide';
|
|
} else {
|
|
$settings['no_match_handling'] = 'nothing';
|
|
}
|
|
if ( isset( $settings['hide_if_empty'] ) ) {
|
|
unset( $settings['hide_if_empty'] );
|
|
}
|
|
} else {
|
|
if ( version_compare( '4.9.8', $settings['ver']) ) {
|
|
if ( isset( $settings['preset_date_format'] ) && 'sincepublished' === $settings['preset_date_format'] ) {
|
|
$settings['date_past_time'] = 999;
|
|
$settings['preset_date_format'] = 'sitedate';
|
|
}
|
|
}
|
|
}
|
|
|
|
$settings['ver'] = VERSION;
|
|
|
|
// Make sure all "empty" settings have default value.
|
|
$settings = wp_parse_args( $settings, default_settings() );
|
|
|
|
return $settings;
|
|
}
|
|
|
|
/**
|
|
* Convert pre 4.8 settings into template
|
|
*
|
|
* @param array $instance Array which contains the various settings.
|
|
*
|
|
* @since 4.8
|
|
*/
|
|
function convert_settings_to_template( $instance ) {
|
|
|
|
$template = '';
|
|
|
|
if ( isset( $instance['thumb'] ) && $instance['thumb'] ) {
|
|
if ( isset( $instance['thumbTop'] ) && $instance['thumbTop'] ) {
|
|
$template .= "%thumb%\n\n";
|
|
if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
|
|
$template .= "%title%\n";
|
|
}
|
|
} elseif ( isset( $instance['date'] ) && $instance['date'] ) {
|
|
if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
|
|
$template .= "%title%\n\n";
|
|
}
|
|
$template .= "%date%\n\n";
|
|
$template .= "%thumb%\n";
|
|
} elseif ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
|
|
$template .= "%thumb%\n%title%\n";
|
|
}
|
|
} else {
|
|
if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
|
|
$template .= "%title%\n";
|
|
}
|
|
if ( isset( $instance['date'] ) && $instance['date'] ) {
|
|
$template .= "%date%\n\n";
|
|
}
|
|
}
|
|
if ( isset( $instance['excerpt'] ) && $instance['excerpt'] ) {
|
|
$template .= '%excerpt%';
|
|
}
|
|
if ( isset( $instance['comment_num'] ) && $instance['comment_num'] ) {
|
|
$template .= "%commentnum%\n\n";
|
|
}
|
|
if ( isset( $instance['author'] ) && $instance['author'] ) {
|
|
$template .= "%author%\n\n";
|
|
}
|
|
|
|
return $template;
|
|
}
|
|
|
|
/*
|
|
* Plugin action links section
|
|
*/
|
|
|
|
/**
|
|
* Applied to the list of links to display on the plugins page (beside the activate/deactivate links).
|
|
*
|
|
* @return array of the widget links
|
|
*
|
|
* @since 4.6.3
|
|
*/
|
|
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), __NAMESPACE__ . '\add_action_links' );
|
|
|
|
/**
|
|
* Handle the add links filter, add our links to the links displayed under the plugin_basename
|
|
* in the plugin admin screen.
|
|
*
|
|
* @param array $links The current links about to be displayed.
|
|
*/
|
|
function add_action_links( $links ) {
|
|
|
|
if ( ! class_exists( '\\termcategoryPostsPro\\Widget' ) ) {
|
|
$pro_link = array(
|
|
'<a target="_blank" href="' . esc_url( PRO_URL ) . '">' . esc_html__( 'Get the Pro version', 'category-posts' ) . '</a>',
|
|
);
|
|
|
|
$links = array_merge( $pro_link, $links );
|
|
}
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Register the widget.
|
|
*/
|
|
function register_widget() {
|
|
return \register_widget( __NAMESPACE__ . '\Widget' );
|
|
}
|
|
|
|
add_action( 'widgets_init', __NAMESPACE__ . '\register_widget' );
|
|
|
|
/**
|
|
* Output js code to set the image height if float text around image.
|
|
*
|
|
* @param int $number The widget number used to identify the specific list.
|
|
* @param array $widgetsettings The "instance" parameters of the widget.
|
|
*
|
|
* @since 4.9
|
|
**/
|
|
function equal_cover_content_height( $number, $widgetsettings ) {
|
|
|
|
if ( isset( $widgetsettings['template'] ) && preg_match( '/%thumb%|%excerpt%/', $widgetsettings['template'] ) ) :
|
|
?>
|
|
<script type="text/javascript">
|
|
if (typeof jQuery !== 'undefined') {
|
|
|
|
var cat_posts_namespace = window.cat_posts_namespace || {};
|
|
cat_posts_namespace.layout_wrap_text = cat_posts_namespace.layout_wrap_text || {};
|
|
cat_posts_namespace.layout_img_size = cat_posts_namespace.layout_img_size || {};
|
|
|
|
cat_posts_namespace.layout_wrap_text = {
|
|
<?php /* Handle item */ echo "\r\n"; ?>
|
|
preWrap : function (widget) {
|
|
jQuery(widget).find('.cat-post-item').each(function(){
|
|
var _that = jQuery(this);
|
|
_that.find('p.cpwp-excerpt-text').addClass('cpwp-wrap-text');
|
|
_that.find('p.cpwp-excerpt-text').closest('div').wrap('<div class="cpwp-wrap-text-stage"></div>');
|
|
});
|
|
return;
|
|
},
|
|
<?php /* Handle add class */ echo "\r\n"; ?>
|
|
add : function(_this){
|
|
var _that = jQuery(_this);
|
|
if (_that.find('p.cpwp-excerpt-text').height() < _that.find('.cat-post-thumbnail').height()) { <?php /* don't move class to do the CSS hack, line's height is smaller as thumb */ echo "\r\n"; ?>
|
|
_that.find('p.cpwp-excerpt-text').closest('.cpwp-wrap-text-stage').removeClass( "cpwp-wrap-text" );
|
|
_that.find('p.cpwp-excerpt-text').addClass( "cpwp-wrap-text" ); <?php /* don't do the CSS hack, just set the class */ echo "\r\n"; ?>
|
|
}else{ <?php /* add the CSS hack, it's needed, text is wrapping, line's height is higher as thumb */ echo "\r\n"; ?>
|
|
_that.find('p.cpwp-excerpt-text').removeClass( "cpwp-wrap-text" );
|
|
_that.find('p.cpwp-excerpt-text').closest('.cpwp-wrap-text-stage').addClass( "cpwp-wrap-text" ); <?php /* text is wrapping, do the CSS hack */ echo "\r\n"; ?>
|
|
}
|
|
return;
|
|
},
|
|
<?php /* Wait for image is loaded */ echo "\r\n"; ?>
|
|
handleLazyLoading : function(_this) {
|
|
var width = jQuery(_this).find('img').width();
|
|
<?php /* image is loaded */ echo "\r\n"; ?>
|
|
if( 0 !== width ){
|
|
cat_posts_namespace.layout_wrap_text.add(_this);
|
|
} else {
|
|
jQuery(_this).find('img').one("load", function(){
|
|
cat_posts_namespace.layout_wrap_text.add(_this);
|
|
});
|
|
}
|
|
return;
|
|
},
|
|
<?php /* Handle post items */ echo "\r\n"; ?>
|
|
setClass : function (widget) {
|
|
// var _widget = jQuery(widget);
|
|
jQuery(widget).find('.cat-post-item').each(function(){
|
|
cat_posts_namespace.layout_wrap_text.handleLazyLoading(this);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
cat_posts_namespace.layout_img_size = {
|
|
<?php /* Handle replace */ echo "\r\n"; ?>
|
|
replace : function(_this){
|
|
var _that = jQuery(_this),
|
|
resp_w = _that.width(),
|
|
resp_h = _that.height(),
|
|
orig_w = _that.data('cat-posts-width'),
|
|
orig_h = _that.data('cat-posts-height');
|
|
<?php /* replace height */ echo "\r\n"; ?>
|
|
if( resp_w < orig_w ){
|
|
_that.height( resp_w * orig_h / orig_w );
|
|
} else {
|
|
_that.height( '' );
|
|
}
|
|
return;
|
|
},
|
|
<?php /* Wait for image is loaded */ echo "\r\n"; ?>
|
|
handleLazyLoading : function(_this) {
|
|
var width = jQuery(_this).width();
|
|
<?php /* image is loaded */ echo "\r\n"; ?>
|
|
if( 0 !== width ){
|
|
cat_posts_namespace.layout_img_size.replace(_this);
|
|
} else {
|
|
jQuery(_this).one("load", function(){
|
|
cat_posts_namespace.layout_img_size.replace(_this);
|
|
});
|
|
}
|
|
return;
|
|
},
|
|
setHeight : function (widget) {
|
|
jQuery(widget).find('.cat-post-item img').each(function(){
|
|
cat_posts_namespace.layout_img_size.handleLazyLoading(this);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
let widget = jQuery('#<?php echo esc_attr( $number ); ?>');
|
|
|
|
jQuery( document ).ready(function () {
|
|
cat_posts_namespace.layout_wrap_text.setClass(widget);
|
|
<?php /* No ratio calculation if one or more dimensions is set to 0 */ echo "\r\n"; ?>
|
|
<?php if ( isset( $widgetsettings['thumb_w'] ) && 0 !== intval( $widgetsettings['thumb_w'] ) &&
|
|
isset( $widgetsettings['thumb_h'] ) && 0 !== intval( $widgetsettings['thumb_h'] ) ) : echo "\r\n"; ?>
|
|
cat_posts_namespace.layout_img_size.setHeight(widget);
|
|
<?php endif; echo "\r\n"; ?>
|
|
});
|
|
|
|
jQuery(window).on('load resize', function() {
|
|
cat_posts_namespace.layout_wrap_text.setClass(widget);
|
|
<?php /* No ratio calculation if one or more dimensions is set to 0 */ echo "\r\n"; ?>
|
|
<?php if ( isset( $widgetsettings['thumb_w'] ) && 0 !== intval( $widgetsettings['thumb_w'] ) &&
|
|
isset( $widgetsettings['thumb_h'] ) && 0 !== intval( $widgetsettings['thumb_h'] ) ) : echo "\r\n"; ?>
|
|
cat_posts_namespace.layout_img_size.setHeight(widget);
|
|
<?php endif; echo "\r\n"; ?>
|
|
});
|
|
|
|
// low-end mobile
|
|
cat_posts_namespace.layout_wrap_text.preWrap(widget);
|
|
cat_posts_namespace.layout_wrap_text.setClass(widget);
|
|
<?php /* No ratio calculation if one or more dimensions is set to 0 */ echo "\r\n"; ?>
|
|
<?php if ( isset( $widgetsettings['thumb_w'] ) && 0 !== intval( $widgetsettings['thumb_w'] ) &&
|
|
isset( $widgetsettings['thumb_h'] ) && 0 !== intval( $widgetsettings['thumb_h'] ) ) : echo "\r\n"; ?>
|
|
cat_posts_namespace.layout_img_size.setHeight(widget);
|
|
<?php endif; echo "\r\n"; ?>
|
|
|
|
}
|
|
</script>
|
|
<?php
|
|
endif;
|
|
}
|
|
|
|
/*
|
|
* shortcode section.
|
|
*/
|
|
|
|
/**
|
|
* Get shortcode settings taking into account if it is being customized
|
|
*
|
|
* When not customized returns the settings as stored in the meta, but when
|
|
* it is customized returns the setting stored in the virtual option used by the customizer
|
|
*
|
|
* @param string $pid The ID of the post in which the shortcode is.
|
|
* @param string $name The name of the shortcode to retun, empty string indicates the nameless.
|
|
*
|
|
* @return array The shortcode settings if a short code name exists or is an empty string,
|
|
* empty array if name not found.
|
|
*
|
|
* @since 4.6
|
|
*/
|
|
function shortcode_settings( $pid, $name ) {
|
|
$meta = get_post_meta( $pid, SHORTCODE_META, true );
|
|
|
|
if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
|
|
$meta = array( '' => $meta ); // the conversion.
|
|
}
|
|
|
|
if ( ! isset( $meta[ $name ] ) ) { // name do not exists? return empty array.
|
|
return array();
|
|
}
|
|
|
|
$instance = $meta[ $name ];
|
|
if ( is_customize_preview() ) {
|
|
$o = get_option( '_virtual-' . WIDGET_BASE_ID );
|
|
if ( is_array( $o ) ) {
|
|
$instance = $o[ $pid ][ $name ];
|
|
$instance['ver'] = VERSION;
|
|
}
|
|
}
|
|
|
|
if ( isset( $instance['template'] ) && $instance['template'] ) {
|
|
;
|
|
} else {
|
|
$instance['template'] = convert_settings_to_template( $instance );
|
|
}
|
|
|
|
$instance = upgrade_settings( $instance );
|
|
|
|
return $instance;
|
|
}
|
|
|
|
/**
|
|
* Handle the shortcode
|
|
*
|
|
* @param array $attr Array of the attributes to the short code, none is expected.
|
|
* @param string $content The content enclosed in the shortcode, none is expected.
|
|
*
|
|
* @return string An HTML of the "widget" based on its settings, actual or customized
|
|
*/
|
|
function shortcode( $attr, $content = null ) {
|
|
$repository = new Virtual_Widgets_Repository();
|
|
|
|
$shortcodes = $repository->getShortcodes();
|
|
|
|
$name = '';
|
|
if ( isset( $attr['name'] ) ) {
|
|
$name = $attr['name'];
|
|
}
|
|
|
|
if ( is_singular() ) {
|
|
if ( isset( $shortcodes[ $name ] ) ) {
|
|
return $shortcodes[ $name ]->getHTML();
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
add_shortcode( SHORTCODE_NAME, __NAMESPACE__ . '\shortcode' );
|
|
|
|
/**
|
|
* Find if a specific shortcode is used in a content
|
|
*
|
|
* @param string $shortcode_name The name of the shortcode.
|
|
* @param string $content The content to look at.
|
|
*
|
|
* @return array An array containing the name attributes of the shortcodes. Empty array is
|
|
* an indication there were no shourcodes
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function shortcode_names( $shortcode_name, $content ) {
|
|
|
|
$names = array();
|
|
|
|
$regex_pattern = get_shortcode_regex();
|
|
if ( preg_match_all( '/' . $regex_pattern . '/s', $content, $matches ) ) {
|
|
foreach ( $matches[2] as $k => $shortcode ) {
|
|
if ( SHORTCODE_NAME === $shortcode ) {
|
|
$name = '';
|
|
$atts = shortcode_parse_atts( $matches[3][ $k ] );
|
|
if ( ! empty( $atts['name'] ) ) {
|
|
$name = $atts['name'];
|
|
}
|
|
$names[] = $name;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $names;
|
|
}
|
|
|
|
/**
|
|
* Organized way to have the default widget settings accessible
|
|
*
|
|
* @since 4.6
|
|
*/
|
|
function default_settings() {
|
|
return array(
|
|
'title' => __( 'Category Posts', 'category-posts' ),
|
|
'title_link' => false,
|
|
'title_level' => 'Initial',
|
|
'title_link_url' => '',
|
|
'hide_title' => false,
|
|
'cat' => 0,
|
|
'num' => get_option( 'posts_per_page' ),
|
|
'offset' => 1,
|
|
'sort_by' => 'date',
|
|
'status' => 'publish',
|
|
'asc_sort_order' => false,
|
|
'exclude_current_post' => false,
|
|
'hideNoThumb' => false,
|
|
'sticky' => false,
|
|
'footer_link_text' => '',
|
|
'footer_link' => '',
|
|
'item_title_level' => 'Inline',
|
|
'item_title_lines' => 2,
|
|
'thumb_w' => get_option( 'thumbnail_size_w', 150 ),
|
|
'thumb_fluid_width' => 100,
|
|
'thumb_h' => get_option( 'thumbnail_size_h', 150 ),
|
|
'thumb_hover' => 'none',
|
|
'hide_post_titles' => false,
|
|
'excerpt_lines' => 4,
|
|
'excerpt_length' => 0,
|
|
'excerpt_more_text' => __( '', 'category-posts' ),
|
|
'excerpt_filters' => false,
|
|
'comment_num' => false,
|
|
'disable_css' => false,
|
|
'disable_font_styles' => false,
|
|
'disable_theme_styles' => false,
|
|
'show_post_format' => 'none',
|
|
'no_cat_childs' => false,
|
|
'everything_is_link' => false,
|
|
'preset_date_format' => 'sitedate',
|
|
'date_format' => '',
|
|
'date_past_time' => '0',
|
|
'template' => "%title%\n\n%thumb%",
|
|
'text_do_not_wrap_thumb' => false,
|
|
'enable_loadmore' => false,
|
|
'loadmore_scrollTo' => false,
|
|
'loadmore_text' => sprintf( __( 'Load More (%s/%s)', 'category-posts' ), '%step%', '%all%'),
|
|
'loading_text' => __( 'Loading...', 'category-posts' ),
|
|
'date_range' => 'off',
|
|
'start_date' => '',
|
|
'end_date' => '',
|
|
'days_ago' => 30,
|
|
'no_match_handling' => 'nothing',
|
|
'no_match_text' => '',
|
|
'default_thunmbnail' => 0,
|
|
'ver' => VERSION,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Manipulate the relevant meta related to the short code when a post is save
|
|
*
|
|
* If A post has a short code, a meta holder is created, If it does not the meta holder is deleted
|
|
*
|
|
* @param integer $pid The post ID of the post being saved.
|
|
* @param WP_Post $post The post being saved.
|
|
* @return void
|
|
*
|
|
* @since 4.6
|
|
*/
|
|
function save_post( $pid, $post ) {
|
|
|
|
// ignore revisions and auto saves.
|
|
if ( wp_is_post_revision( $pid ) || wp_is_post_autosave( $pid ) ) {
|
|
return;
|
|
}
|
|
|
|
$meta = get_post_meta( $pid, SHORTCODE_META, true );
|
|
if ( empty( $meta ) ) {
|
|
$meta = array();
|
|
}
|
|
|
|
// check if only one shortcode format - non array of arrays, and convert it.
|
|
if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
|
|
$meta = array( '' => $meta ); // the conversion.
|
|
}
|
|
|
|
$old_names = array_keys( $meta ); // keep list of current shortcode names to delete lter whatever was deleted.
|
|
$names = shortcode_names( SHORTCODE_NAME, $post->post_content );
|
|
|
|
// remove setting for unused names.
|
|
$to_delete = array_diff( $old_names, $names );
|
|
foreach ( $to_delete as $k ) {
|
|
unset( $meta[ $k ] );
|
|
}
|
|
|
|
foreach ( $names as $name ) {
|
|
if ( ! isset( $meta[ $name ] ) ) {
|
|
$meta[ $name ] = default_settings();
|
|
}
|
|
}
|
|
|
|
delete_post_meta( $pid, SHORTCODE_META );
|
|
if ( ! empty( $meta ) ) {
|
|
add_post_meta( $pid, SHORTCODE_META, $meta, true );
|
|
}
|
|
}
|
|
|
|
add_action( 'save_post', __NAMESPACE__ . '\save_post', 10, 2 );
|
|
|
|
/**
|
|
* Called on Customizer init to do related registrations.
|
|
*
|
|
* @param mixed $wp_customize The customizer object.
|
|
*/
|
|
function customize_register( $wp_customize ) {
|
|
|
|
require_once __DIR__ . '/class-shortcode-control.php';
|
|
|
|
$args = array(
|
|
'post_type' => 'any',
|
|
'post_status' => 'any',
|
|
'posts_per_page' => -1,
|
|
'update_post_term_cache' => false,
|
|
'meta_query' => array(
|
|
array(
|
|
'key' => SHORTCODE_META,
|
|
'compare' => 'EXISTS',
|
|
),
|
|
),
|
|
|
|
);
|
|
$posts = get_posts( $args );
|
|
|
|
if ( count( $posts ) > 0 ) {
|
|
$wp_customize->add_panel(
|
|
__NAMESPACE__,
|
|
array(
|
|
'title' => __( 'Category Posts Shortcode', 'category-posts' ),
|
|
'priority' => 300,
|
|
'capability' => 'edit_theme_options',
|
|
)
|
|
);
|
|
|
|
foreach ( $posts as $p ) {
|
|
$widget = new Widget();
|
|
$meta = get_post_meta( $p->ID, SHORTCODE_META, true );
|
|
if ( ! is_array( $meta ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( ! is_array( reset( $meta ) ) ) { // 4.6 format.
|
|
$meta = array( '' => $meta );
|
|
}
|
|
|
|
foreach ( $meta as $k => $m ) {
|
|
|
|
if ( isset( $m['template'] ) && $m['template'] ) {
|
|
;
|
|
} else {
|
|
$m['template'] = convert_settings_to_template( $m );
|
|
}
|
|
|
|
if ( 0 === count( $meta ) ) { // new widget, use defaults.
|
|
;
|
|
} else { // updated widgets come from =< 4.6 excerpt filter is on.
|
|
if ( ! isset( $m['excerpt_filters'] ) ) {
|
|
$m['excerpt_filters'] = 'on';
|
|
}
|
|
}
|
|
|
|
$m = upgrade_settings( $m );
|
|
|
|
$section_title = $k;
|
|
if ( '' === $section_title ) {
|
|
$section_title = __( '[shortcode]', 'category-posts' );
|
|
}
|
|
|
|
$wp_customize->add_section(
|
|
__NAMESPACE__ . '-' . $p->id . '-' . $k,
|
|
array(
|
|
'title' => $section_title,
|
|
'priority' => 10,
|
|
'capability' => 'edit_theme_options',
|
|
'panel' => __NAMESPACE__,
|
|
)
|
|
);
|
|
|
|
ob_start();
|
|
|
|
// For the form method to handle generation gracefully, the number needs to be a simple string, and the name might include other chars as well, so for simplisity md5 it.
|
|
if ( '' !== $k ) {
|
|
$widget->number = $p->ID . '_' . md5( $k );
|
|
} else {
|
|
$widget->number = $p->ID . '_';
|
|
}
|
|
|
|
$widget->form( $m );
|
|
$form = ob_get_clean();
|
|
$form = preg_replace_callback(
|
|
'/<(input|select|textarea)\s+.*name=("|\').*\[\w*\]\[([^\]]*)\][^>]*>/',
|
|
function ( $matches ) use ( $p, $wp_customize, $m, $k ) {
|
|
$setting = '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][' . $matches[3] . ']';
|
|
if ( ! isset( $m[ $matches[3] ] ) ) {
|
|
$m[ $matches[3] ] = null;
|
|
}
|
|
$wp_customize->add_setting(
|
|
$setting,
|
|
array(
|
|
'default' => $m[ $matches[3] ], // set default to current value.
|
|
'type' => 'option',
|
|
)
|
|
);
|
|
|
|
return str_replace( '<' . $matches[1], '<' . $matches[1] . ' data-customize-setting-link="' . $setting . '"', $matches[0] );
|
|
},
|
|
$form
|
|
);
|
|
|
|
$args = array(
|
|
'label' => __( 'Layout', 'twentyfourteen' ),
|
|
'section' => __NAMESPACE__ . '-' . $p->id . '-' . $k,
|
|
'form' => $form,
|
|
'settings' => '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
|
|
'active_callback' => function () use ( $p ) {
|
|
return is_singular() && ( get_the_ID() === $p->ID );
|
|
},
|
|
);
|
|
|
|
if ( get_option( 'page_on_front' ) === $p->ID ) {
|
|
$args['active_callback'] = function () {
|
|
return is_front_page();
|
|
};
|
|
}
|
|
|
|
$sc = new ShortCode_Control(
|
|
$wp_customize,
|
|
'_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
|
|
$args
|
|
);
|
|
|
|
if ( '' !== $k ) {
|
|
$sc->title_postfix = ' ' . $k;
|
|
}
|
|
$wp_customize->add_control( $sc );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
add_action( 'customize_register', __NAMESPACE__ . '\customize_register' );
|
|
|
|
/**
|
|
* Save the virtual option used by the customizer into the proper meta values.
|
|
*
|
|
* The customizer actually saves only the changed values, so a merge needs to be done.
|
|
* After everything is updated the virtual option is deleted to leave a clean slate
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 4.6
|
|
*/
|
|
function customize_save_after() {
|
|
$virtual = get_option( '_virtual-' . WIDGET_BASE_ID );
|
|
|
|
if ( is_array( $virtual ) ) {
|
|
foreach ( $virtual as $pid => $instance ) {
|
|
$meta = get_post_meta( $pid, SHORTCODE_META, true );
|
|
if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
|
|
$meta = array( '' => $meta ); // the conversion.
|
|
}
|
|
|
|
foreach ( $instance as $name => $new ) {
|
|
if ( isset( $meta[ $name ] ) ) { // unlikely but maybe that short code was deleted by other session.
|
|
$meta[ $name ] = array_merge( $meta[ $name ], $new );
|
|
|
|
$meta[ $name ] = upgrade_settings( $meta[ $name ] );
|
|
}
|
|
}
|
|
}
|
|
update_post_meta( $pid, SHORTCODE_META, $meta );
|
|
}
|
|
|
|
delete_option( '_virtual-' . WIDGET_BASE_ID );
|
|
}
|
|
|
|
add_action( 'customize_save_after', __NAMESPACE__ . '\customize_save_after', 100 );
|
|
|
|
/*
|
|
* tinymce related functions.
|
|
*/
|
|
|
|
/**
|
|
* Uninstall handler, cleanup DB from options and meta
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function uninstall() {
|
|
delete_option( 'widget-' . WIDGET_BASE_ID ); // delete the option storing the widget options.
|
|
delete_post_meta_by_key( SHORTCODE_META ); // delete the meta storing the shortcode.
|
|
// delete_metadata( 'user', 0, __NAMESPACE__, '', true ); // delete all user metadata. // df 2024-03-26 Deletion failed: https://wordpress.org/support/topic/deletion-failed-there-has-been-a-critical-error-on-this-website-5/
|
|
}
|
|
|
|
register_uninstall_hook( __FILE__, __NAMESPACE__ . '\uninstall' );
|
|
|
|
/**
|
|
* Register the tinymce shortcode plugin
|
|
*
|
|
* @param array $plugin_array An array containing the current plugins to be used by tinymce.
|
|
*
|
|
* @return array An array containing the plugins to be used by tinymce, our plugin added to the $plugin_array parameter
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function mce_external_plugins( $plugin_array ) {
|
|
if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
|
|
// enqueue TinyMCE plugin script with its ID.
|
|
$meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
|
|
if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
|
|
;
|
|
} else {
|
|
$plugin_array[ __NAMESPACE__ ] = plugins_url( 'js/admin/tinymce.min.js?ver=' . VERSION, __FILE__ );
|
|
}
|
|
}
|
|
|
|
return $plugin_array;
|
|
}
|
|
|
|
add_filter( 'mce_external_plugins', __NAMESPACE__ . '\mce_external_plugins' );
|
|
|
|
/**
|
|
* Register the tinymce buttons for the add shortcode
|
|
*
|
|
* @param array $buttons An array containing the current buttons to be used by tinymce.
|
|
*
|
|
* @return array An array containing the buttons to be used by tinymce, our button added to the $buttons parameter
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function mce_buttons( $buttons ) {
|
|
if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode
|
|
// register buttons with their id.
|
|
$meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
|
|
if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
|
|
;
|
|
} else {
|
|
array_push( $buttons, __NAMESPACE__ );
|
|
}
|
|
}
|
|
|
|
return $buttons;
|
|
}
|
|
|
|
add_filter( 'mce_buttons', __NAMESPACE__ . '\mce_buttons' );
|
|
|
|
/**
|
|
* Register the tinymcetranslation file
|
|
*
|
|
* @param array $locales An array containing the current translations to be used by tinymce.
|
|
*
|
|
* @return array An array containing the translations to be used by tinymce, our localization added to the $locale parameter
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function mce_external_languages( $locales ) {
|
|
if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
|
|
$meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
|
|
if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
|
|
;
|
|
} else {
|
|
$locales['cat-posts'] = plugin_dir_path( __FILE__ ) . 'tinymce-translations.php';
|
|
}
|
|
}
|
|
|
|
return $locales;
|
|
}
|
|
|
|
add_filter( 'mce_external_languages', __NAMESPACE__ . '\mce_external_languages' );
|
|
|
|
/*
|
|
* user profile related functions.
|
|
*/
|
|
|
|
add_action( 'show_user_profile', __NAMESPACE__ . '\show_user_profile' );
|
|
add_action( 'edit_user_profile', __NAMESPACE__ . '\show_user_profile' );
|
|
|
|
/**
|
|
* Display the user specific setting on its profile page
|
|
*
|
|
* @param WP_user $user The user for which the profile page displays information.
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function show_user_profile( $user ) {
|
|
|
|
if ( ! current_user_can( 'edit_user', $user->ID ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( ! current_user_can( 'edit_theme_options', $user->ID ) ) {
|
|
return;
|
|
}
|
|
|
|
$meta = get_the_author_meta( __NAMESPACE__, $user->ID );
|
|
|
|
if ( empty( $meta ) ) {
|
|
$meta = array();
|
|
}
|
|
|
|
$accordion = false;
|
|
if ( isset( $meta['panels'] ) ) {
|
|
$accordion = true;
|
|
}
|
|
|
|
$editor = false;
|
|
if ( isset( $meta['editor'] ) ) {
|
|
$editor = true;
|
|
}
|
|
?>
|
|
<h3 id="<?php echo __NAMESPACE__; ?>"><?php esc_html_e( 'Category Posts Widget behaviour settings', 'category-posts' ); ?></h3>
|
|
|
|
<table class="form-table">
|
|
<tr>
|
|
<th><label for="<?php echo __NAMESPACE__; ?>[panels]"><?php esc_html_e( 'Open panels behavior', 'category-posts' ); ?></label></th>
|
|
<td>
|
|
<input type="checkbox" name="<?php echo __NAMESPACE__; ?>[panels]" id="<?php echo __NAMESPACE__; ?>[panels]" <?php checked( $accordion ); ?>>
|
|
<label for=<?php echo __NAMESPACE__; ?>[panels]><?php esc_html_e( 'Close the currently open panel when opening a new one', 'category-posts' ); ?></label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th><label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Visual editor button', 'category-posts' ); ?></label></th>
|
|
<td>
|
|
<input type="checkbox" name="<?php echo __NAMESPACE__; ?>[editor]" id="<?php echo __NAMESPACE__; ?>[editor]" <?php checked( $editor ); ?>>
|
|
<label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Hide the "insert shortcode" button from the editor', 'category-posts' ); ?></label>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
add_action( 'personal_options_update', __NAMESPACE__ . '\personal_options_update' );
|
|
add_action( 'edit_user_profile_update', __NAMESPACE__ . '\personal_options_update' );
|
|
|
|
/**
|
|
* Handles saving user related settings as was set in the profile page.
|
|
*
|
|
* @param int $user_id the ID of the user for which the data is saved..
|
|
*
|
|
* @since 4.7
|
|
*/
|
|
function personal_options_update( $user_id ) {
|
|
|
|
if ( ! current_user_can( 'edit_user', $user_id ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( ! current_user_can( 'edit_theme_options', $user_id ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( isset( $_POST[ __NAMESPACE__ ] ) ) {
|
|
update_user_meta( $user_id, __NAMESPACE__, wp_unslash( $_POST[ __NAMESPACE__ ] ) );
|
|
} else {
|
|
delete_user_meta( $user_id, __NAMESPACE__ );
|
|
}
|
|
}
|
|
|
|
add_action( 'wp_loaded', __NAMESPACE__ . '\wp_loaded' );
|
|
|
|
/**
|
|
* Run after WordPress finished bootstrapping, do whatever is needed at this stage
|
|
* like registering the meta.
|
|
*/
|
|
function wp_loaded() {
|
|
register_meta( 'post', SHORTCODE_META, null, '__return_false' ); // do not allow access to the shortcode meta
|
|
// use the pre 4.6 format for backward compatibility.
|
|
}
|