From 00935df91eb727fcd881b31bcc65dc0ae9ffa69f Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Tue, 31 May 2016 17:51:53 +0100
Subject: [PATCH 01/11] Initial code for User Select field
---
inc/fields/class-field-user-select.php | 167 +++++++++++++
js/build/shortcode-ui.js | 219 +++++++++++++++++-
.../views/edit-attribute-field-user-select.js | 194 ++++++++++++++++
js/src/views/edit-shortcode-form.js | 3 +-
shortcode-ui.php | 4 +-
5 files changed, 574 insertions(+), 13 deletions(-)
create mode 100644 inc/fields/class-field-user-select.php
create mode 100644 js/src/views/edit-attribute-field-user-select.js
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
new file mode 100644
index 00000000..6e18f52b
--- /dev/null
+++ b/inc/fields/class-field-user-select.php
@@ -0,0 +1,167 @@
+ array(
+ 'template' => 'shortcode-ui-field-user-select',
+ 'view' => 'editAttributeFieldUserSelect',
+ ),
+ );
+
+ /**
+ * Setup the instance.
+ *
+ * @return Shortcode_UI_Field_User_Select
+ */
+ public static function get_instance() {
+
+ if ( ! isset( self::$instance ) ) {
+ self::$instance = new self;
+ self::$instance->setup_actions();
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Add the required actions and filters.
+ */
+ private function setup_actions() {
+
+ add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
+ add_action( 'enqueue_shortcode_ui', array( $this, 'action_enqueue_shortcode_ui' ) );
+ add_action( 'wp_ajax_shortcode_ui_user_field', array( $this, 'action_wp_ajax_shortcode_ui_user_field' ) );
+ add_action( 'shortcode_ui_loaded_editor', array( $this, 'action_shortcode_ui_loaded_editor' ) );
+ }
+
+ /**
+ * Add our field to the shortcode fields.
+ *
+ * @param $fields
+ *
+ * @return array
+ */
+ public function filter_shortcode_ui_fields( $fields ) {
+
+ return array_merge( $fields, $this->fields );
+ }
+
+ /**
+ * Add Select2 for our UI.
+ */
+ public function action_enqueue_shortcode_ui() {
+
+ $plugin_dir = dirname( dirname( __FILE__ ) );
+
+ wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ), array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
+ wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
+
+ wp_localize_script( 'shortcode-ui', 'shortcodeUiUserFieldData', array(
+ 'nonce' => wp_create_nonce( 'shortcode_ui_field_user_select' ),
+ ) );
+ }
+
+ /**
+ * Output styles and templates used by user select field.
+ */
+ public function action_shortcode_ui_loaded_editor() {
+ ?>
+
+
+
+
+
+ post_fields
+ * Supports passing page number and search query string.
+ *
+ * @return null
+ */
+ public function action_wp_ajax_shortcode_ui_user_field() {
+
+ $nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( $_GET['nonce'] ) : null;
+ $requested_shortcode = isset( $_GET['shortcode'] ) ? sanitize_text_field( $_GET['shortcode'] ) : null;
+ $requested_attr = isset( $_GET['attr'] ) ? sanitize_text_field( $_GET['attr'] ) : null;
+ $response = array( 'users' => array(), 'found_users' => 0, 'users_per_page' => 0 );
+
+ if ( ! wp_verify_nonce( $nonce, 'shortcode_ui_field_user_select' ) ) {
+ wp_send_json_error( $response );
+ }
+
+ $shortcodes = Shortcode_UI::get_instance()->get_shortcodes();
+
+ // Shortcode not found.
+ if ( ! isset( $shortcodes[ $requested_shortcode ] ) ) {
+ wp_send_json_error( $response );
+ }
+
+ $shortcode = $shortcodes[ $requested_shortcode ];
+
+ // Supports WP_User_Query query args.
+ foreach ( $shortcode['attrs'] as $attr ) {
+ if ( $attr['attr'] === $requested_attr && isset( $attr['query'] ) ) {
+ $query_args = $attr['query'];
+ }
+ }
+
+ // Hardcoded user query args.
+ $query_args['search_columns'] = array( 'ID', 'user_login', 'user_nicename', 'user_email' );
+
+ if ( isset( $_GET['page'] ) ) {
+ $query_args['paged'] = sanitize_text_field( $_GET['page'] );
+ }
+
+ if ( ! empty( $_GET['s'] ) ) {
+ $query_args['search'] = sanitize_text_field( $_GET['s'] );
+ }
+
+ $query = new WP_User_Query( $query_args );
+
+ foreach ( $query->get_results() as $user ) {
+ array_push( $response['users'], array(
+ 'id' => $user->ID,
+ 'text' => html_entity_decode( $user->display_name ),
+ ) );
+ }
+
+ $response['found_users'] = $query->get_total();
+ $response['users_per_page'] = $query->query_vars['number'];
+
+ wp_send_json_success( $response );
+ }
+}
diff --git a/js/build/shortcode-ui.js b/js/build/shortcode-ui.js
index 66e7f002..6f1f7cb7 100644
--- a/js/build/shortcode-ui.js
+++ b/js/build/shortcode-ui.js
@@ -281,7 +281,7 @@ $(document).ready(function(){
});
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./collections/shortcodes.js":2,"./utils/shortcode-view-constructor.js":9,"./utils/sui.js":10,"./views/media-frame.js":19}],8:[function(require,module,exports){
+},{"./collections/shortcodes.js":2,"./utils/shortcode-view-constructor.js":9,"./utils/sui.js":10,"./views/media-frame.js":20}],8:[function(require,module,exports){
(function (global){
var $ = (typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null);
var _ = (typeof window !== "undefined" ? window['_'] : typeof global !== "undefined" ? global['_'] : null);
@@ -1049,7 +1049,7 @@ sui.views.editAttributeFieldColor = editAttributeField.extend({
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../utils/sui.js":10,"./edit-attribute-field.js":15}],13:[function(require,module,exports){
+},{"./../utils/sui.js":10,"./edit-attribute-field.js":16}],13:[function(require,module,exports){
( function( $ ) {
var sui = window.Shortcode_UI;
@@ -1443,6 +1443,202 @@ sui.views.editAttributeFieldColor = editAttributeField.extend({
} )( jQuery );
},{}],15:[function(require,module,exports){
+( function( $ ) {
+
+ var sui = window.Shortcode_UI;
+
+ // Cached Data.
+ var userSelectCache = {};
+
+ sui.views.editAttributeFieldUserSelect = sui.views.editAttributeField.extend( {
+
+ events: {
+ 'change .shortcode-ui-user-select': 'inputChanged',
+ },
+
+ inputChanged: function(e) {
+ this.setValue( e.val );
+ this.triggerCallbacks();
+ },
+
+ render: function() {
+
+ var self = this,
+ defaults = { multiple: false };
+
+ for ( var arg in defaults ) {
+ if ( ! this.model.get( arg ) ) {
+ this.model.set( arg, defaults[ arg ] );
+ }
+ }
+
+ var data = this.model.toJSON();
+ data.id = 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid;
+
+ this.$el.html( this.template( data ) );
+
+ var ajaxData = {
+ action : 'shortcode_ui_user_field',
+ nonce : shortcodeUiUserFieldData.nonce,
+ shortcode : this.shortcode.get( 'shortcode_tag'),
+ attr : this.model.get( 'attr' )
+ };
+
+ var $field = this.$el.find( '.shortcode-ui-user-select' );
+
+ $field.select2({
+
+ placeholder: "Search",
+ multiple: this.model.get( 'multiple' ),
+ ajax: {
+ url: ajaxurl,
+ dataType: 'json',
+ quietMillis: 250,
+ data: function (term, page) {
+ ajaxData.s = term;
+ ajaxData.page = page;
+ return ajaxData;
+ },
+ results: function ( response, page ) {
+
+ if ( ! response.success ) {
+ return { results: {}, more: false };
+ }
+
+ // Cache data for quicker rendering later.
+ userSelectCache = $.extend( userSelectCache, response.data.users );
+
+ var more = ( page * response.data.users_per_page ) < response.data.found_users; // whether or not there are more results available
+ return { results: response.data.users, more: more };
+
+ },
+ },
+
+ /**
+ * Initialize Callback
+ * Used to set render the initial value.
+ * Has to make a request to get the title for the current ID.
+ */
+ initSelection: function(element, callback) {
+
+ var ids, parsedData = [], cached;
+
+ // Convert stored value to array of IDs (int).
+ ids = $(element)
+ .val()
+ .split(',')
+ .map( function (str) { return str.trim(); } )
+ .map( function (str) { return parseInt( str ); } );
+
+ if ( ids.length < 1 ) {
+ return;
+ }
+
+ // Check if there is already cached data.
+ for ( var i = 0; i < ids.length; i++ ) {
+ cached = _.find( userSelectCache, _.matches( { id: ids[i] } ) );
+ if ( cached ) {
+ parsedData.push( cached );
+ }
+ }
+
+ // If not multiple - return single value if we have one.
+ if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
+ callback( parsedData[0] );
+ return;
+ }
+
+ var uncachedIds = _.difference( ids, _.pluck( parsedData, 'id' ) );
+
+ if ( ! uncachedIds.length ) {
+
+ callback( parsedData );
+
+ } else {
+
+ var initAjaxData = jQuery.extend( true, {}, ajaxData );
+ initAjaxData.action = 'shortcode_ui_user_field';
+ initAjaxData.post__in = uncachedIds;
+
+ $.get( ajaxurl, initAjaxData ).done( function( response ) {
+
+ if ( ! response.success ) {
+ return { results: {}, more: false };
+ }
+
+ userSelectCache = $.extend( userSelectCache, response.data.users );
+
+ // If not multi-select, expects single object, not array of objects.
+ if ( ! self.model.get( 'multiple' ) ) {
+ callback( response.data.users[0] );
+ return;
+ }
+
+ // Append new data to cached data.
+ // Sort by original order.
+ parsedData = parsedData
+ .concat( response.data.users )
+ .sort(function (a, b) {
+ if ( ids.indexOf( a.id ) > ids.indexOf( b.id ) ) return 1;
+ if ( ids.indexOf( a.id ) < ids.indexOf( b.id ) ) return -1;
+ return 0;
+ });
+
+ callback( parsedData );
+ return;
+
+ } );
+
+ }
+
+ },
+
+ } );
+
+ // Make multiple values sortable.
+ if ( this.model.get( 'multiple' ) ) {
+ $field.select2('container').find('ul.select2-choices').sortable({
+ containment: 'parent',
+ start: function() { $('.shortcode-ui-user-select').select2('onSortStart'); },
+ update: function() { $('.shortcode-ui-user-select').select2('onSortEnd'); }
+ });
+ }
+
+ return this;
+
+ }
+
+ } );
+
+ /**
+ * Extending SUI Media Controller to hide Select2 UI Drop-Down when menu
+ * changes in Meida modal
+ * 1. going back/forth between different shortcakes (refresh)
+ * 2. changing the menu in left column (deactivate)
+ * 3. @TODO closing the modal.
+ */
+ var mediaController = sui.controllers.MediaController;
+ sui.controllers.MediaController = mediaController.extend({
+
+ refresh: function(){
+ mediaController.prototype.refresh.apply( this, arguments );
+ this.destroySelect2UI();
+ },
+
+ //doesn't need to call parent as it already an "abstract" method in parent to provide callback
+ deactivate: function() {
+ this.destroySelect2UI();
+ },
+
+ destroySelect2UI: function() {
+ $('.shortcode-ui-user-select.select2-container').select2( "close" );
+ }
+
+ });
+
+} )( jQuery );
+
+},{}],16:[function(require,module,exports){
(function (global){
var Backbone = (typeof window !== "undefined" ? window['Backbone'] : typeof global !== "undefined" ? global['Backbone'] : null),
sui = require('./../utils/sui.js'),
@@ -1585,7 +1781,7 @@ sui.views.editAttributeField = editAttributeField;
module.exports = editAttributeField;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../utils/sui.js":10}],16:[function(require,module,exports){
+},{"./../utils/sui.js":10}],17:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null),
sui = require('./../utils/sui.js'),
@@ -1597,7 +1793,8 @@ backbone = (typeof window !== "undefined" ? window['Backbone'] : typeof global !
editAttributeFieldAttachment = require('./edit-attribute-field-attachment.js'),
editAttributeFieldPostSelect = require('./edit-attribute-field-post-select.js'),
editAttributeFieldTermSelect = require('./edit-attribute-field-term-select.js'),
- editAttributeFieldColor = require('./edit-attribute-field-color.js');
+ editAttributeFieldUserSelect = require('./edit-attribute-field-user-select.js'),
+ editAttributeFieldColor = require('./edit-attribute-field-color.js');
/**
@@ -1670,7 +1867,7 @@ var EditShortcodeForm = wp.Backbone.View.extend({
module.exports = EditShortcodeForm;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../utils/sui.js":10,"./edit-attribute-field-attachment.js":11,"./edit-attribute-field-color.js":12,"./edit-attribute-field-post-select.js":13,"./edit-attribute-field-term-select.js":14,"./edit-attribute-field.js":15}],17:[function(require,module,exports){
+},{"./../utils/sui.js":10,"./edit-attribute-field-attachment.js":11,"./edit-attribute-field-color.js":12,"./edit-attribute-field-post-select.js":13,"./edit-attribute-field-term-select.js":14,"./edit-attribute-field-user-select.js":15,"./edit-attribute-field.js":16}],18:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null),
$ = (typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null);
@@ -1704,7 +1901,7 @@ var insertShortcodeListItem = wp.Backbone.View.extend({
module.exports = insertShortcodeListItem;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],18:[function(require,module,exports){
+},{}],19:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null);
var Backbone = (typeof window !== "undefined" ? window['Backbone'] : typeof global !== "undefined" ? global['Backbone'] : null);
@@ -1751,7 +1948,7 @@ var insertShortcodeList = wp.Backbone.View.extend({
module.exports = insertShortcodeList;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../collections/shortcodes.js":2,"./insert-shortcode-list-item.js":17}],19:[function(require,module,exports){
+},{"./../collections/shortcodes.js":2,"./insert-shortcode-list-item.js":18}],20:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null),
$ = (typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null),
@@ -1875,7 +2072,7 @@ var mediaFrame = postMediaFrame.extend( {
module.exports = mediaFrame;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../controllers/media-controller.js":3,"./media-toolbar":20,"./shortcode-ui":22}],20:[function(require,module,exports){
+},{"./../controllers/media-controller.js":3,"./media-toolbar":21,"./shortcode-ui":23}],21:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null);
@@ -1907,7 +2104,7 @@ var Toolbar = wp.media.view.Toolbar.extend({
module.exports = Toolbar;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],21:[function(require,module,exports){
+},{}],22:[function(require,module,exports){
(function (global){
var wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null);
sui = require('./../utils/sui.js');
@@ -1955,7 +2152,7 @@ sui.views.SearchShortcode = SearchShortcode;
module.exports = SearchShortcode;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../utils/sui.js":10}],22:[function(require,module,exports){
+},{"./../utils/sui.js":10}],23:[function(require,module,exports){
(function (global){
var Backbone = (typeof window !== "undefined" ? window['Backbone'] : typeof global !== "undefined" ? global['Backbone'] : null),
insertShortcodeList = require('./insert-shortcode-list.js'),
@@ -2060,4 +2257,4 @@ var Shortcode_UI = Backbone.View.extend({
module.exports = Shortcode_UI;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./../utils/sui.js":10,"./edit-shortcode-form.js":16,"./insert-shortcode-list.js":18,"./media-toolbar.js":20,"./search-shortcode.js":21}]},{},[7]);
+},{"./../utils/sui.js":10,"./edit-shortcode-form.js":17,"./insert-shortcode-list.js":19,"./media-toolbar.js":21,"./search-shortcode.js":22}]},{},[7]);
diff --git a/js/src/views/edit-attribute-field-user-select.js b/js/src/views/edit-attribute-field-user-select.js
new file mode 100644
index 00000000..ff761d12
--- /dev/null
+++ b/js/src/views/edit-attribute-field-user-select.js
@@ -0,0 +1,194 @@
+( function( $ ) {
+
+ var sui = window.Shortcode_UI;
+
+ // Cached Data.
+ var userSelectCache = {};
+
+ sui.views.editAttributeFieldUserSelect = sui.views.editAttributeField.extend( {
+
+ events: {
+ 'change .shortcode-ui-user-select': 'inputChanged',
+ },
+
+ inputChanged: function(e) {
+ this.setValue( e.val );
+ this.triggerCallbacks();
+ },
+
+ render: function() {
+
+ var self = this,
+ defaults = { multiple: false };
+
+ for ( var arg in defaults ) {
+ if ( ! this.model.get( arg ) ) {
+ this.model.set( arg, defaults[ arg ] );
+ }
+ }
+
+ var data = this.model.toJSON();
+ data.id = 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid;
+
+ this.$el.html( this.template( data ) );
+
+ var ajaxData = {
+ action : 'shortcode_ui_user_field',
+ nonce : shortcodeUiUserFieldData.nonce,
+ shortcode : this.shortcode.get( 'shortcode_tag'),
+ attr : this.model.get( 'attr' )
+ };
+
+ var $field = this.$el.find( '.shortcode-ui-user-select' );
+
+ $field.select2({
+
+ placeholder: "Search",
+ multiple: this.model.get( 'multiple' ),
+ ajax: {
+ url: ajaxurl,
+ dataType: 'json',
+ quietMillis: 250,
+ data: function (term, page) {
+ ajaxData.s = term;
+ ajaxData.page = page;
+ return ajaxData;
+ },
+ results: function ( response, page ) {
+
+ if ( ! response.success ) {
+ return { results: {}, more: false };
+ }
+
+ // Cache data for quicker rendering later.
+ userSelectCache = $.extend( userSelectCache, response.data.users );
+
+ var more = ( page * response.data.users_per_page ) < response.data.found_users; // whether or not there are more results available
+ return { results: response.data.users, more: more };
+
+ },
+ },
+
+ /**
+ * Initialize Callback
+ * Used to set render the initial value.
+ * Has to make a request to get the title for the current ID.
+ */
+ initSelection: function(element, callback) {
+
+ var ids, parsedData = [], cached;
+
+ // Convert stored value to array of IDs (int).
+ ids = $(element)
+ .val()
+ .split(',')
+ .map( function (str) { return str.trim(); } )
+ .map( function (str) { return parseInt( str ); } );
+
+ if ( ids.length < 1 ) {
+ return;
+ }
+
+ // Check if there is already cached data.
+ for ( var i = 0; i < ids.length; i++ ) {
+ cached = _.find( userSelectCache, _.matches( { id: ids[i] } ) );
+ if ( cached ) {
+ parsedData.push( cached );
+ }
+ }
+
+ // If not multiple - return single value if we have one.
+ if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
+ callback( parsedData[0] );
+ return;
+ }
+
+ var uncachedIds = _.difference( ids, _.pluck( parsedData, 'id' ) );
+
+ if ( ! uncachedIds.length ) {
+
+ callback( parsedData );
+
+ } else {
+
+ var initAjaxData = jQuery.extend( true, {}, ajaxData );
+ initAjaxData.action = 'shortcode_ui_user_field';
+ initAjaxData.post__in = uncachedIds;
+
+ $.get( ajaxurl, initAjaxData ).done( function( response ) {
+
+ if ( ! response.success ) {
+ return { results: {}, more: false };
+ }
+
+ userSelectCache = $.extend( userSelectCache, response.data.users );
+
+ // If not multi-select, expects single object, not array of objects.
+ if ( ! self.model.get( 'multiple' ) ) {
+ callback( response.data.users[0] );
+ return;
+ }
+
+ // Append new data to cached data.
+ // Sort by original order.
+ parsedData = parsedData
+ .concat( response.data.users )
+ .sort(function (a, b) {
+ if ( ids.indexOf( a.id ) > ids.indexOf( b.id ) ) return 1;
+ if ( ids.indexOf( a.id ) < ids.indexOf( b.id ) ) return -1;
+ return 0;
+ });
+
+ callback( parsedData );
+ return;
+
+ } );
+
+ }
+
+ },
+
+ } );
+
+ // Make multiple values sortable.
+ if ( this.model.get( 'multiple' ) ) {
+ $field.select2('container').find('ul.select2-choices').sortable({
+ containment: 'parent',
+ start: function() { $('.shortcode-ui-user-select').select2('onSortStart'); },
+ update: function() { $('.shortcode-ui-user-select').select2('onSortEnd'); }
+ });
+ }
+
+ return this;
+
+ }
+
+ } );
+
+ /**
+ * Extending SUI Media Controller to hide Select2 UI Drop-Down when menu
+ * changes in Meida modal
+ * 1. going back/forth between different shortcakes (refresh)
+ * 2. changing the menu in left column (deactivate)
+ * 3. @TODO closing the modal.
+ */
+ var mediaController = sui.controllers.MediaController;
+ sui.controllers.MediaController = mediaController.extend({
+
+ refresh: function(){
+ mediaController.prototype.refresh.apply( this, arguments );
+ this.destroySelect2UI();
+ },
+
+ //doesn't need to call parent as it already an "abstract" method in parent to provide callback
+ deactivate: function() {
+ this.destroySelect2UI();
+ },
+
+ destroySelect2UI: function() {
+ $('.shortcode-ui-user-select.select2-container').select2( "close" );
+ }
+
+ });
+
+} )( jQuery );
diff --git a/js/src/views/edit-shortcode-form.js b/js/src/views/edit-shortcode-form.js
index 8292f849..952f918b 100644
--- a/js/src/views/edit-shortcode-form.js
+++ b/js/src/views/edit-shortcode-form.js
@@ -8,7 +8,8 @@ backbone = require('backbone'),
editAttributeFieldAttachment = require( 'sui-views/edit-attribute-field-attachment' ),
editAttributeFieldPostSelect = require( 'sui-views/edit-attribute-field-post-select' ),
editAttributeFieldTermSelect = require( 'sui-views/edit-attribute-field-term-select' ),
- editAttributeFieldColor = require( 'sui-views/edit-attribute-field-color' );
+ editAttributeFieldUserSelect = require( 'sui-views/edit-attribute-field-user-select' ),
+ editAttributeFieldColor = require( 'sui-views/edit-attribute-field-color' );
/**
diff --git a/shortcode-ui.php b/shortcode-ui.php
index 0492a2d5..0cea695e 100644
--- a/shortcode-ui.php
+++ b/shortcode-ui.php
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*/
-define( 'SHORTCODE_UI_VERSION', '0.7.1-alpha' );
+define( 'SHORTCODE_UI_VERSION', '0.7.2-alpha' );
require_once dirname( __FILE__ ) . '/inc/class-shortcode-ui.php';
require_once dirname( __FILE__ ) . '/inc/fields/class-shortcode-ui-fields.php';
@@ -27,6 +27,7 @@
require_once dirname( __FILE__ ) . '/inc/fields/class-field-color.php';
require_once dirname( __FILE__ ) . '/inc/fields/class-field-post-select.php';
require_once dirname( __FILE__ ) . '/inc/fields/class-field-term-select.php';
+require_once dirname( __FILE__ ) . '/inc/fields/class-field-user-select.php';
add_action( 'init', 'shortcode_ui_load_textdomain' );
@@ -44,6 +45,7 @@ function shortcode_ui_init() {
$color_field = Shortcake_Field_Color::get_instance();
$post_field = Shortcode_UI_Field_Post_Select::get_instance();
$term_field = Shortcode_UI_Field_Term_Select::get_instance();
+ $user_field = Shortcode_UI_Field_User_Select::get_instance();
}
/**
From 71c0d26dec3ac5ee49e5a55ce91fdb31ff944b2c Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Wed, 1 Jun 2016 14:37:51 +0100
Subject: [PATCH 02/11] Add 'number' query arg set to 10 by default - needed
for pagination and WP_User_Query doesn't set default. Move default user
shortcode args, so they can be overwritten by values in shorcode setup
---
inc/fields/class-field-user-select.php | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index 6e18f52b..2bba61ae 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -130,7 +130,11 @@ public function action_wp_ajax_shortcode_ui_user_field() {
wp_send_json_error( $response );
}
- $shortcode = $shortcodes[ $requested_shortcode ];
+ $shortcode = $shortcodes[ $requested_shortcode ];
+
+ // Defaults user query args.
+ $query_args['search_columns'] = array( 'ID', 'user_login', 'user_nicename', 'user_email' );
+ $query_args['number'] = 10;
// Supports WP_User_Query query args.
foreach ( $shortcode['attrs'] as $attr ) {
@@ -139,9 +143,6 @@ public function action_wp_ajax_shortcode_ui_user_field() {
}
}
- // Hardcoded user query args.
- $query_args['search_columns'] = array( 'ID', 'user_login', 'user_nicename', 'user_email' );
-
if ( isset( $_GET['page'] ) ) {
$query_args['paged'] = sanitize_text_field( $_GET['page'] );
}
From 55e502d6594ca208bfd8438ff32030065ac8cf74 Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Wed, 1 Jun 2016 14:39:12 +0100
Subject: [PATCH 03/11] Add * to search string, so it converts to % in SQL
query and searchers for partial match
---
inc/fields/class-field-user-select.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index 2bba61ae..ee73f42f 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -148,7 +148,7 @@ public function action_wp_ajax_shortcode_ui_user_field() {
}
if ( ! empty( $_GET['s'] ) ) {
- $query_args['search'] = sanitize_text_field( $_GET['s'] );
+ $query_args['search'] = '*' . sanitize_text_field( $_GET['s'] ) . '*';
}
$query = new WP_User_Query( $query_args );
From d5967a3e0d1900791955db13fe63d1df2da74d1f Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Wed, 1 Jun 2016 15:04:25 +0100
Subject: [PATCH 04/11] Updated readme with new minor version, contributor name
and description of an update
---
README.md | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index f5f9ec8b..1fd85319 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# Shortcake (Shortcode UI) #
-**Contributors:** fusionengineering, mattheu, danielbachhuber, zebulonj, goldenapples, jitendraharpalani, sanchothefat, bfintal, davisshaver, garyj, mte90, fredserva, khromov, bronsonquick
+**Contributors:** fusionengineering, mattheu, danielbachhuber, zebulonj, goldenapples, jitendraharpalani, sanchothefat, bfintal, davisshaver, garyj, mte90, fredserva, khromov, bronsonquick, dashaluna
**Tags:** shortcodes
**Requires at least:** 4.1
**Tested up to:** 4.4
-**Stable tag:** 0.6.3
+**Stable tag:** 0.6.4
**License:** GPLv2 or later
**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
@@ -60,6 +60,9 @@ We've removed the compatibility shim for the magical `content` attribute. If you
## Changelog ##
+### 0.6.4 (June 1, 2016) ###
+* Introduced a `user_select` input type for user selection.
+
### 0.6.3 (May 19, 2016) ###
* Introduced a `term_select` input type for taxonomy selection.
From a077c94b48f5b693f92386e694bb916a23a24c1b Mon Sep 17 00:00:00 2001
From: Matth_eu
Date: Wed, 1 Jun 2016 16:32:12 +0100
Subject: [PATCH 05/11] Fix init selection for user select
---
inc/fields/class-field-user-select.php | 6 ++++++
js/build/shortcode-ui.js | 2 +-
js/src/views/edit-attribute-field-user-select.js | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index ee73f42f..ca3e71f2 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -136,6 +136,12 @@ public function action_wp_ajax_shortcode_ui_user_field() {
$query_args['search_columns'] = array( 'ID', 'user_login', 'user_nicename', 'user_email' );
$query_args['number'] = 10;
+ // Include selected users.
+ if ( isset( $_GET['include'] ) ) {
+ $query_args['include'] = is_array( $_GET['include'] ) ? $_GET['include'] : explode( ',', $_GET['include'] );
+ $query_args['include'] = array_map( 'absint', $query_args['include'] );
+ }
+
// Supports WP_User_Query query args.
foreach ( $shortcode['attrs'] as $attr ) {
if ( $attr['attr'] === $requested_attr && isset( $attr['query'] ) ) {
diff --git a/js/build/shortcode-ui.js b/js/build/shortcode-ui.js
index 1cbeb4ca..3f302056 100644
--- a/js/build/shortcode-ui.js
+++ b/js/build/shortcode-ui.js
@@ -1558,7 +1558,7 @@ sui.views.editAttributeFieldColor = editAttributeField.extend({
var initAjaxData = jQuery.extend( true, {}, ajaxData );
initAjaxData.action = 'shortcode_ui_user_field';
- initAjaxData.post__in = uncachedIds;
+ initAjaxData.include = uncachedIds;
$.get( ajaxurl, initAjaxData ).done( function( response ) {
diff --git a/js/src/views/edit-attribute-field-user-select.js b/js/src/views/edit-attribute-field-user-select.js
index ff761d12..ff74bc98 100644
--- a/js/src/views/edit-attribute-field-user-select.js
+++ b/js/src/views/edit-attribute-field-user-select.js
@@ -113,7 +113,7 @@
var initAjaxData = jQuery.extend( true, {}, ajaxData );
initAjaxData.action = 'shortcode_ui_user_field';
- initAjaxData.post__in = uncachedIds;
+ initAjaxData.include = uncachedIds;
$.get( ajaxurl, initAjaxData ).done( function( response ) {
From e2b9c7a9c47bcd6de50734361b4489e3b053a03b Mon Sep 17 00:00:00 2001
From: Matth_eu
Date: Wed, 1 Jun 2016 16:34:07 +0100
Subject: [PATCH 06/11] Add users field to dev
---
dev.php | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/dev.php b/dev.php
index f3d66bec..1488c887 100644
--- a/dev.php
+++ b/dev.php
@@ -193,6 +193,12 @@ function shortcode_ui_dev_advanced_example() {
'taxonomy' => 'post_tag',
'multiple' => true,
),
+ array(
+ 'label' => __( 'User Select', 'shortcode-ui-example' ),
+ 'attr' => 'users',
+ 'type' => 'user_select',
+ 'multiple' => true,
+ ),
array(
'label' => esc_html__( 'Background Color', 'shortcode-ui-example' ),
'attr' => 'background-color',
@@ -285,8 +291,16 @@ function shortcode_ui_dev_shortcode( $attr, $content, $shortcode_tag ) {
'source' => '',
'attachment' => 0,
'page' => null,
+ 'users' => '',
), $attr, $shortcode_tag );
+ $attr['users'] = array_map(
+ function( $user_id ) {
+ $data = get_userdata( $user_id );
+ return $data->display_name;
+ },
+ array_filter( array_map( 'absint', explode( ',', $attr['users'] ) ) )
+ );
// Shortcode callbacks must return content, hence, output buffering here.
ob_start();
?>
@@ -295,6 +309,9 @@ function shortcode_ui_dev_shortcode( $attr, $content, $shortcode_tag ) {
+
+
+
Date: Thu, 2 Jun 2016 16:05:14 +0100
Subject: [PATCH 07/11] Fix version numbers
---
README.md | 12 ++++++------
shortcode-ui.php | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 1fd85319..af2c6f8b 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
# Shortcake (Shortcode UI) #
**Contributors:** fusionengineering, mattheu, danielbachhuber, zebulonj, goldenapples, jitendraharpalani, sanchothefat, bfintal, davisshaver, garyj, mte90, fredserva, khromov, bronsonquick, dashaluna
-**Tags:** shortcodes
-**Requires at least:** 4.1
-**Tested up to:** 4.4
-**Stable tag:** 0.6.4
-**License:** GPLv2 or later
-**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
+**Tags:** shortcodes
+**Requires at least:** 4.1
+**Tested up to:** 4.4
+**Stable tag:** 0.6.3
+**License:** GPLv2 or later
+**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
Shortcake makes using WordPress shortcodes a piece of cake.
diff --git a/shortcode-ui.php b/shortcode-ui.php
index 0cea695e..d97b87ad 100644
--- a/shortcode-ui.php
+++ b/shortcode-ui.php
@@ -19,7 +19,7 @@
* GNU General Public License for more details.
*/
-define( 'SHORTCODE_UI_VERSION', '0.7.2-alpha' );
+define( 'SHORTCODE_UI_VERSION', '0.7.0-alpha' );
require_once dirname( __FILE__ ) . '/inc/class-shortcode-ui.php';
require_once dirname( __FILE__ ) . '/inc/fields/class-shortcode-ui-fields.php';
From a9098e8255a649f273f533bba20c7d8abb0df8e5 Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Fri, 3 Jun 2016 11:17:02 +0100
Subject: [PATCH 08/11] Move all extractions at the top of the function.
wp_unslash vars before sanitization
---
inc/fields/class-field-user-select.php | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index ca3e71f2..684ecf07 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -114,9 +114,12 @@ public function action_shortcode_ui_loaded_editor() {
*/
public function action_wp_ajax_shortcode_ui_user_field() {
- $nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( $_GET['nonce'] ) : null;
- $requested_shortcode = isset( $_GET['shortcode'] ) ? sanitize_text_field( $_GET['shortcode'] ) : null;
- $requested_attr = isset( $_GET['attr'] ) ? sanitize_text_field( $_GET['attr'] ) : null;
+ $nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : null;
+ $requested_shortcode = isset( $_GET['shortcode'] ) ? sanitize_text_field( wp_unslash( $_GET['shortcode'] ) ) : null;
+ $requested_attr = isset( $_GET['attr'] ) ? sanitize_text_field( wp_unslash( $_GET['attr'] ) ) : null;
+ $include = isset( $_GET['include'] ) ? sanitize_text_field( wp_unslash( $_GET['include'] ) ) : null;
+ $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : null;
+ $search_str = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null;
$response = array( 'users' => array(), 'found_users' => 0, 'users_per_page' => 0 );
if ( ! wp_verify_nonce( $nonce, 'shortcode_ui_field_user_select' ) ) {
@@ -137,8 +140,8 @@ public function action_wp_ajax_shortcode_ui_user_field() {
$query_args['number'] = 10;
// Include selected users.
- if ( isset( $_GET['include'] ) ) {
- $query_args['include'] = is_array( $_GET['include'] ) ? $_GET['include'] : explode( ',', $_GET['include'] );
+ if ( $include ) {
+ $query_args['include'] = is_array( $include ) ? $include : explode( ',', $include );
$query_args['include'] = array_map( 'absint', $query_args['include'] );
}
@@ -149,12 +152,12 @@ public function action_wp_ajax_shortcode_ui_user_field() {
}
}
- if ( isset( $_GET['page'] ) ) {
- $query_args['paged'] = sanitize_text_field( $_GET['page'] );
+ if ( $page ) {
+ $query_args['paged'] = $page;
}
- if ( ! empty( $_GET['s'] ) ) {
- $query_args['search'] = '*' . sanitize_text_field( $_GET['s'] ) . '*';
+ if ( $search_str ) {
+ $query_args['search'] = '*' . $search_str . '*';
}
$query = new WP_User_Query( $query_args );
From 9e816a1b594dbf20c8f9878eaae2d8b68bc58eee Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Fri, 3 Jun 2016 13:41:50 +0100
Subject: [PATCH 09/11] Add registration of select2 js and style outside of
select fields. Enqueue in select fields using handle
---
inc/class-shortcode-ui.php | 3 +++
inc/fields/class-field-post-select.php | 6 ++----
inc/fields/class-field-term-select.php | 5 ++---
inc/fields/class-field-user-select.php | 6 ++----
4 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/inc/class-shortcode-ui.php b/inc/class-shortcode-ui.php
index 54bc03c7..77671a3f 100644
--- a/inc/class-shortcode-ui.php
+++ b/inc/class-shortcode-ui.php
@@ -195,6 +195,9 @@ public function get_shortcode( $shortcode_tag ) {
*/
public function action_admin_enqueue_scripts( $editor_supports ) {
add_editor_style( trailingslashit( $this->plugin_url ) . 'css/shortcode-ui-editor-styles.css' );
+
+ wp_register_script( 'select2', trailingslashit( $this->plugin_url ) . 'lib/select2/select2.min.js', array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
+ wp_register_style( 'select2', trailingslashit( $this->plugin_url ) . 'lib/select2/select2.css', null, '3.5.2' );
}
/**
diff --git a/inc/fields/class-field-post-select.php b/inc/fields/class-field-post-select.php
index 6f5d3934..3032725b 100644
--- a/inc/fields/class-field-post-select.php
+++ b/inc/fields/class-field-post-select.php
@@ -38,10 +38,8 @@ public function filter_shortcode_ui_fields( $fields ) {
public function action_enqueue_shortcode_ui() {
- $plugin_dir = dirname( dirname( __FILE__ ) );
-
- wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ) , array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
- wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
+ wp_enqueue_script( 'select2' );
+ wp_enqueue_style( 'select2' );
wp_localize_script( 'shortcode-ui', 'shortcodeUiPostFieldData', array(
'nonce' => wp_create_nonce( 'shortcode_ui_field_post_select' ),
diff --git a/inc/fields/class-field-term-select.php b/inc/fields/class-field-term-select.php
index 1f1e5b4d..63c382a8 100644
--- a/inc/fields/class-field-term-select.php
+++ b/inc/fields/class-field-term-select.php
@@ -51,10 +51,9 @@ public function filter_shortcode_ui_fields( $fields ) {
* Add Select2 for our UI.
*/
public function action_enqueue_shortcode_ui() {
- $plugin_dir = dirname( dirname( __FILE__ ) );
- wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ), array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
- wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
+ wp_enqueue_script( 'select2' );
+ wp_enqueue_style( 'select2' );
wp_localize_script( 'shortcode-ui', 'shortcodeUiTermFieldData', array(
'nonce' => wp_create_nonce( 'shortcode_ui_field_term_select' ),
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index 684ecf07..eb21aa84 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -57,10 +57,8 @@ public function filter_shortcode_ui_fields( $fields ) {
*/
public function action_enqueue_shortcode_ui() {
- $plugin_dir = dirname( dirname( __FILE__ ) );
-
- wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ), array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
- wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
+ wp_enqueue_script( 'select2' );
+ wp_enqueue_style( 'select2' );
wp_localize_script( 'shortcode-ui', 'shortcodeUiUserFieldData', array(
'nonce' => wp_create_nonce( 'shortcode_ui_field_user_select' ),
From c9a1365eb65bc9ef6ffc2f74b691d5bc4099f66c Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Fri, 3 Jun 2016 15:16:27 +0100
Subject: [PATCH 10/11] Fix sanitisation of include, it's an array. Oops
---
inc/fields/class-field-user-select.php | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index eb21aa84..c3fbab95 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -115,11 +115,16 @@ public function action_wp_ajax_shortcode_ui_user_field() {
$nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : null;
$requested_shortcode = isset( $_GET['shortcode'] ) ? sanitize_text_field( wp_unslash( $_GET['shortcode'] ) ) : null;
$requested_attr = isset( $_GET['attr'] ) ? sanitize_text_field( wp_unslash( $_GET['attr'] ) ) : null;
- $include = isset( $_GET['include'] ) ? sanitize_text_field( wp_unslash( $_GET['include'] ) ) : null;
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : null;
$search_str = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null;
$response = array( 'users' => array(), 'found_users' => 0, 'users_per_page' => 0 );
+ if ( isset( $_GET['include'] ) ) {
+ // Make sure include is always an array & sanitize its values.
+ $include = is_array( $_GET['include'] ) ? $_GET['include'] : explode( ',', $_GET['include'] );
+ $include = array_map( 'absint', stripslashes_deep( $include ) );
+ }
+
if ( ! wp_verify_nonce( $nonce, 'shortcode_ui_field_user_select' ) ) {
wp_send_json_error( $response );
}
@@ -137,10 +142,9 @@ public function action_wp_ajax_shortcode_ui_user_field() {
$query_args['search_columns'] = array( 'ID', 'user_login', 'user_nicename', 'user_email' );
$query_args['number'] = 10;
- // Include selected users.
+ // Include selected users to be displayed.
if ( $include ) {
- $query_args['include'] = is_array( $include ) ? $include : explode( ',', $include );
- $query_args['include'] = array_map( 'absint', $query_args['include'] );
+ $query_args['include'] = $include;
}
// Supports WP_User_Query query args.
From 0b9e7c9379701786eeda1135dc44824ca06448db Mon Sep 17 00:00:00 2001
From: dashaluna
Date: Fri, 3 Jun 2016 16:02:46 +0100
Subject: [PATCH 11/11] Declare default value for , so if statement don't do
warning if it's not set
---
inc/fields/class-field-user-select.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/inc/fields/class-field-user-select.php b/inc/fields/class-field-user-select.php
index c3fbab95..779fb8fd 100644
--- a/inc/fields/class-field-user-select.php
+++ b/inc/fields/class-field-user-select.php
@@ -119,6 +119,7 @@ public function action_wp_ajax_shortcode_ui_user_field() {
$search_str = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null;
$response = array( 'users' => array(), 'found_users' => 0, 'users_per_page' => 0 );
+ $include = null;
if ( isset( $_GET['include'] ) ) {
// Make sure include is always an array & sanitize its values.
$include = is_array( $_GET['include'] ) ? $_GET['include'] : explode( ',', $_GET['include'] );