Merge pull request #1203 from ultimatemember/development/2.6.3

Version 2.6.3
This commit is contained in:
Mykyta Synelnikov
2023-06-13 22:12:59 +03:00
committed by GitHub
43 changed files with 1325 additions and 498 deletions
+7
View File
@@ -0,0 +1,7 @@
# Welcome to the Ultimate Member Plugin Hook Documentation
This resource is generated documentation on actions and filters found in the [Ultimate Member](https://wordpress.org/plugins/ultimate-member/) plugin. Use the sidebar to browse and navigate.
For more information about using Ultimate Member with WordPress, please see the [Ultimate Member Docs](https://docs.ultimatemember.com/).
To report an issue with Ultimate Member, please visit the [Support forum](https://wordpress.org/support/plugin/ultimate-member/).
+46
View File
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><?js= title ?> - Ultimate Member Hook Docs</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<link href="https://fonts.googleapis.com/css?family=IBM+Plex+Mono|IBM+Plex+Sans:300,400|Playfair+Display:900&display=swap" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="styles-um.css">
</head>
<body<?js if (title === 'Home') { ?> class="home"<?js } ?>>
<div id="main">
<?js if (title !== 'Home') { ?>
<h1 class="page-title"><?js= title ?></h1>
<?js } ?>
<?js= content ?>
<footer>
<a href="https://wordpress.org/plugins/ultimate-member/">Ultimate Member Plugin</a> &bull;
<a href="https://docs.ultimatemember.com/">Official Docs</a>
</footer>
</div>
<nav>
<?js= this.nav ?>
</nav>
<br class="clear">
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+99
View File
@@ -0,0 +1,99 @@
body {
background: #fefefe;
color: #232323;
font-family: 'IBM Plex Sans', sans-serif;
font-size: 1.3rem;
font-weight: 300;
}
h1, h2, h3 {
line-height: 1.2;
font-family: 'Playfair Display', sans-serif;
font-weight: 900;
letter-spacing: -.01em;
}
h1.page-title {
font-size: 42px;
margin-top: .5em;
}
nav ul {
font-size: 1.2rem;
}
nav li a {
background-image: none;
}
nav li a:hover {
text-decoration: underline;
}
code, pre,
nav ul a, nav ul a:visited, nav ul a:active,
.name, .signature,
.params .name, .props .name,
.name code {
font-family: 'IBM Plex Mono', monospace;
}
article h1 {
margin: 12px 0 32px;
}
a {
background-image: linear-gradient(transparent calc(100% - 7px), #f2dede 0),
linear-gradient(transparent calc(100% - 7px), #cef8f7 0);
background-position: 0 0;
background-repeat: no-repeat;
background-size: 0 100%, 100% 100%;
color: #232323;
text-decoration: none;
transition: all .1s;
}
a:visited,
a:active {
color: #232323;
}
a:focus,
a:hover {
background-size: 100% 100%, 100% 100%;
color: #232323;
text-decoration: none;
}
a.banner {
background-image: none;
margin-left: -10px;
}
a.banner img {
width: 100%;
max-width: 888px;
}
footer {
text-align: center;
font-size: .8em;
font-style: normal;
font-weight: 300;
}
.home #main > section:first-of-type,
.home nav > h2 {
display: none;
}
.prettyprint.source {
font-size: 14px;
}
.prettyprint code {
font-size: 16px;
padding: 2px 10px;
line-height: 18px;
max-height: 150px;
}
+31
View File
@@ -0,0 +1,31 @@
name: Build Hook Docs
on:
push:
branches:
- master
jobs:
hookdocs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: npm install, and build docs
run: |
npm install
npm run build:docs
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: PhpDocumentor
uses: gpupo/actions-phpDocumentor@1.0
with:
dir: './'
- name: Deploy to GH Pages
uses: JamesIves/github-pages-deploy-action@v4.3.3
with:
branch: gh-pages # The branch the action should deploy to.
folder: 'docs/' # The folder the action should deploy.
token: ${{ secrets.GH_PAT }}
+1 -1
View File
@@ -42,7 +42,7 @@ GNU Version 2 or Any Later Version
## Releases
[Official Release Version: 2.6.2](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.2).
[Official Release Version: 2.6.3](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.3).
## Changelog
+7 -1
View File
@@ -6,6 +6,12 @@
"license": "GPL-3.0-or-later",
"minimum-stability": "stable",
"prefer-stable": true,
"config": {
"allow-plugins": {
"symfony/flex": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"require": {
"ext-mbstring": "*",
"ext-json": "*",
@@ -18,7 +24,7 @@
"woocommerce/action-scheduler": "3.2.1"
},
"require-dev": {
"roave/security-advisories": "dev-master",
"roave/security-advisories": "dev-latest",
"wp-cli/wp-cli": "*",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
"object-calisthenics/phpcs-calisthenics-rules": "*",
+11
View File
@@ -0,0 +1,11 @@
# Welcome to the Ultimate Member Documentation
There are GitHub Pages documentation of [Ultimate Member](https://wordpress.org/plugins/ultimate-member/) plugin. Use the links below:
The generated documentation on actions and filters is [here](https://ultimatemember.github.io/ultimatemember/hooks).
The generated documentation on PHP namespaces, classes, properties, methods and functions is [here](https://ultimatemember.github.io/ultimatemember/phpdoc).
For more information about using Ultimate Member with WordPress, please see the [Ultimate Member Docs](https://docs.ultimatemember.com/).
To report an issue with Ultimate Member, please visit the [Support forum](https://wordpress.org/support/plugin/ultimate-member/).
+31
View File
@@ -0,0 +1,31 @@
{
"opts": {
"destination": "docs/hooks",
"template": "node_modules/wp-hookdoc/template",
"recurse": true,
"readme": "./.github/hookdoc-tmpl/README.md"
},
"source": {
"include": [
"./"
],
"exclude": [
"node_modules"
],
"includePattern": ".+\\.(php)?$"
},
"plugins": [
"node_modules/wp-hookdoc/plugin",
"plugins/markdown"
],
"templates": {
"default": {
"layoutFile": "./.github/hookdoc-tmpl/layout.tmpl",
"staticFiles": {
"include": [
"./.github/hookdoc-tmpl/static"
]
}
}
}
}
@@ -146,6 +146,14 @@ textarea.um-forms-field.um-small-field {
flex: 0.9;
}
.um-multi-selects-option-line .um-field-wrapper.um-custom-order-fields label select{
width: auto;
display: inline;
font-weight: normal;
max-width: 70%;
flex: 0.9;
}
.um-multi-selects-option-line.um-admin-drag-fld .um-field-wrapper {
width: calc( 100% - 90px );
}
+55 -4
View File
@@ -1,17 +1,48 @@
function um_admin_init_users_select() {
if ( jQuery('.um-user-select-field').length ) {
function avatarformat( data ) {
var option;
if ( ! data.id ) {
return data.text;
}
if ( 'undefined' !== typeof data.img ) {
option = jQuery('<span><img style="vertical-align: sub; width: 20px; height: 20px;" src="' + data.img + '" /> ' + data.text + '</span>');
} else {
var img = data.element.attributes['data-img']['value'];
if ( img ) {
option = jQuery('<img style="vertical-align: sub; width: 20px; height: 20px;" src="' + img + '" /> ' + data.text + '</span>');
} else {
option = jQuery('<span>' + data.text + '</span>');
}
}
return option;
}
var select2_atts = {
ajax: {
url: wp.ajax.settings.url,
dataType: 'json',
delay: 250, // delay in ms while typing when to perform a AJAX search
data: function( params ) {
return {
search: params.term, // search query
var args = {
action: 'um_get_users', // AJAX action for admin-ajax.php
search: params.term, // search query
page: params.page || 1, // infinite scroll pagination
nonce: um_admin_scripts.nonce
};
jQuery.each( jQuery(this)[0].attributes, function() {
// this.attributes is not a plain object, but an array
// of attribute nodes, which contain both the name and value
if ( this.specified ) {
if ( -1 !== this.name.indexOf( 'data-ajax-args-' ) ) {
var arg_name = this.name.replace( 'data-ajax-args-', '' ).trim();
args[ arg_name ] = this.value;
}
}
});
return args;
},
processResults: function( response, params ) {
params.page = params.page || 1;
@@ -19,7 +50,11 @@ function um_admin_init_users_select() {
if ( response.data.users ) {
jQuery.each( response.data.users, function( index, text ) {
options.push( { id: text.ID, text: text.user_login + ' (#' + text.ID + ')' } );
if ( typeof text.img !== 'undefined' ) {
options.push({ id: text.ID, text: text.user_login + ' (#' + text.ID + ')', img: text.img });
} else {
options.push( { id: text.ID, text: text.user_login + ' (#' + text.ID + ')' } );
}
});
}
@@ -38,7 +73,9 @@ function um_admin_init_users_select() {
allowHtml: true,
dropdownCssClass: 'um-select2-users-dropdown',
containerCssClass : 'um-select2-users-container',
placeholder: jQuery(this).data('placeholder')
placeholder: jQuery(this).data('placeholder'),
templateSelection: avatarformat,
templateResult: avatarformat
};
jQuery('.um-user-select-field').select2( select2_atts );
@@ -245,11 +282,23 @@ jQuery(document).ready( function() {
html += '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>';
}
let dataTypesOptions = '';
jQuery.each( um_forms_data.md_sorting_data_types, function( key, label ) {
dataTypesOptions += '<option value="' + key + '">' + label + '</option>';
} );
html += '<span class="um-field-wrapper">' + selector_html + '</span>' +
'<span class="um-field-control">' +
'<a href="javascript:void(0);" class="um-select-delete">' + wp.i18n.__( 'Remove', 'ultimate-member' ) + '</a>' +
'</span>' +
'<span class="um-field-wrapper um-custom-order-fields"><label>' + wp.i18n.__( 'Meta key', 'ultimate-member' ) + ':&nbsp;<input type="text" name="meta_key" /></label></span>' +
'<span class="um-field-wrapper um-custom-order-fields"><label>' + wp.i18n.__( 'Data type', 'ultimate-member' ) + ':&nbsp;<select name="data_type" />' +
dataTypesOptions +
'</select></label></span>' +
'<span class="um-field-wrapper um-custom-order-fields"><label>' + wp.i18n.__( 'Order', 'ultimate-member' ) + ':&nbsp;<select name="order" />' +
'<option value="ASC">' + wp.i18n.__( 'ASC', 'ultimate-member' ) + '</option>' +
'<option value="DESC">' + wp.i18n.__( 'DESC', 'ultimate-member' ) + '</option>' +
'</select></label></span>' +
'<span class="um-field-wrapper um-custom-order-fields"><label>' + wp.i18n.__( 'Label', 'ultimate-member' ) + ':&nbsp;<input type="text" name="label" /></label></span>' +
'</li>';
list.append( html );
@@ -259,6 +308,8 @@ jQuery(document).ready( function() {
jQuery( '#' + list.data('id_attr') + '-' + k ).parents('li').find('.um-field-wrapper.um-custom-order-fields input[name="meta_key"]').attr('name', 'um_metadata[_um_sorting_fields][other_data][' + k + '][meta_key]');
jQuery( '#' + list.data('id_attr') + '-' + k ).parents('li').find('.um-field-wrapper.um-custom-order-fields input[name="label"]').attr('name', 'um_metadata[_um_sorting_fields][other_data][' + k + '][label]');
jQuery( '#' + list.data('id_attr') + '-' + k ).parents('li').find('.um-field-wrapper.um-custom-order-fields select[name="data_type"]').attr('name', 'um_metadata[_um_sorting_fields][other_data][' + k + '][data_type]');
jQuery( '#' + list.data('id_attr') + '-' + k ).parents('li').find('.um-field-wrapper.um-custom-order-fields select[name="order"]').attr('name', 'um_metadata[_um_sorting_fields][other_data][' + k + '][order]');
});
+12 -3
View File
@@ -1,21 +1,18 @@
<?php
namespace um\admin;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\admin\Admin' ) ) {
/**
* Class Admin
* @package um\admin
*/
class Admin extends Admin_Functions {
/**
* @var string
*/
@@ -389,6 +386,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
'_um_sortby_custom_label' => array(
'sanitize' => 'text',
),
'_um_sortby_custom_type' => array(
'sanitize' => 'text',
),
'_um_sortby_custom_order' => array(
'sanitize' => 'text',
),
'_um_enable_sorting' => array(
'sanitize' => 'bool',
),
@@ -867,6 +870,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
if ( isset( $item['label'] ) ) {
$item['label'] = sanitize_text_field( $item['label'] );
}
if ( isset( $item['order'] ) ) {
$item['order'] = sanitize_text_field( $item['order'] );
}
if ( isset( $item['data_type'] ) ) {
$item['data_type'] = sanitize_text_field( $item['data_type'] );
}
return $item;
} else {
+16 -12
View File
@@ -1,30 +1,37 @@
<?php
namespace um\admin\core;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\admin\core\Admin_DragDrop' ) ) {
/**
* Class Admin_DragDrop
* @package um\admin\core
*/
class Admin_DragDrop {
/**
* @var array
*/
public $row_data = array();
/**
* @var array
*/
public $exist_rows = array();
/**
* Admin_DragDrop constructor.
*/
function __construct() {
public function __construct() {
add_action( 'admin_footer', array( &$this, 'load_field_order' ), 9 );
}
/**
* Update order of fields
* Update order of fields.
*/
public function update_order() {
UM()->admin()->check_ajax_nonce();
@@ -153,12 +160,10 @@ if ( ! class_exists( 'um\admin\core\Admin_DragDrop' ) ) {
update_option( 'um_form_rowdata_' . $form_id, $this->row_data );
UM()->query()->update_attr( 'custom_fields', $form_id, $fields );
}
/**
* Load form to maintain form order
* Load form to maintain form order.
*/
public function load_field_order() {
@@ -233,7 +238,7 @@ if ( ! class_exists( 'um\admin\core\Admin_DragDrop' ) ) {
<input type="hidden" name="form_id" id="form_id" value="<?php echo esc_attr( get_the_ID() ); ?>" />
<input type="hidden" name="action" value="um_update_order" />
<input type="hidden" name="nonce" value="<?php echo esc_attr( wp_create_nonce( 'um-admin-nonce' ) ) ?>" />
<input type="hidden" name="nonce" value="<?php echo esc_attr( wp_create_nonce( 'um-admin-nonce' ) ); ?>" />
<div class="um_update_order_fields">
@@ -244,6 +249,5 @@ if ( ! class_exists( 'um\admin\core\Admin_DragDrop' ) ) {
<?php
}
}
}
+2 -1
View File
@@ -375,6 +375,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Enqueue' ) ) {
),
admin_url( 'admin.php' )
),
'md_sorting_data_types' => UM()->member_directory()->sort_data_types,
)
);
@@ -566,7 +567,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Enqueue' ) ) {
* Load Gutenberg scripts
*/
public function load_gutenberg_js() {
//disable Gutenberg scripts to avoid the conflicts
/** This filter is documented in includes/core/class-blocks.php */
$disable_script = apply_filters( 'um_disable_blocks_script', false );
if ( $disable_script ) {
return;
+80 -23
View File
@@ -125,6 +125,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
'target' => array(),
'class' => array(),
),
'button' => array(
'class' => array(),
),
'i' => array(
'class' => array(),
),
@@ -576,33 +579,39 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
*
* @return bool|string
*/
function render_users_dropdown( $field_data ) {
public function render_users_dropdown( $field_data ) {
if ( empty( $field_data['id'] ) ) {
return false;
}
$multiple = ! empty( $field_data['multi'] ) ? 'multiple' : '';
$id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id'];
$id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id'];
$id_attr = ' id="' . esc_attr( $id ) . '" ';
$class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' ';
$class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field';
$class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' ';
$class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field';
$class_attr = ' class="um-forms-field um-user-select-field' . esc_attr( $class ) . '" ';
$data = array(
'field_id' => $field_data['id'],
'avatar' => ! empty( $field_data['avatar'] ) ? 1 : 0,
);
if ( ! empty( $field_data['data'] ) && is_array( $field_data['data'] ) ) {
$data = array_merge( $data, $field_data['data'] );
}
$data_attr = '';
foreach ( $data as $key => $value ) {
$data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" ';
}
$name = $field_data['id'];
$name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name;
$name = $field_data['id'];
$name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name;
$hidden_name_attr = ' name="' . $name . '" ';
$name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' );
$name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' );
$name_attr = ' name="' . $name . '" ';
$value = $this->get_field_value( $field_data );
@@ -620,15 +629,22 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$options = '';
if ( ! empty( $users ) ) {
foreach ( $users as $user ) {
$options .= '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->user_login . ' (#' . $user->ID . ')' ) . '</option>';
if ( ! empty( $field_data['avatar'] ) ) {
$url = get_avatar_url( $user->ID, 'size=20' );
$options .= '<option data-img="' . esc_url( $url ) . '" value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->user_login . ' (#' . $user->ID . ')' ) . '</option>';
} else {
$options .= '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->user_login . ' (#' . $user->ID . ')' ) . '</option>';
}
}
}
$placeholder = ! empty( $field_data['placeholder'] ) ? $field_data['placeholder'] : __( 'Select Users', 'ultimate-member' );
$hidden = '';
if ( ! empty( $multiple ) ) {
$hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />";
}
$html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr data-placeholder=\"" . esc_attr__( 'Select Users', 'ultimate-member' ) . "\" placeholder=\"" . esc_attr__( 'Select Users', 'ultimate-member' ) . "\"><option>" . esc_html__( 'Select Users', 'ultimate-member' ) . "</option>$options</select>";
$html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr data-placeholder=\"" . esc_attr( $placeholder ) . "\" placeholder=\"" . esc_attr( $placeholder ) . "\"><option value=\"\">" . esc_html( $placeholder ) . "</option>$options</select>";
return $html;
}
@@ -869,8 +885,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$value = $this->get_field_value( $field_data );
add_filter( 'wp_default_editor', array( &$this, 'set_default_editor_fix' ) );
ob_start();
wp_editor( $value,
wp_editor(
$value,
$id,
array(
'textarea_name' => $name,
@@ -878,14 +897,25 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
'editor_height' => 425,
'wpautop' => false,
'media_buttons' => false,
'editor_class' => $class
'editor_class' => $class,
)
);
$html = ob_get_clean();
remove_filter( 'wp_default_editor', array( &$this, 'set_default_editor_fix' ) );
return $html;
}
/**
* Fix the displaying wp_editor on macOS
*
* @return string
*/
public function set_default_editor_fix() {
return 'html';
}
/**
* @param $field_data
@@ -1590,16 +1620,30 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
if ( ! empty( $values ) && is_array( $values ) ) {
foreach ( $values as $k => $value ) {
$other_key = '';
$other_key = '';
$other_label = '';
$other_type = '';
$other_order = '';
if ( is_array( $value ) ) {
$keys = array_keys( $value );
$keys = array_keys( $value );
$other_key = $keys[0];
$labels = array_values( $value );
$other_label = $labels[0];
if ( ! empty( $value['label'] ) ) {
$other_label = $value['label'];
} else {
$labels = array_values( $value );
$other_label = $labels[0];
}
if ( ! empty( $value['type'] ) ) {
$other_type = $value['type'];
}
if ( ! empty( $value['order'] ) ) {
$other_order = $value['order'];
}
} else {
if ( ! in_array( $value, array_keys( $field_data['options'] ) ) ) {
if ( ! array_key_exists( $value, $field_data['options'] ) ) {
continue;
}
}
@@ -1609,7 +1653,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$options = '';
foreach ( $field_data['options'] as $key => $option ) {
if ( is_array( $value ) ) {
$selected = selected( $key == 'other', true, false );
$selected = selected( 'other' === $key, true, false );
} else {
$selected = selected( $key == $value, true, false );
}
@@ -1621,12 +1665,25 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
if ( $sorting ) {
$html .= '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>';
}
$html .= "<span class=\"um-field-wrapper\">
<select $id_attr $name_attr $class_attr $data_attr>$options</select></span>
<span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span>
<span class=\"um-field-wrapper um-custom-order-fields\"><label>" . __( 'Meta key', 'ultimate-member' ) . ":&nbsp;<input type=\"text\" name=\"um_metadata[_um_sorting_fields][other_data][" . $k . "][meta_key]\" value=\"" . esc_attr( $other_key ) . "\" /></label></span>
<span class=\"um-field-wrapper um-custom-order-fields\"><label>" . __( 'Label', 'ultimate-member' ) . ":&nbsp;<input type=\"text\" name=\"um_metadata[_um_sorting_fields][other_data][" . $k . "][label]\" value=\"" . esc_attr( $other_label ) . "\" /></label></span>
</li>";
$data_types_html = '';
foreach ( UM()->member_directory()->sort_data_types as $type_key => $type_label ) {
$data_types_html .= '<option value="' . esc_attr( $type_key ) . '" ' . selected( $other_type, $type_key, false ) . '>' . esc_html( $type_label ) . '</option>';
}
$html .= '<span class="um-field-wrapper">
<select ' . $id_attr . ' ' . $name_attr . ' ' . $class_attr . ' ' . $data_attr . '>' . $options . '</select></span>
<span class="um-field-control"><a href="javascript:void(0);" class="um-select-delete">' . __( 'Remove', 'ultimate-member' ) . '</a></span>
<span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Meta key', 'ultimate-member' ) . ':&nbsp;<input type="text" name="um_metadata[_um_sorting_fields][other_data][' . $k . '][meta_key]" value="' . esc_attr( $other_key ) . '" /></label></span>
<span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Data type', 'ultimate-member' ) . ':&nbsp;<select name="um_metadata[_um_sorting_fields][other_data][' . $k . '][data_type]" />' .
$data_types_html .
'</select></label></span>
<span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Order', 'ultimate-member' ) . ':&nbsp;<select name="um_metadata[_um_sorting_fields][other_data][' . $k . '][order]" />
<option value="ASC" ' . selected( $other_order, 'ASC', false ) . '>' . __( 'ASC', 'ultimate-member' ) . '</option>
<option value="DESC" ' . selected( $other_order, 'DESC', false ) . '>' . __( 'DESC', 'ultimate-member' ) . '</option>
</select></label></span>
<span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Label', 'ultimate-member' ) . ':&nbsp;<input type="text" name="um_metadata[_um_sorting_fields][other_data][' . $k . '][label]" value="' . esc_attr( $other_label ) . '" /></label></span>
</li>';
}
} elseif ( ! empty( $field_data['show_default_number'] ) && is_numeric( $field_data['show_default_number'] ) && $field_data['show_default_number'] > 0 ) {
$i = 0;
+4 -7
View File
@@ -47,16 +47,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Navmenu' ) ) {
* Fires just before the move buttons of a nav menu item in the menu editor.
* Adds block "Ultimate Member Menu Settings"
*
* @since WP 5.4.0
* @hook wp_nav_menu_item_custom_fields
*
* @param int $item_id Menu item ID.
* @param int $item_id Menu item ID.
* @param \WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param int $depth Depth of menu item. Used for padding.
* @param \stdClass $args An object of menu item arguments.
* @param int $id Nav menu ID.
* @param int $id Nav menu ID.
*/
function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args, $id = null ) {
public function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args, $id = null ) {
$um_nav_public = get_post_meta( $item->ID, 'menu-item-um_nav_public', true );
$_nav_roles_meta = get_post_meta( $item->ID, 'menu-item-um_nav_roles', true );
+25 -28
View File
@@ -1,13 +1,12 @@
<?php
namespace um\admin\core;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
/**
* Class Admin_Users
* @package um\admin\core
@@ -42,8 +41,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
add_action( 'um_admin_user_action_hook', array( &$this, 'user_action_hook' ), 10, 1 );
}
function get_users() {
public function get_users() {
UM()->admin()->check_ajax_nonce();
$search_request = ! empty( $_REQUEST['search'] ) ? sanitize_text_field( $_REQUEST['search'] ) : '';
@@ -53,17 +51,26 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
$args = array(
'fields' => array( 'ID', 'user_login' ),
'paged' => $page,
'number' => $per_page
'number' => $per_page,
);
if ( ! empty( $search_request ) ) {
$args['search'] = $search_request;
$args['search'] = '*' . $search_request . '*';
}
$args = apply_filters( 'um_get_users_list_ajax_args', $args );
$users_query = new \WP_User_Query( $args );
$users = $users_query->get_results();
$total_count = $users_query->get_total();
if ( ! empty( $_REQUEST['avatar'] ) ) {
foreach ( $users as $key => $user ) {
$url = get_avatar_url( $user->ID );
$users[ $key ]->img = $url;
}
}
wp_send_json_success(
array(
'users' => $users,
@@ -72,7 +79,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
);
}
/**
* Restrict the edit/delete users via wp-admin screen by the UM role capabilities
*
@@ -83,7 +89,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
*
* @return mixed
*/
function map_caps_by_role( $allcaps, $cap, $args, $user ) {
public function map_caps_by_role( $allcaps, $cap, $args, $user ) {
if ( isset( $cap[0] ) && $cap[0] == 'edit_users' ) {
if ( isset( $args[0] ) && isset( $args[1] ) && ! user_can( $args[1], 'administrator' ) && $args[0] == 'edit_user' ) {
if ( isset( $args[2] ) && ! UM()->roles()->um_current_user_can( 'edit', $args[2] ) ) {
@@ -107,13 +113,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $allcaps;
}
/**
* Does an action to user asap
*
* @param string $action
*/
function user_action_hook( $action ) {
public function user_action_hook( $action ) {
switch ( $action ) {
default:
/**
@@ -176,12 +181,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
}
}
/**
* Add UM Bulk actions to Users List Table
*
*/
function restrict_manage_users() { ?>
public function restrict_manage_users() {
?>
<div style="float:right;margin:0 4px">
<label class="screen-reader-text" for="um_bulk_action"><?php _e( 'UM Action', 'ultimate-member' ); ?></label>
@@ -197,16 +202,16 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
<?php if ( ! empty( $_REQUEST['um_status'] ) ) { ?>
<input type="hidden" name="um_status" id="um_status" value="<?php echo esc_attr( sanitize_key( $_REQUEST['um_status'] ) );?>"/>
<?php }
<?php
}
}
/**
* Get UM bulk actions HTML
*
* @return string
*/
function get_bulk_admin_actions() {
public function get_bulk_admin_actions() {
/**
* UM hook
@@ -259,7 +264,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $output;
}
/**
* Custom row actions for users page
*
@@ -267,7 +271,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
* @param $user_object \WP_User
* @return array
*/
function user_row_actions( $actions, $user_object ) {
public function user_row_actions( $actions, $user_object ) {
$user_id = $user_object->ID;
$actions['frontend_profile'] = '<a href="' . um_user_profile_url( $user_id ) . '">' . __( 'View profile', 'ultimate-member' ) . '</a>';
@@ -312,14 +316,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $actions;
}
/**
* Change default sorting at WP Users list table
*
* @param array $args
* @return array
*/
function hide_by_caps( $args ) {
public function hide_by_caps( $args ) {
if ( ! current_user_can( 'administrator' ) ) {
$can_view_roles = um_user( 'can_view_roles' );
if ( um_user( 'can_view_all' ) && ! empty( $can_view_roles ) ) {
@@ -330,7 +333,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $args;
}
/**
* Change default sorting at WP Users list table
*
@@ -350,7 +352,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $query;
}
/**
* Filter WP users by UM Status
*
@@ -385,7 +386,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $query;
}
/**
* Add status links to WP Users List Table
*
@@ -474,7 +474,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $views;
}
/**
* Bulk user editing actions
*/
@@ -561,14 +560,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
}
}
/**
* Sets redirect URI after bulk action
*
* @param string $uri
* @return string
*/
function set_redirect_uri( $uri ) {
public function set_redirect_uri( $uri ) {
if ( ! empty( $_REQUEST['s'] ) ) {
$uri = add_query_arg( 's', sanitize_text_field( $_REQUEST['s'] ), $uri );
@@ -581,6 +579,5 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
return $uri;
}
}
}
@@ -42,6 +42,23 @@ if ( isset( $_GET['action'] ) ) {
}
delete_option( "um_role_{$role_key}_meta" );
/**
* Fires after delete UM role.
*
* @since 2.6.3
* @hook um_after_delete_role
*
* @param {string} $role_key Role key.
* @param {array} $role_meta Role meta.
*
* @example <caption>Make any custom action after deleting UM role.</caption>
* function my_custom_um_after_delete_role( $role_key, $role_meta ) {
* // your code here
* }
* add_action( 'um_after_delete_role', 'my_custom_um_after_delete_role', 10, 2 );
*/
do_action( 'um_after_delete_role', $role_key, $role_meta );
$um_roles = array_diff( $um_roles, array( $role_key ) );
$roleID = 'um_' . $role_key;
@@ -114,6 +131,23 @@ if ( isset( $_GET['action'] ) ) {
}
delete_option( "um_role_{$role_key}_meta" );
/**
* Fires after delete UM role meta.
*
* @since 2.6.3
* @hook um_after_delete_role_meta
*
* @param {string} $role_key Role key.
* @param {array} $role_meta Role meta.
*
* @example <caption>Make any custom action after deleting UM role meta.</caption>
* function my_custom_um_after_delete_role_meta( $role_key, $role_meta ) {
* // your code here
* }
* add_action( 'um_after_delete_role_meta', 'my_custom_um_after_delete_role_meta', 10, 2 );
*/
do_action( 'um_after_delete_role_meta', $role_key, $role_meta );
}
um_js_redirect( add_query_arg( 'msg', 'reset', $redirect ) );
@@ -362,7 +396,25 @@ class UM_Roles_List_Table extends WP_List_Table {
}
}
return sprintf('%1$s %2$s', '<strong><a class="row-title" href="admin.php?page=um_roles&tab=edit&id=' . esc_attr( $id ) . '">' . stripslashes( $item['name'] ) . '</a></strong>', $this->row_actions( $actions ) );
/**
* Filters the role actions in WP ListTable Ultimate Member > Roles screen.
*
* @since 2.6.3
* @hook um_role_row_actions
*
* @param {array} $actions Action links.
* @param {string} $id Role key.
*
* @example <caption>Add custom action to role's row.</caption>
* function my_custom_um_role_row_actions( $actions, $id ) {
* $actions['{action_key}'] = "<a href="{action_link}">Action Title</a>";
* return $actions;
* }
* add_action( 'um_role_row_actions', 'my_custom_um_role_row_actions', 10, 2 );
*/
$actions = apply_filters( 'um_role_row_actions', $actions, $id );
return sprintf( '%1$s %2$s', '<strong><a class="row-title" href="admin.php?page=um_roles&tab=edit&id=' . esc_attr( $id ) . '">' . stripslashes( $item['name'] ) . '</a></strong>', $this->row_actions( $actions ) );
}
@@ -24,6 +24,27 @@ $fields = array(
'value' => UM()->query()->get_meta_value( '_um_sortby_custom', null, 'na' ),
'conditional' => array( '_um_sortby', '=', 'other' ),
),
array(
'id' => '_um_sortby_custom_type',
'type' => 'select',
'label' => __( 'Data type', 'ultimate-member' ),
'tooltip' => __( 'To correct sort by a custom field, choose a data type', 'ultimate-member' ),
'value' => UM()->query()->get_meta_value( '_um_sortby_custom_type', null, 'CHAR' ),
'options' => UM()->member_directory()->sort_data_types,
'conditional' => array( '_um_sortby', '=', 'other' ),
),
array(
'id' => '_um_sortby_custom_order',
'type' => 'select',
'label' => __( 'Order', 'ultimate-member' ),
'tooltip' => __( 'To correct sort by a custom field, choose an order', 'ultimate-member' ),
'value' => UM()->query()->get_meta_value( '_um_sortby_custom_order', null, 'ASC' ),
'options' => array(
'ASC' => __( 'ASC', 'ultimate-member' ),
'DESC' => __( 'DESC', 'ultimate-member' ),
),
'conditional' => array( '_um_sortby', '=', 'other' ),
),
array(
'id' => '_um_sortby_custom_label',
'type' => 'text',
+31 -2
View File
@@ -1,4 +1,5 @@
<?php if ( ! defined( 'ABSPATH' ) ) {
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@@ -124,6 +125,7 @@ if ( ! empty( $_POST['role'] ) ) {
if ( '' === $error ) {
$update = true;
if ( 'add' === sanitize_key( $_GET['tab'] ) ) {
$roles = get_option( 'um_roles', array() );
$roles[] = $id;
@@ -134,9 +136,36 @@ if ( ! empty( $_POST['role'] ) ) {
$auto_increment++;
UM()->options()->update( 'custom_roles_increment', $auto_increment );
}
$update = false;
}
$role_meta = $data;
/**
* Filters the role meta before save it to DB.
*
* @param {array} $data Role meta.
* @param {string} $id Role key.
* @param {bool} $update Create or update role. "True" if update.
*
* @since 2.6.3
* @hook um_role_edit_data
*
* @example <caption>Add custom metadata for role on saving.</caption>
* function my_custom_um_role_edit_data( $data, $id, $update ) {
* $data['{meta_key}'] = {meta_value}; // set your meta key and meta value
* return $data;
* }
* add_action( 'um_role_edit_data', 'my_custom_um_role_edit_data', 10, 3 );
* @example <caption>Force remove role's metadata on saving when update.</caption>
* function my_custom_um_role_edit_data( $data, $id, $update ) {
* if ( true === $update ) {
* unset( $data['{meta_key}'] ); // set your meta key
* }
* return $data;
* }
* add_action( 'um_role_edit_data', 'my_custom_um_role_edit_data', 10, 3 );
*/
$role_meta = apply_filters( 'um_role_edit_data', $data, $id, $update );
unset( $role_meta['id'] );
update_option( "um_role_{$id}_meta", $role_meta );
+3 -4
View File
@@ -1,13 +1,12 @@
<?php
namespace um;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\Config' ) ) {
/**
* Class Config
*
+12
View File
@@ -729,6 +729,18 @@ if ( ! class_exists( 'UM_Functions' ) ) {
* @param {string} $context Function context 'wp-admin' for Admin Dashboard echo, 'templates' for the frontend.
*
* @return {array} Allowed HTML tags with attributes.
*
* @example <caption>It adds iframe HTML tag and 'onclick' attribute for strong tag.</caption>
* function add_extra_kses_allowed_tags( $allowed_html, $context ) {
* if ( 'templates' === $context ) {
* $allowed_html['iframe'] = array(
* 'src' => true,
* );
* $allowed_html['strong']['onclick'] = true;
* }
* return $allowed_html;
* }
* add_filter( 'um_late_escaping_allowed_tags', 'add_extra_kses_allowed_tags', 10, 2 );
*/
$allowed_html = apply_filters( 'um_late_escaping_allowed_tags', $allowed_html, $context );
+1 -1
View File
@@ -472,7 +472,7 @@ if ( ! class_exists( 'um\core\Account' ) ) {
*/
function tab_link( $id ) {
if ( get_option( 'permalink_structure' ) ) {
if ( UM()->is_permalinks ) {
$url = trailingslashit( untrailingslashit( um_get_core_page( 'account' ) ) );
$url = $url . $id . '/';
+82 -21
View File
@@ -1,31 +1,40 @@
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Blocks' ) ) {
/**
* Class Blocks
* @package um\core
*/
class Blocks {
/**
* Access constructor.
* Blocks constructor.
*/
public function __construct() {
add_action( 'init', array( &$this, 'block_editor_render' ), 10 );
add_filter( 'block_type_metadata_settings', array( &$this, 'block_type_metadata_settings' ), 10, 2 );
add_action( 'init', array( &$this, 'block_editor_render' ) );
add_filter( 'block_type_metadata_settings', array( &$this, 'block_type_metadata_settings' ), 9999, 2 );
}
/**
* Add attribute types if restricted blocks is active.
*
* @param array $settings Array of determined settings for registering a block type.
* @param array $args Metadata provided for registering a block type.
*
* @return array
*/
public function block_type_metadata_settings( $settings, $args ) {
$restricted_blocks = UM()->options()->get( 'restricted_blocks' );
if ( empty( $restricted_blocks ) ) {
return $settings;
}
if ( empty( $settings['attributes']['um_is_restrict'] ) ) {
$settings['attributes']['um_is_restrict'] = array(
'type' => 'boolean',
@@ -55,9 +64,31 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
return $settings;
}
/**
* Register UM Blocks.
*
* @uses register_block_type_from_metadata()
*/
public function block_editor_render() {
//disable Gutenberg scripts to avoid the conflicts
/**
* Filters the variable to disable adding UM Blocks to Gutenberg editor.
*
* Note: It's "false" by default. To disable Gutenberg scripts to avoid the conflicts set it to "true"
*
* @since 2.6.3
* @hook um_disable_blocks_script
*
* @param {bool} $disable_script Disabling block scripts variable.
*
* @return {bool} It's true for disabling block scripts.
*
* @example <caption>Disable block scripts.</caption>
* function my_custom_um_disable_blocks_script( $disable_script ) {
* $disable_script = true;
* return $disable_script;
* }
* add_filter( 'um_disable_blocks_script', 'my_custom_um_disable_blocks_script', 10, 1 );
*/
$disable_script = apply_filters( 'um_disable_blocks_script', false );
if ( $disable_script ) {
return;
@@ -70,7 +101,7 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
$blocks = array(
'um-block/um-member-directories' => array(
'render_callback' => array( $this, 'um_member_directories_render' ),
'render_callback' => array( $this, 'member_directories_render' ),
'attributes' => array(
'member_id' => array(
'type' => 'string',
@@ -78,7 +109,7 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
),
),
'um-block/um-forms' => array(
'render_callback' => array( $this, 'um_forms_render' ),
'render_callback' => array( $this, 'forms_render' ),
'attributes' => array(
'form_id' => array(
'type' => 'string',
@@ -86,10 +117,10 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
),
),
'um-block/um-password-reset' => array(
'render_callback' => array( $this, 'um_password_reset_render' ),
'render_callback' => array( $this, 'password_reset_render' ),
),
'um-block/um-account' => array(
'render_callback' => array( $this, 'um_account_render' ),
'render_callback' => array( $this, 'account_render' ),
'attributes' => array(
'tab' => array(
'type' => 'string',
@@ -104,8 +135,16 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
}
}
public function um_member_directories_render( $atts ) {
/**
* Renders member directory block.
*
* @param array $atts Block attributes.
*
* @return string
*
* @uses apply_shortcodes()
*/
public function member_directories_render( $atts ) {
$shortcode = '[ultimatemember';
if ( isset( $atts['member_id'] ) && '' !== $atts['member_id'] ) {
@@ -117,8 +156,16 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
return apply_shortcodes( $shortcode );
}
public function um_forms_render( $atts ) {
/**
* Renders UM Form block.
*
* @param array $atts Block attributes.
*
* @return string
*
* @uses apply_shortcodes()
*/
public function forms_render( $atts ) {
if ( isset( $atts['form_id'] ) && '' !== $atts['form_id'] ) {
$mode = get_post_meta( $atts['form_id'], '_um_mode', true );
if ( 'profile' === $mode && ( um_is_core_page( 'account' ) || um_is_core_page( 'user' ) ) ) {
@@ -136,15 +183,29 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
return apply_shortcodes( $shortcode );
}
public function um_password_reset_render() {
/**
* Renders UM Reset Password form block.
*
* @return string
*
* @uses apply_shortcodes()
*/
public function password_reset_render() {
$shortcode = '[ultimatemember_password]';
return apply_shortcodes( $shortcode );
}
public function um_account_render( $atts ) {
/**
* Renders UM Account block.
*
* @param array $atts Block attributes.
*
* @return string
*
* @uses apply_shortcodes()
*/
public function account_render( $atts ) {
if ( um_is_core_page( 'account' ) || um_is_core_page( 'user' ) ) {
return '';
}
+21 -5
View File
@@ -1,12 +1,12 @@
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Builtin' ) ) {
/**
* Class Builtin
* @package um\core
@@ -627,12 +627,27 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
'validate' => array(
'_title' => array(
'mode' => 'required',
'error' => __('You must provide a title','ultimate-member')
'error' => __( 'You must provide a title', 'ultimate-member' ),
),
'_metakey' => array(
'mode' => 'unique',
),
)
),
),
'spotify' => array(
'name' => __( 'Spotify URL', 'ultimate-member' ),
'col1' => array('_title','_metakey','_help','_visibility'),
'col2' => array('_label','_placeholder','_public','_roles','_validate','_custom_validate'),
'col3' => array('_required','_editable','_icon'),
'validate' => array(
'_title' => array(
'mode' => 'required',
'error' => __( 'You must provide a title', 'ultimate-member' ),
),
'_metakey' => array(
'mode' => 'unique',
),
),
),
/*'group' => array(
@@ -1497,6 +1512,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
$array['unique_username_or_email'] = __('Unique Username/E-mail','ultimate-member');
$array['url'] = __('Website URL','ultimate-member');
$array['youtube_url'] = __('YouTube Profile','ultimate-member');
$array['spotify_url'] = __('Spotify URL','ultimate-member');
$array['telegram_url'] = __('Telegram URL','ultimate-member');
$array['discord'] = __('Discord ID','ultimate-member');
$array['tiktok_url'] = __('TikTok URL','ultimate-member');
+83 -50
View File
@@ -31,7 +31,8 @@ if ( ! class_exists( 'um\core\External_Integrations' ) ) {
add_action( 'um_access_fix_external_post_content', array( &$this, 'forumwp_fix' ), 11 );
add_action( 'um_access_fix_external_post_content', array( &$this, 'woocommerce_fix' ), 12 );
add_filter( 'um_localize_permalink_filter', array( &$this, 'um_localize_permalink_filter' ), 10, 2 );
add_filter( 'um_external_profile_url', array( &$this, 'um_localize_profile_url' ), 10, 2 );
add_filter( 'um_get_current_page_url', array( &$this, 'um_localize_profile_nav_url' ), 10, 2 );
add_filter( 'icl_ls_languages', array( &$this, 'um_core_page_wpml_permalink' ), 10, 1 );
// Integration for the "Transposh Translation Filter" plugin
@@ -50,7 +51,6 @@ if ( ! class_exists( 'um\core\External_Integrations' ) ) {
* UM filter - Restore original arguments on translated page
*
* @description Restore original arguments on load shortcode if they are missed in the WPML translation
* @hook um_pre_args_setup
*
* @global \SitePress $sitepress
* @param array $args
@@ -81,7 +81,6 @@ if ( ! class_exists( 'um\core\External_Integrations' ) ) {
* Integration for the "Transposh Translation Filter" plugin
*
* @description Fix issue "404 Not Found" on profile page
* @hook template_redirect
* @see http://transposh.org/
*
* @global transposh_plugin $my_transposh_plugin
@@ -175,76 +174,110 @@ if ( ! class_exists( 'um\core\External_Integrations' ) ) {
return $single_template;
}
/**
* @param $profile_url
* @param $page_id
* Change user profile URL for WPML compatibility.
*
* @return bool|false|string
* @see \um\core\Permalinks::profile_permalink()
*
* @param bool|string $profile_url Profile URL.
* @param string $slug Profile slug.
*
* @return string
*/
function um_localize_permalink_filter( $profile_url, $page_id ) {
if ( ! $this->is_wpml_active() )
public function um_localize_profile_url( $profile_url, $slug ) {
if ( ! $this->is_wpml_active() ) {
return $profile_url;
}
/*if ( function_exists( 'icl_get_current_language' ) && icl_get_current_language() != icl_get_default_language() ) {
if ( get_the_ID() > 0 && get_post_meta( get_the_ID(), '_um_wpml_user', true ) == 1 ) {
$profile_url = get_permalink( get_the_ID() );
}
}*/
$page_id = UM()->config()->permalinks['user'];
$lang_post_id = apply_filters( 'wpml_object_id', $page_id, 'page', true );
// WPML compatibility
if ( function_exists( 'icl_object_id' ) ) {
$language_code = ICL_LANGUAGE_CODE;
$lang_post_id = icl_object_id( $page_id , 'page', true, $language_code );
if ( $lang_post_id && $lang_post_id !== $page_id ) {
$user_page_url = get_permalink( $lang_post_id );
if ( $lang_post_id != 0 ) {
$profile_url = get_permalink( $lang_post_id );
if ( UM()->is_permalinks ) {
if ( false === strpos( $user_page_url, '?' ) ) {
$profile_url = trailingslashit( $user_page_url ) . trailingslashit( $slug );
} else {
$profile_url = str_replace( '?', trailingslashit( $slug ) . '?', $user_page_url );
}
} else {
// No page found, it's most likely the homepage
global $sitepress;
$profile_url = $sitepress->language_url( $language_code );
$profile_url = add_query_arg( 'um_user', strtolower( $slug ), $user_page_url );
}
}
return $profile_url;
}
/**
* @param $array
* Change current URL for WPML compatibility.
*
* @return mixed
* Note: It's used for User Profile nav links fix
*
* @see \um\core\Permalinks::get_current_url()
*
* @param string $page_url Current URL.
* @param bool $no_query_params Ignore $_GET attributes in URL. "true" == ignore.
*
* @return string
*/
function um_core_page_wpml_permalink( $array ) {
if ( ! $this->is_wpml_active() )
return $array;
global $sitepress;
if( ! um_is_core_page("user") ) return $array;
if( ! defined("ICL_LANGUAGE_CODE") ) return $array;
if( ! function_exists('icl_object_id') ) return $array;
// Permalink base
$permalink_base = UM()->options()->get( 'permalink_base' );
// Get user slug
$profile_slug = strtolower( get_user_meta( um_profile_id(), "um_user_profile_url_slug_{$permalink_base}", true ) );
$current_language = ICL_LANGUAGE_CODE;
foreach ( $array as $lang_code => $arr ) {
$sitepress->switch_lang( $lang_code );
$user_page = um_get_core_page( "user" );
$array[ $lang_code ]['url'] = "{$user_page}{$profile_slug}/";
public function um_localize_profile_nav_url( $page_url, $no_query_params ) {
if ( ! $this->is_wpml_active() ) {
return $page_url;
}
$sitepress->switch_lang( $current_language );
if ( false === $no_query_params ) {
return $page_url;
}
if ( ! empty( $_GET['lang'] ) ) {
$page_url = add_query_arg( 'lang', sanitize_key( $_GET['lang'] ), $page_url );
}
return $page_url;
}
/**
* Filters the displayed languages of the WPML language switcher.
*
* @see https://wpml.org/wpml-hook/icl_ls_languages/
*
* @param array $array Collection of active languages to display in the language switcher.
*
* @return array
*/
public function um_core_page_wpml_permalink( $array ) {
if ( $this->is_wpml_active() && um_is_core_page( 'user' ) && is_array( $array ) ) {
global $sitepress;
$current_language = wpml_get_current_language();
$slug = strtolower( UM()->user()->get_profile_slug( um_profile_id() ) );
foreach ( $array as $lang_code => $arr ) {
$sitepress->switch_lang( $lang_code );
$lang_post_id = apply_filters( 'wpml_object_id', UM()->config()->permalinks['user'], 'page', true );
$user_page_url = get_permalink( $lang_post_id );
if ( UM()->is_permalinks ) {
if ( false === strpos( $user_page_url, '?' ) ) {
$profile_url = trailingslashit( $user_page_url ) . trailingslashit( $slug );
} else {
$profile_url = str_replace( '?', trailingslashit( $slug ) . '?', $user_page_url );
}
} else {
$profile_url = add_query_arg( 'um_user', strtolower( $slug ), $user_page_url );
}
$array[ $lang_code ]['url'] = $profile_url;
}
$sitepress->switch_lang( $current_language );
}
return $array;
}
/**
* Check if WPML is active
*
+16 -10
View File
@@ -1,13 +1,12 @@
<?php
namespace um\core;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Fields' ) ) {
/**
* Class Fields
* @package um\core
@@ -393,6 +392,8 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
}
update_post_meta( $directory_id, '_um_sortby_custom', '' );
update_post_meta( $directory_id, '_um_sortby_custom_label', '' );
update_post_meta( $directory_id, '_um_sortby_custom_type', '' );
update_post_meta( $directory_id, '_um_sortby_custom_order', '' );
}
}
@@ -1651,6 +1652,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
case 'youtube_video':
case 'vimeo_video':
case 'soundcloud_track':
case 'spotify':
$array['disabled'] = '';
$array['input'] = 'text';
break;
@@ -2380,6 +2382,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
case 'googlemap':
case 'youtube_video':
case 'vimeo_video':
case 'spotify':
case 'soundcloud_track':
$output .= '<div ' . $this->get_atts( $key, $classes, $conditional, $data ) . '>';
@@ -2814,7 +2817,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
$output .= '<div class="um-field-area">';
if ( isset( $data['html'] ) && $data['html'] != 0 && $key != "description" ) {
if ( isset( $data['html'] ) && $data['html'] != 0 && 'description' !== $key ) {
$textarea_settings = array(
'media_buttons' => false,
@@ -2863,7 +2866,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
$output .= ob_get_clean();
$output .= '<br /><span class="description">' . $placeholder . '</span>';
} else {
$textarea_field_value = ! empty( $data['html'] ) ? $field_value : strip_tags( $field_value );
$textarea_field_value = '';
if ( ! empty( $field_value ) ) {
$textarea_field_value = ! empty( $data['html'] ) ? $field_value : wp_strip_all_tags( $field_value );
}
$output .= '<textarea ' . $disabled . ' style="height: ' . esc_attr( $height ) . ';" class="' . $this->get_class( $key, $data ) . '" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_id ) . '" placeholder="' . esc_attr( $placeholder ) . '">' . esc_textarea( $textarea_field_value ) . '</textarea>';
}
@@ -3881,9 +3887,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
$um_field_checkbox_item_title = $v;
$v = $this->filter_field_non_utf8_value( $v );
$v = $this->filter_field_non_utf8_value( $v );
$value_attr = ( ! empty( $v ) && is_string( $v ) ) ? wp_strip_all_tags( $v ) : $v;
$output .= '<input ' . $disabled . ' type="checkbox" name="' . esc_attr( $key ) . '[]" value="' . strip_tags( $v ) . '" ';
$output .= '<input ' . $disabled . ' type="checkbox" name="' . esc_attr( $key ) . '[]" value="' . esc_attr( $value_attr ) . '" ';
if ( $this->is_selected( $key, $v, $data ) ) {
$output .= 'checked';
@@ -3892,10 +3899,9 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
$output .= ' />';
if ( ! empty( $disabled ) && $this->is_selected( $key, $v, $data ) ) {
$output .= $this->disabled_hidden_field( $key . '[]', strip_tags( $v ) );
$output .= $this->disabled_hidden_field( $key . '[]', $value_attr );
}
$output .= '<span class="um-field-checkbox-state"><i class="' . esc_attr( $class ) . '"></i></span>';
/**
* UM hook
+18 -15
View File
@@ -1,42 +1,47 @@
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\FontIcons' ) ) {
/**
* Class FontIcons
* @package um\core
*/
class FontIcons {
/**
* The list of the FontIcons.
*
* @var array
*/
public $all = array();
/**
* FontIcons constructor.
*/
function __construct() {
if ( ! get_option( 'um_cache_fonticons' ) ) {
public function __construct() {
$cached_option = get_option( 'um_cache_fonticons', array() );
if ( empty( $cached_option ) ) {
$files['ii'] = um_path . 'assets/css/um-fonticons-ii.css';
$files['fa'] = um_path . 'assets/css/um-fonticons-fa.css';
$array = array();
foreach ( $files as $c => $file ) {
$css = file_get_contents( $file );
if ( $c == 'fa' ) {
preg_match_all('/\.(um-faicon-.*?):before/', $css, $matches);
if ( 'fa' === $c ) {
preg_match_all( '/\.(um-faicon-.*?):before/', $css, $matches );
} else {
preg_match_all('/\.(um-icon-.*?):before/', $css, $matches);
preg_match_all( '/\.(um-icon-.*?):before/', $css, $matches );
}
foreach ( $matches[1] as $match ) {
$icon = str_replace( ':before', '', $match );
$icon = str_replace( ':before', '', $match );
$array[] = $icon;
}
$array = array_unique( $array );
@@ -45,9 +50,7 @@ if ( ! class_exists( 'um\core\FontIcons' ) ) {
update_option( 'um_cache_fonticons', $array );
}
$this->all = get_option( 'um_cache_fonticons' );
$this->all = $cached_option;
}
}
}
}
+9 -3
View File
@@ -1,12 +1,12 @@
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Form' ) ) {
/**
* Class Form
* @package um\core
@@ -23,6 +23,11 @@ if ( ! class_exists( 'um\core\Form' ) ) {
*/
public $form_id;
/**
* @var
*/
public $form_status;
/**
* @var null
*/
@@ -738,6 +743,7 @@ if ( ! class_exists( 'um\core\Form' ) ) {
case 'youtube_video':
case 'vimeo_video':
case 'soundcloud_track':
case 'spotify':
$form[ $k ] = sanitize_text_field( $form[ $k ] );
break;
case 'multiselect':
+1 -1
View File
@@ -117,7 +117,7 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
* @param string $template_name
* @return string
*/
private function locate_template( $template_name ) {
public function locate_template( $template_name ) {
// check if there is template at theme folder
$blog_id = $this->get_blog_id();
+56 -38
View File
@@ -1,27 +1,36 @@
<?php
namespace um\core;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
/**
* Class Member_Directory_Meta
* @package um\core
*/
class Member_Directory_Meta extends Member_Directory {
/**
* @var array
*/
public $joins = array();
/**
* @var string
* @var array
*/
var $joins = array();
var $where_clauses = array();
public $where_clauses = array();
var $roles = array();
/**
* @var array
*/
public $roles = array();
/**
* @var bool
*/
var $roles_in_query = false;
var $general_meta_joined = false;
@@ -35,7 +44,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
/**
* Member_Directory_Meta constructor.
*/
function __construct() {
public function __construct() {
parent::__construct();
add_action( 'updated_user_meta', array( &$this, 'on_update_usermeta' ), 10, 4 );
@@ -144,10 +153,10 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
global $wpdb;
$result = $wpdb->get_var( $wpdb->prepare(
"SELECT umeta_id
FROM {$wpdb->prefix}um_metadata
WHERE user_id = %d AND
um_key = %s
"SELECT umeta_id
FROM {$wpdb->prefix}um_metadata
WHERE user_id = %d AND
um_key = %s
LIMIT 1",
$object_id,
$meta_key
@@ -501,7 +510,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
}
}
$profile_photo_where = '';
if ( $directory_data['has_profile_photo'] == 1 ) {
$profile_photo_where = " AND umm_general.um_value LIKE '%s:13:\"profile_photo\";b:1;%'";
@@ -517,7 +525,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
$this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_general ON umm_general.user_id = u.ID";
$this->general_meta_joined = true;
}
$this->where_clauses[] = "( umm_general.um_key = 'um_member_directory_data' AND
$this->where_clauses[] = "( umm_general.um_key = 'um_member_directory_data' AND
umm_general.um_value LIKE '%s:14:\"account_status\";s:8:\"approved\";%' AND umm_general.um_value LIKE '%s:15:\"hide_in_members\";b:0;%'{$profile_photo_where}{$cover_photo_where} )";
} else {
if ( ! empty( $cover_photo_where ) || ! empty( $profile_photo_where ) ) {
@@ -578,7 +586,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
}
}
if ( ! empty( $_POST['search'] ) ) {
$search_line = trim( stripslashes( sanitize_text_field( $_POST['search'] ) ) );
@@ -600,7 +607,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
$this->is_search = true;
}
//filters
$filter_query = array();
if ( ! empty( $directory_data['search_fields'] ) ) {
@@ -638,7 +644,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
}
}
//unable default filter in case if we select other filters in frontend filters
//if ( empty( $this->custom_filters_in_query ) ) {
$default_filters = array();
@@ -676,7 +681,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
if ( ! empty( UM()->builtin()->saved_fields ) ) {
foreach ( UM()->builtin()->saved_fields as $key => $data ) {
if ( $key == '_um_last_login' ) {
if ( '_um_last_login' === $key ) {
continue;
}
@@ -694,12 +699,29 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
// handle sorting options
// sort members by
if ( $sortby == $directory_data['sortby_custom'] || in_array( $sortby, $custom_sort ) ) {
$custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC';
$this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_sort ON ( umm_sort.user_id = u.ID AND umm_sort.um_key = '{$sortby}' )";
$custom_sort_type = apply_filters( 'um_member_directory_custom_sorting_type', 'CHAR', $sortby, $directory_data );
$meta_query = new \WP_Meta_Query();
$custom_sort_type = ! empty( $directory_data['sortby_custom_type'] ) ? $meta_query->get_cast_for_type( $directory_data['sortby_custom_type'] ) : 'CHAR';
if ( ! empty( $directory_data['sorting_fields'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification -- already verified here
$sorting = sanitize_text_field( $_POST['sorting'] );
$sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
$this->sql_order = " ORDER BY CAST( umm_sort.um_value AS {$custom_sort_type} ) {$order} ";
foreach ( $sorting_fields as $field ) {
if ( isset( $field[ $sorting ] ) ) {
$custom_sort_type = ! empty( $field['type'] ) ? $meta_query->get_cast_for_type( $field['type'] ) : 'CHAR';
$custom_sort_order = $field['order'];
}
}
}
/** This filter is documented in includes/core/class-member-directory.php */
$custom_sort_type = apply_filters( 'um_member_directory_custom_sorting_type', $custom_sort_type, $sortby, $directory_data );
$this->sql_order = " ORDER BY CAST( umm_sort.um_value AS {$custom_sort_type} ) {$custom_sort_order} ";
} elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys ) ) {
@@ -802,7 +824,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
$this->sql_order = apply_filters( 'um_modify_sortby_parameter_meta', $this->sql_order, $sortby );
$profiles_per_page = $directory_data['profiles_per_page'];
if ( UM()->mobile()->isMobile() && isset( $directory_data['profiles_per_page_mobile'] ) ) {
$profiles_per_page = $directory_data['profiles_per_page_mobile'];
@@ -856,25 +877,22 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
$total_users = (int) $wpdb->get_var( 'SELECT FOUND_ROWS()' );
/**
* UM hook
* Filters the member directory query result when um_usermeta table is used.
*
* @type filter
* @title um_prepare_user_results_array_meta
* @description Extend member directory query result
* @input_vars
* [{"var":"$result","type":"array","desc":"Members Query Result"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_prepare_user_results_array', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_prepare_user_results_array', 'my_prepare_user_results', 10, 2 );
* function my_prepare_user_results( $user_ids, $query ) {
* // your code here
* @since 2.1.3
* @hook um_prepare_user_results_array_meta
*
* @param {array} $user_ids Members Query Result.
* @param {array} $query_args Query arguments.
*
* @return {array} Query result.
*
* @example <caption>Remove some users where ID equals 10 and 12 from query.</caption>
* function my_custom_um_prepare_user_results_array_meta( $user_ids, $query_args ) {
* $user_ids = array_diff( $user_ids, array( 10, 12 ) );
* return $user_ids;
* }
* ?>
* add_filter( 'um_prepare_user_results_array_meta', 'my_custom_um_prepare_user_results_array', 10, 2 );
*/
$user_ids = apply_filters( 'um_prepare_user_results_array_meta', $user_ids, $query );
+120 -33
View File
@@ -1,20 +1,18 @@
<?php
namespace um\core;
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Member_Directory' ) ) {
/**
* Class Member_Directory
* @package um\core
*/
class Member_Directory {
/**
* Member Directory Views
*
@@ -28,6 +26,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
*/
var $sort_fields = array();
/**
* @var array
*/
var $sort_data_types = array();
/**
* @var array
@@ -210,7 +212,6 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
if ( ! empty( $value ) && in_array( $key, array( '_um_view_types', '_um_roles', '_um_roles_can_search', '_um_roles_can_filter' ), true ) ) {
$value = array_keys( $value );
} elseif ( '_um_search_filters' === $key ) {
$temp_value = array();
if ( ! empty( $value ) ) {
@@ -264,8 +265,17 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
if ( ! empty( $other_data[ $k ]['label'] ) ) {
$metalabel = wp_strip_all_tags( $other_data[ $k ]['label'] );
}
if ( ! empty( $other_data[ $k ]['data_type'] ) ) {
$data_type = sanitize_text_field( $other_data[ $k ]['data_type'] );
}
if ( ! empty( $other_data[ $k ]['order'] ) ) {
$order = sanitize_text_field( $other_data[ $k ]['order'] );
}
$row = array(
$metakey => ! empty( $metalabel ) ? $metalabel : $metakey,
$metakey => $metakey,
'label' => ! empty( $metalabel ) ? $metalabel : $metakey,
'type' => ! empty( $data_type ) ? $data_type : '',
'order' => ! empty( $order ) ? $order : '',
);
}
}
@@ -275,6 +285,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$value = sanitize_text_field( $value );
} elseif ( '_um_sortby_custom_label' === $key ) {
$value = wp_strip_all_tags( $value );
} elseif ( '_um_sortby_custom_type' === $key ) {
$value = sanitize_text_field( $value );
} elseif ( '_um_sortby_custom_order' === $key ) {
$value = sanitize_text_field( $value );
}
}
@@ -308,6 +322,20 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$this->sorting_supported_fields = apply_filters( 'um_members_directory_custom_field_types_supported_sorting', array( 'number' ) );
$this->sort_data_types = array(
'CHAR' => __( 'CHAR', 'ultimate-member' ),
'NUMERIC' => __( 'NUMERIC', 'ultimate-member' ),
'BINARY' => __( 'BINARY', 'ultimate-member' ),
'DATE' => __( 'DATE', 'ultimate-member' ),
'DATETIME' => __( 'DATETIME', 'ultimate-member' ),
'DECIMAL' => __( 'DECIMAL', 'ultimate-member' ),
'SIGNED' => __( 'SIGNED', 'ultimate-member' ),
'TIME' => __( 'TIME', 'ultimate-member' ),
'UNSIGNED' => __( 'UNSIGNED', 'ultimate-member' ),
);
$this->sort_data_types = apply_filters( 'um_members_directory_sort_data_types', $this->sort_data_types );
if ( ! empty( UM()->builtin()->saved_fields ) ) {
foreach ( UM()->builtin()->saved_fields as $key => $data ) {
if ( $key == '_um_last_login' ) {
@@ -1422,23 +1450,64 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
unset( $this->query_args['order'] );
} elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby == $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort ) ) {
$custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC';
$custom_sort_type = apply_filters( 'um_member_directory_custom_sorting_type', 'CHAR', $sortby, $directory_data );
$meta_query = new \WP_Meta_Query();
$custom_sort_type = ! empty( $directory_data['sortby_custom_type'] ) ? $meta_query->get_cast_for_type( $directory_data['sortby_custom_type'] ) : 'CHAR';
if ( ! empty( $directory_data['sorting_fields'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification -- already verified here
$sorting = sanitize_text_field( $_POST['sorting'] );
$sorting_fields = maybe_serialize( $directory_data['sorting_fields'] );
foreach ( $sorting_fields as $field ) {
if ( isset( $field[ $sorting ] ) ) {
$custom_sort_type = ! empty( $field['type'] ) ? $meta_query->get_cast_for_type( $field['type'] ) : 'CHAR';
$custom_sort_order = $field['order'];
}
}
}
/**
* Filters the sorting MySQL type in member directory custom sorting query.
*
* Note: Possible MySQL types are BINARY|CHAR|DATE|DATETIME|SIGNED|UNSIGNED|TIME|DECIMAL
*
* @since 2.1.3
* @hook um_member_directory_custom_sorting_type
*
* @param {string} $custom_sort_type MySQL type to cast meta_value. 'CHAR' is default.
* @param {string} $sortby meta_key used for sorting.
* @param {array} $directory_data Member directory data.
*
* @return {string} MySQL type to cast meta_value.
* @example <caption>Change type to DATE by the directory ID and mete_key.</caption>
* function my_um_member_directory_custom_sorting_type( $custom_sort_type, $sortby, $directory_data ) {
* if ( '{selected member directory ID}' == $directory_data['form_id'] && '{custom_date_key}' === $sortby ) {
* $custom_sort_type = 'DATE';
* }
*
* return $custom_sort_type;
* }
* add_filter( 'um_member_directory_custom_sorting_type', 'my_um_member_directory_custom_sorting_type', 10, 3 );
*/
$custom_sort_type = apply_filters( 'um_member_directory_custom_sorting_type', $custom_sort_type, $sortby, $directory_data );
$this->query_args['meta_query'][] = array(
'relation' => 'OR',
'relation' => 'OR',
$sortby . '_cs' => array(
'key' => $sortby,
'compare' => 'EXISTS',
'type' => $custom_sort_type,
'key' => $sortby,
'compare' => 'EXISTS',
'type' => $custom_sort_type,
),
array(
'key' => $sortby,
'compare' => 'NOT EXISTS',
)
'key' => $sortby,
'compare' => 'NOT EXISTS',
),
);
$this->query_args['orderby'] = array( $sortby . '_cs' => 'ASC', 'user_login' => 'ASC' );
$this->query_args['orderby'] = array(
$sortby . '_cs' => $custom_sort_order,
'user_login' => 'ASC',
);
} else {
@@ -2648,29 +2717,25 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$user_ids = ! empty( $user_query->results ) ? array_unique( $user_query->results ) : array();
/**
* UM hook
* Filters the member directory query result.
*
* @type filter
* @title um_prepare_user_results_array
* @description Extend member directory query result
* @input_vars
* [{"var":"$result","type":"array","desc":"Members Query Result"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_prepare_user_results_array', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_prepare_user_results_array', 'my_prepare_user_results', 10, 2 );
* function my_prepare_user_results( $user_ids, $query ) {
* // your code here
* @since 2.0
* @hook um_prepare_user_results_array
*
* @param {array} $user_ids Members Query Result.
* @param {array} $query_args Query arguments.
*
* @return {array} Query result.
*
* @example <caption>Remove some users where ID equals 10 and 12 from query.</caption>
* function my_custom_um_prepare_user_results_array( $user_ids, $query_args ) {
* $user_ids = array_diff( $user_ids, array( 10, 12 ) );
* return $user_ids;
* }
* ?>
* add_filter( 'um_prepare_user_results_array', 'my_custom_um_prepare_user_results_array', 10, 2 );
*/
$user_ids = apply_filters( 'um_prepare_user_results_array', $user_ids, $this->query_args );
$sizes = UM()->options()->get( 'cover_thumb_sizes' );
$this->cover_size = UM()->mobile()->isTablet() ? $sizes[1] : end( $sizes );
@@ -2762,5 +2827,27 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
wp_send_json_success( array( 'field_html' => $html ) );
}
/**
* Get member directory id by page id.
*
* @param int $page_id Page ID.
*
* @return array Member directories ID.
*/
public function get_member_directory_id( $page_id ) {
$members_page = get_post( $page_id );
if ( ! empty( $members_page ) && ! is_wp_error( $members_page ) ) {
if ( ! empty( $members_page->post_content ) ) {
preg_match_all( '/\[ultimatemember[^\]]*?form_id\=[\'"]*?(\d+)[\'"]*?/i', $members_page->post_content, $matches );
if ( ! empty( $matches[1] ) && is_array( $matches[1] ) ) {
$member_directory_ids = array_map( 'absint', $matches[1] );
return $member_directory_ids;
}
}
}
return array();
}
}
}
+199 -186
View File
@@ -1,35 +1,32 @@
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Permalinks' ) ) {
/**
* Class Permalinks
* @package um\core
*/
class Permalinks {
/**
* @var
*/
var $core;
/**
* @var
*/
var $current_url;
/**
* Permalinks constructor.
*/
function __construct() {
public function __construct() {
add_action( 'init', array( &$this, 'set_current_url' ), 0 );
add_action( 'init', array( &$this, 'check_for_querystrings' ), 1 );
@@ -37,78 +34,19 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
add_action( 'init', array( &$this, 'activate_account_via_email_link' ), 1 );
}
/**
* Set current URL variable
*/
function set_current_url() {
public function set_current_url() {
$this->current_url = $this->get_current_url();
}
/**
* SEO canonical href bugfix
*
* @deprecated since version 2.1.7
*
* @see function um_profile_remove_wpseo()
*/
function um_rel_canonical_() {
global $wp_the_query;
if ( ! is_singular() )
return;
/**
* UM hook
*
* @type filter
* @title um_allow_canonical__filter
* @description Allow canonical
* @input_vars
* [{"var":"$allow_canonical","type":"bool","desc":"Allow?"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_allow_canonical__filter', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_allow_canonical__filter', 'my_allow_canonical', 10, 1 );
* function my_allow_canonical( $allow_canonical ) {
* // your code here
* return $allow_canonical;
* }
* ?>
*/
$enable_canonical = apply_filters( "um_allow_canonical__filter", true );
if( ! $enable_canonical )
return;
if ( !$id = $wp_the_query->get_queried_object_id() )
return;
if ( UM()->config()->permalinks['user'] == $id ) {
$link = esc_url( $this->get_current_url() );
echo "<link rel='canonical' href='$link' />\n";
return;
}
$link = get_permalink( $id );
if ( $page = get_query_var( 'cpage' ) ){
$link = get_comments_pagenum_link( $page );
echo "<link rel='canonical' href='$link' />\n";
}
}
/**
* Get query as array
*
* @return array
*/
function get_query_array() {
public function get_query_array() {
$parts = parse_url( $this->get_current_url() );
if ( isset( $parts['query'] ) ) {
parse_str( $parts['query'], $query );
@@ -118,66 +56,61 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
return array();
}
/**
* Get current URL anywhere
*
* @param bool $no_query_params
*
* @return mixed|void
* @return string
*/
function get_current_url( $no_query_params = false ) {
public function get_current_url( $no_query_params = false ) {
//use WP native function for fill $_SERVER variables by correct values
wp_fix_server_vars();
//check if WP-CLI there isn't set HTTP_HOST, use localhost instead
if ( defined( 'WP_CLI' ) && WP_CLI ) {
$host = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : 'localhost';
} else{
if ( isset( $_SERVER['HTTP_HOST'] ) ) {
$host = $_SERVER['HTTP_HOST'];
}else{
$host = 'localhost';
}
}
} else {
if ( isset( $_SERVER['HTTP_HOST'] ) ) {
$host = $_SERVER['HTTP_HOST'];
} else {
$host = 'localhost';
}
}
$page_url = ( is_ssl() ? 'https://' : 'http://' ) . $host . $_SERVER['REQUEST_URI'];
if ( $no_query_params == true ) {
if ( false !== $no_query_params ) {
$page_url = strtok( $page_url, '?' );
}
/**
* UM hook
* Filters current page URL.
*
* @type filter
* @title um_get_current_page_url
* @description Change current page URL
* @input_vars
* [{"var":"$page_url","type":"string","desc":"Page URL"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_get_current_page_url', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_get_current_page_url', 'my_get_current_page_url', 10, 1 );
* function my_get_current_page_url( $page_url ) {
* // your code here
* @param {string} $page_url Current page URL.
* @param {bool} $no_query_params Ignore $_GET attributes in URL. false !== ignore.
*
* @return {string} Current page URL.
*
* @since 1.3.x
* @hook um_get_current_page_url
*
* @example <caption>Add your custom $_GET attribute to all links.</caption>
* function my_um_get_current_page_url( $page_url, $no_query_params ) {
* $page_url = add_query_arg( '{attr_value}', '{attr_key}', $page_url ); // replace to your custom value and key.
* return $page_url;
* }
* ?>
* add_filter( 'um_get_current_page_url', 'my_um_get_current_page_url', 10, 2 );
*/
return apply_filters( 'um_get_current_page_url', $page_url );
return apply_filters( 'um_get_current_page_url', $page_url, $no_query_params );
}
/**
* Activates an account via email
*/
public function activate_account_via_email_link() {
if ( isset( $_REQUEST['act'] ) && 'activate_via_email' === sanitize_key( $_REQUEST['act'] ) && isset( $_REQUEST['hash'] ) && is_string( $_REQUEST['hash'] ) && strlen( $_REQUEST['hash'] ) == 40 &&
isset( $_REQUEST['user_id'] ) && is_numeric( $_REQUEST['user_id'] ) ) { // valid token
isset( $_REQUEST['user_id'] ) && is_numeric( $_REQUEST['user_id'] ) ) { // valid token
$user_id = absint( $_REQUEST['user_id'] );
delete_option( "um_cache_userdata_{$user_id}" );
@@ -238,18 +171,15 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
$redirect = apply_filters( 'um_after_email_confirmation_redirect', $redirect, $user_id, $login );
exit( wp_redirect( $redirect ) );
}
}
/**
* Makes an activate link for any user
*
* @return bool|string
*/
function activate_url() {
public function activate_url() {
if ( ! um_user( 'account_secret_hash' ) ) {
return false;
}
@@ -283,17 +213,15 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
return $url;
}
/**
* Checks for UM query strings
*/
function check_for_querystrings() {
public function check_for_querystrings() {
if ( isset( $_REQUEST['message'] ) ) {
UM()->shortcodes()->message_mode = true;
}
}
/**
* Add a query param to url
*
@@ -302,12 +230,11 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
*
* @return string
*/
function add_query( $key, $value ) {
public function add_query( $key, $value ) {
$this->current_url = add_query_arg( $key, $value, $this->get_current_url() );
return $this->current_url;
}
/**
* Remove a query param from url
*
@@ -316,26 +243,25 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
*
* @return string
*/
function remove_query( $key, $value ) {
public function remove_query( $key, $value ) {
$this->current_url = remove_query_arg( $key, $this->current_url );
return $this->current_url;
}
/**
* @param $slug
*
* @return int|null|string
*/
function slug_exists_user_id( $slug ) {
public function slug_exists_user_id( $slug ) {
global $wpdb;
$permalink_base = UM()->options()->get( 'permalink_base' );
$user_id = $wpdb->get_var(
"SELECT user_id
FROM {$wpdb->usermeta}
WHERE meta_key = 'um_user_profile_url_slug_{$permalink_base}' AND
"SELECT user_id
FROM {$wpdb->usermeta}
WHERE meta_key = 'um_user_profile_url_slug_{$permalink_base}' AND
meta_value = '{$slug}'
ORDER BY umeta_id ASC
LIMIT 1"
@@ -348,57 +274,93 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
return false;
}
/**
* Get Profile Permalink
*
* @param string $slug
* @return string $profile_url
*
* @return string
*/
function profile_permalink( $slug ) {
public function profile_permalink( $slug ) {
/**
* Filters user profile URL externally with own logic.
*
* @since 2.6.3
* @hook um_external_profile_url
*
* @param {bool|string} $profile_url Profile URL.
* @param {string} $slug User profile slug.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile URL to your custom link and ignore native profile permalink handlers.</caption>
* function my_um_external_profile_url( $profile_url, $slug ) {
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* add_filter( 'um_external_profile_url', 'my_um_external_profile_url', 10, 2 );
*/
$external_profile_url = apply_filters( 'um_external_profile_url', false, $slug );
if ( false !== $external_profile_url ) {
return ! empty( $external_profile_url ) ? $external_profile_url : '';
}
$page_id = UM()->config()->permalinks['user'];
$page_id = UM()->config()->permalinks['user'];
$profile_url = get_permalink( $page_id );
/**
* UM hook
* Filters the base URL of the UM profile page.
*
* @type filter
* @title um_localize_permalink_filter
* @description Change user profile URL
* @input_vars
* [{"var":"$profile_url","type":"string","desc":"Profile URL"},
* {"var":"$page_id","type":"int","desc":"Profile Page ID"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_localize_permalink_filter', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_localize_permalink_filter', 'my_localize_permalink', 10, 2 );
* @since 1.3.x
* @deprecated 2.6.3 Use <a href="https://developer.wordpress.org/reference/hooks/post_link/" target="_blank" title="'post_link' hook article on developer.wordpress.org">'post_link'</a> instead.
* @hook um_localize_permalink_filter
* @todo fully remove since 2.7.0
*
* @param {string} $profile_url Profile URL.
* @param {int} $page_id Profile Page ID.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile base URL to your custom link.</caption>
* function my_localize_permalink( $profile_url, $page_id ) {
* // your code here
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* ?>
* add_filter( 'um_localize_permalink_filter', 'my_localize_permalink', 10, 2 );
*/
$profile_url = apply_filters( 'um_localize_permalink_filter', $profile_url, $page_id );
if ( get_option( 'permalink_structure' ) ) {
$profile_url = trailingslashit( untrailingslashit( $profile_url ) );
$profile_url = $profile_url . strtolower( $slug ). '/';
if ( UM()->is_permalinks ) {
$profile_url = trailingslashit( untrailingslashit( $profile_url ) );
$profile_url .= trailingslashit( strtolower( $slug ) );
} else {
$profile_url = add_query_arg( 'um_user', strtolower( $slug ), $profile_url );
$profile_url = add_query_arg( 'um_user', strtolower( $slug ), $profile_url );
}
/**
* Filters user profile URL.
*
* @since 2.6.3
* @hook um_profile_permalink
*
* @param {string} $profile_url Profile URL.
* @param {int} $page_id Profile Page ID.
* @param {string} $slug User profile slug.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile URL to your custom link.</caption>
* function my_um_profile_permalink( $profile_url, $page_id, $slug ) {
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* add_filter( 'um_profile_permalink', 'my_um_profile_permalink', 10, 3 );
*/
$profile_url = apply_filters( 'um_profile_permalink', $profile_url, $page_id, $slug );
return ! empty( $profile_url ) ? $profile_url : '';
}
/**
* Generate profile slug
*
@@ -407,41 +369,38 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
* @param string $last_name
* @return string
*/
function profile_slug( $full_name, $first_name, $last_name ){
public function profile_slug( $full_name, $first_name, $last_name ) {
$permalink_base = UM()->options()->get( 'permalink_base' );
$user_in_url = '';
$full_name = str_replace("'", "", $full_name );
$full_name = str_replace("&", "", $full_name );
$full_name = str_replace("/", "", $full_name );
$full_name = str_replace( "'", "", $full_name );
$full_name = str_replace( "&", "", $full_name );
$full_name = str_replace( "/", "", $full_name );
switch( $permalink_base ) {
switch ( $permalink_base ) {
case 'name': // dotted
$full_name_slug = $full_name;
$difficulties = 0;
if( strpos( $full_name, '.' ) > -1 ){
$full_name = str_replace(".", "_", $full_name );
if ( strpos( $full_name, '.' ) > -1 ) {
$full_name = str_replace( ".", "_", $full_name );
$difficulties++;
}
$full_name = strtolower( str_replace( " ", ".", $full_name ) );
if( strpos( $full_name, '_.' ) > -1 ){
$full_name = str_replace('_.', '_', $full_name );
if ( strpos( $full_name, '_.' ) > -1 ) {
$full_name = str_replace( '_.', '_', $full_name );
$difficulties++;
}
$full_name_slug = str_replace( '-' , '.', $full_name_slug );
$full_name_slug = str_replace( ' ' , '.', $full_name_slug );
$full_name_slug = str_replace( '..' , '.', $full_name_slug );
$full_name_slug = str_replace( '-', '.', $full_name_slug );
$full_name_slug = str_replace( ' ', '.', $full_name_slug );
$full_name_slug = str_replace( '..', '.', $full_name_slug );
if( strpos( $full_name, '.' ) > -1 ){
$full_name = str_replace('.', ' ', $full_name );
if ( strpos( $full_name, '.' ) > -1 ) {
$full_name = str_replace( '.', ' ', $full_name );
$difficulties++;
}
@@ -450,76 +409,73 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
break;
case 'name_dash': // dashed
$difficulties = 0;
$full_name_slug = strtolower( $full_name );
// if last name has dashed replace with underscore
if( strpos( $last_name, '-') > -1 && strpos( $full_name, '-' ) > -1 ){
if ( strpos( $last_name, '-' ) > -1 && strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
$full_name = str_replace('-', '_', $full_name );
$full_name = str_replace( '-', '_', $full_name );
}
// if first name has dashed replace with underscore
if( strpos( $first_name, '-') > -1 && strpos( $full_name, '-' ) > -1 ){
if ( strpos( $first_name, '-' ) > -1 && strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
$full_name = str_replace('-', '_', $full_name );
$full_name = str_replace( '-', '_', $full_name );
}
// if name has space, replace with dash
$full_name_slug = str_replace( ' ' , '-', $full_name_slug );
$full_name_slug = str_replace( ' ', '-', $full_name_slug );
// if name has period
if( strpos( $last_name, '.') > -1 && strpos( $full_name, '.' ) > -1 ){
if ( strpos( $last_name, '.' ) > -1 && strpos( $full_name, '.' ) > -1 ) {
$difficulties++;
}
$full_name_slug = str_replace( '.' , '-', $full_name_slug );
$full_name_slug = str_replace( '--' , '-', $full_name_slug );
$full_name_slug = str_replace( '.', '-', $full_name_slug );
$full_name_slug = str_replace( '--', '-', $full_name_slug );
$user_in_url = rawurlencode( $full_name_slug );
$user_in_url = rawurlencode( $full_name_slug );
break;
case 'name_plus': // plus
$difficulties = 0;
$full_name_slug = strtolower( $full_name );
// if last name has dashed replace with underscore
if( strpos( $last_name, '+') > -1 && strpos( $full_name, '+' ) > -1 ){
if ( strpos( $last_name, '+' ) > -1 && strpos( $full_name, '+' ) > -1 ) {
$difficulties++;
$full_name = str_replace('-', '_', $full_name );
$full_name = str_replace( '-', '_', $full_name );
}
// if first name has dashed replace with underscore
if( strpos( $first_name, '+') > -1 && strpos( $full_name, '+' ) > -1 ){
if ( strpos( $first_name, '+' ) > -1 && strpos( $full_name, '+' ) > -1 ) {
$difficulties++;
$full_name = str_replace('-', '_', $full_name );
$full_name = str_replace( '-', '_', $full_name );
}
if( strpos( $last_name, '-') > -1 || strpos( $first_name, '-') > -1 || strpos( $full_name, '-') > -1 ){
if ( strpos( $last_name, '-' ) > -1 || strpos( $first_name, '-' ) > -1 || strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
}
// if name has space, replace with dash
$full_name_slug = str_replace( ' ' , '+', $full_name_slug );
$full_name_slug = str_replace( '-' , '+', $full_name_slug );
$full_name_slug = str_replace( ' ', '+', $full_name_slug );
$full_name_slug = str_replace( '-', '+', $full_name_slug );
// if name has period
if( strpos( $last_name, '.') > -1 && strpos( $full_name, '.' ) > -1 ){
if ( strpos( $last_name, '.' ) > -1 && strpos( $full_name, '.' ) > -1 ) {
$difficulties++;
}
$full_name_slug = str_replace( '.' , '+', $full_name_slug );
$full_name_slug = str_replace( '++' , '+', $full_name_slug );
$full_name_slug = str_replace( '.', '+', $full_name_slug );
$full_name_slug = str_replace( '++', '+', $full_name_slug );
$user_in_url = $full_name_slug;
break;
}
return $user_in_url ;
return $user_in_url;
}
/**
* Get action url for admin use
*
@@ -528,12 +484,69 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
*
* @return mixed|string|void
*/
function admin_act_url( $action, $subaction ) {
public function admin_act_url( $action, $subaction ) {
$url = $this->get_current_url();
$url = add_query_arg( 'um_adm_action', $action, $url );
$url = add_query_arg( 'sub', $subaction, $url );
$url = add_query_arg( 'user_id', um_user('ID'), $url );
$url = add_query_arg( 'um_adm_action', $action, $url );
$url = add_query_arg( 'sub', $subaction, $url );
$url = add_query_arg( 'user_id', um_user( 'ID' ), $url );
return $url;
}
/**
* SEO canonical href bugfix
*
* @deprecated since version 2.1.7
*
* @todo remove since 2.7.0
* @see function um_profile_remove_wpseo()
*/
public function um_rel_canonical_() {
_deprecated_function( __METHOD__, '2.1.7', 'um_profile_remove_wpseo()' );
global $wp_the_query;
if ( ! is_singular() )
return;
/**
* UM hook
*
* @type filter
* @title um_allow_canonical__filter
* @description Allow canonical
* @input_vars
* [{"var":"$allow_canonical","type":"bool","desc":"Allow?"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_allow_canonical__filter', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_allow_canonical__filter', 'my_allow_canonical', 10, 1 );
* function my_allow_canonical( $allow_canonical ) {
* // your code here
* return $allow_canonical;
* }
* ?>
*/
$enable_canonical = apply_filters( "um_allow_canonical__filter", true );
if( ! $enable_canonical )
return;
if ( !$id = $wp_the_query->get_queried_object_id() )
return;
if ( UM()->config()->permalinks['user'] == $id ) {
$link = esc_url( $this->get_current_url() );
echo "<link rel='canonical' href='$link' />\n";
return;
}
$link = get_permalink( $id );
if ( $page = get_query_var( 'cpage' ) ) {
$link = get_comments_pagenum_link( $page );
echo "<link rel='canonical' href='$link' />\n";
}
}
}
}
+25 -20
View File
@@ -91,40 +91,47 @@ if ( ! class_exists( 'um\core\Roles_Capabilities' ) ) {
}
}
/**
* Loop through dynamic roles and add them to the $wp_roles array
*
* @param null|object $wp_roles
* @return null
*/
function um_roles_init( $wp_roles = null ) {
public function um_roles_init( $wp_roles = null ) {
$role_keys = get_option( 'um_roles', array() );
$um_roles = array_map( array( &$this, 'key_to_role_id_mapping' ), $role_keys );
//Add UM role data to WP Roles
foreach ( $wp_roles->roles as $roleID => $role_data ) {
$role_meta = get_option( "um_role_{$roleID}_meta" );
// Add UM role data to WP Roles.
foreach ( $wp_roles->roles as $role_id => $role_data ) {
// Skip custom UM roles meta here, because it's added below. See: "Add custom UM roles".
if ( in_array( $role_id, $um_roles, true ) ) {
continue;
}
$role_meta = get_option( "um_role_{$role_id}_meta" );
if ( ! empty( $role_meta ) ) {
$wp_roles->roles[ $roleID ] = array_merge( $role_data, $role_meta );
$wp_roles->roles[ $role_id ] = array_merge( $role_data, $role_meta );
}
}
//Add custom UM roles
// Add custom UM roles.
$roles = array();
$role_keys = get_option( 'um_roles', array() );
foreach ( $role_keys as $role_key ) {
$role_meta = get_option( "um_role_{$role_key}_meta" );
if ( $role_meta ) {
if ( ! empty( $role_meta ) ) {
$roles[ 'um_' . $role_key ] = $role_meta;
}
}
if ( empty( $roles ) ) {
return $wp_roles;
}
foreach ( $roles as $role_id => $details ) {
$capabilities = ! empty( $details['wp_capabilities'] ) ? array_keys( $details['wp_capabilities'] ) : array();
$capabilities = ! empty( $details['wp_capabilities'] ) ? array_keys( $details['wp_capabilities'] ) : array();
$details['capabilities'] = array_fill_keys( array_values( $capabilities ), true );
unset( $details['wp_capabilities'] );
$wp_roles->roles[ $role_id ] = $details;
$wp_roles->role_objects[ $role_id ] = new \WP_Role( $role_id, $details['capabilities'] );
$wp_roles->role_names[ $role_id ] = $details['name'];
@@ -134,6 +141,9 @@ if ( ! class_exists( 'um\core\Roles_Capabilities' ) ) {
return $wp_roles;
}
public function key_to_role_id_mapping( $role_key ) {
return 'um_' . $role_key;
}
/**
* Check if role is custom
@@ -141,22 +151,17 @@ if ( ! class_exists( 'um\core\Roles_Capabilities' ) ) {
* @param $role
* @return bool
*/
function is_role_custom( $role ) {
public function is_role_custom( $role ) {
// User has roles so look for a UM Role one
$role_keys = get_option( 'um_roles', array() );
if ( empty( $role_keys ) ) {
return false;
}
$role_keys = array_map( function( $item ) {
return 'um_' . $item;
}, $role_keys );
return in_array( $role, $role_keys );
$um_roles = array_map( array( &$this, 'key_to_role_id_mapping' ), $role_keys );
return in_array( $role, $um_roles, true );
}
/**
* Return a user's main role
*
+2 -10
View File
@@ -1260,7 +1260,7 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
*
* @return string
*/
public function ultimatemember_searchform( $args = array(), $content = "" ) {
public function ultimatemember_searchform( $args = array(), $content = '' ) {
if ( ! UM()->options()->get( 'members_page' ) ) {
return '';
}
@@ -1269,15 +1269,7 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
$page_id = UM()->config()->permalinks['members'];
if ( ! empty( $page_id ) ) {
$members_page = get_post( $page_id );
if ( ! empty( $members_page ) && ! is_wp_error( $members_page ) ) {
if ( ! empty( $members_page->post_content ) ) {
preg_match_all( '/\[ultimatemember[^\]]*?form_id\=[\'"]*?(\d+)[\'"]*?/i', $members_page->post_content, $matches );
if ( ! empty( $matches[1] ) && is_array( $matches[1] ) ) {
$member_directory_ids = array_map( 'absint', $matches[1] );
}
}
}
$member_directory_ids = UM()->member_directory()->get_member_directory_id( $page_id );
}
if ( empty( $member_directory_ids ) ) {
+6
View File
@@ -715,6 +715,12 @@ function um_submit_form_errors_hook_( $args ) {
}
break;
case 'spotify_url':
if ( ! UM()->validation()->is_url( $args[ $key ], 'open.spotify.com' ) ) {
UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s URL', 'ultimate-member' ), $array['label'] ) );
}
break;
case 'telegram_url':
if ( ! UM()->validation()->is_url( $args[ $key ], 't.me' ) ) {
UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) );
+24 -4
View File
@@ -1725,6 +1725,26 @@ function um_profile_menu( $args ) {
*/
$nav_link = apply_filters( "um_profile_menu_link_{$id}", $nav_link );
/**
* Filters a profile menu navigation links' tag attributes.
*
* @since 2.6.3
* @hook um_profile_menu_link_{$id}_attrs
*
* @param {string} $profile_nav_attrs Link's tag attributes.
* @param {array} $args Profile form arguments.
*
* @return {string} Link's tag attributes.
*
* @example <caption>Add a link's tag attributes.</caption>
* function um_profile_menu_link_attrs( $profile_nav_attrs ) {
* // your code here
* return $profile_nav_attrs;
* }
* add_filter( 'um_profile_menu_link_{$id}_attrs', 'um_profile_menu_link_attrs', 10, 1 );
*/
$profile_nav_attrs = apply_filters( "um_profile_menu_link_{$id}_attrs", '', $args );
$profile_nav_class = '';
if ( ! UM()->options()->get( 'profile_menu_icons' ) ) {
$profile_nav_class .= ' without-icon';
@@ -1737,7 +1757,7 @@ function um_profile_menu( $args ) {
<div class="um-profile-nav-item um-profile-nav-<?php echo esc_attr( $id . ' ' . $profile_nav_class ); ?>">
<?php if ( UM()->options()->get( 'profile_menu_icons' ) ) { ?>
<a href="<?php echo esc_url( $nav_link ); ?>" class="uimob800-show uimob500-show uimob340-show um-tip-n"
title="<?php echo esc_attr( $tab['name'] ); ?>" original-title="<?php echo esc_attr( $tab['name'] ); ?>">
title="<?php echo esc_attr( $tab['name'] ); ?>" original-title="<?php echo esc_attr( $tab['name'] ); ?>" <?php echo esc_attr( $profile_nav_attrs ); ?>>
<i class="<?php echo esc_attr( $tab['icon'] ); ?>"></i>
@@ -1748,7 +1768,7 @@ function um_profile_menu( $args ) {
<span class="uimob800-hide uimob500-hide uimob340-hide title"><?php echo esc_html( $tab['name'] ); ?></span>
</a>
<a href="<?php echo esc_url( $nav_link ); ?>" class="uimob800-hide uimob500-hide uimob340-hide"
title="<?php echo esc_attr( $tab['name'] ); ?>">
title="<?php echo esc_attr( $tab['name'] ); ?>" <?php echo esc_attr( $profile_nav_attrs ); ?>>
<i class="<?php echo esc_attr( $tab['icon'] ); ?>"></i>
@@ -1760,7 +1780,7 @@ function um_profile_menu( $args ) {
</a>
<?php } else { ?>
<a href="<?php echo esc_url( $nav_link ); ?>" class="uimob800-show uimob500-show uimob340-show um-tip-n"
title="<?php echo esc_attr( $tab['name'] ); ?>" original-title="<?php echo esc_attr( $tab['name'] ); ?>">
title="<?php echo esc_attr( $tab['name'] ); ?>" original-title="<?php echo esc_attr( $tab['name'] ); ?>" <?php echo esc_attr( $profile_nav_attrs ); ?>>
<i class="<?php echo esc_attr( $tab['icon'] ); ?>"></i>
@@ -1769,7 +1789,7 @@ function um_profile_menu( $args ) {
<?php } ?>
</a>
<a href="<?php echo esc_url( $nav_link ); ?>" class="uimob800-hide uimob500-hide uimob340-hide"
title="<?php echo esc_attr( $tab['name'] ); ?>">
title="<?php echo esc_attr( $tab['name'] ); ?>" <?php echo esc_attr( $profile_nav_attrs ); ?>>
<?php if ( isset( $tab['notifier'] ) && $tab['notifier'] > 0 ) { ?>
<span class="um-tab-notifier"><?php echo $tab['notifier']; ?></span>
+24
View File
@@ -77,6 +77,30 @@ function um_profile_field_filter_hook__youtube_video( $value, $data ) {
add_filter( 'um_profile_field_filter_hook__youtube_video', 'um_profile_field_filter_hook__youtube_video', 99, 2 );
/**
* Outputs a spotify iframe
*
* @param $value
* @param $data
*
* @return bool|string
*/
function um_profile_field_filter_hook__spotify( $value, $data ) {
if ( preg_match( '/https:\/\/open.spotify.com\/.*/', $value ) ) {
$url = str_replace( 'open.spotify.com/', 'open.spotify.com/embed/', $value );
$value = '<div class="um-spotify">
<iframe width="100%" height="352" style="border-radius:12px" frameBorder="0" allowfullscreen="" loading="lazy" src="' . esc_url( $url ) . '"></iframe>
</div>';
} else {
return __( 'Invalid Spotify URL', 'ultimate-member' );
}
return $value;
}
add_filter( 'um_profile_field_filter_hook__spotify', 'um_profile_field_filter_hook__spotify', 99, 2 );
/**
* Outputs a vimeo video
*
+3 -4
View File
@@ -1515,10 +1515,10 @@ function um_can_view_field( $data ) {
UM()->fields()->set_mode = '';
}
if ( isset( $data['public'] ) && UM()->fields()->set_mode != 'register' ) {
if ( isset( $data['public'] ) && 'register' !== UM()->fields()->set_mode ) {
$can_edit = false;
$current_user_roles = [];
$can_edit = false;
$current_user_roles = array();
if ( is_user_logged_in() ) {
$can_edit = UM()->roles()->um_current_user_can( 'edit', um_user( 'ID' ) );
@@ -1563,7 +1563,6 @@ function um_can_view_field( $data ) {
$can_view = apply_filters( 'um_can_view_field_custom', $can_view, $data );
break;
}
}
return apply_filters( 'um_can_view_field', $can_view, $data );
+12 -5
View File
@@ -1,7 +1,11 @@
{
"name": "roots",
"version": "7.0.3",
"author": "Ben Word <ben@benword.com>",
"name": "ultimate-member",
"version": "2.6.3",
"author": {
"name": "Ultimate Member",
"email": "team@ultimatemember.com",
"url": "https://ultimatemember.com"
},
"homepage": "http://roots.io",
"repository": {
"type": "git",
@@ -17,7 +21,7 @@
}
],
"scripts": {
"postinstall": "node node_modules/bower/bin/bower install && grunt dev",
"build:docs": "rm -rf docs/hooks/ && jsdoc -c hookdoc-conf.json",
"build": "npm-run-all build:*",
"build:all-blocks": "npm-run-all --parallel build-block-*",
"build-block-um-member-directories": "cd includes/blocks/um-member-directories && wp-scripts build src/index.js",
@@ -36,6 +40,8 @@
"gulp-sass": "^5.1.0",
"gulp-uglify": "^3.0.2",
"gulp-clean-css": "^4.3.0",
"jsdoc": "~4.0.2",
"wp-hookdoc": "^0.2.0",
"npm-run-all": "^4.1.5",
"@wordpress/block-editor": "^11.5.0",
"@wordpress/blocks": "^12.5.0",
@@ -45,6 +51,7 @@
"@wordpress/server-side-render": "^4.5.0"
},
"dependencies": {
"react": "^18.2.0"
"react": "^18.2.0",
"taffydb": "^2.7.3"
}
}
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor
configVersion="3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://www.phpdoc.org"
xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd">
<title>Ultimate Member - PHPDoc</title>
<paths>
<output>docs/phpdoc</output>
<cache>docs/phpdoc/cache</cache>
</paths>
<version number="1.0.0">
<folder>latest</folder>
<api>
<source dsn=".">
<path>includes</path>
<path>templates</path>
</source>
<extensions>
<extension>php</extension>
</extensions>
</api>
</version>
<template name="clean"/>
</phpdocumentor>
+33 -3
View File
@@ -7,7 +7,7 @@ Tags: community, member, membership, user-profile, user-registration
Requires PHP: 5.6
Requires at least: 5.5
Tested up to: 6.2
Stable tag: 2.6.2
Stable tag: 2.6.3
License: GNU Version 2 or Any Later Version
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
@@ -96,9 +96,9 @@ If you're a developer and would like to contribute to the source code of the plu
Want to add a new language to Ultimate Member? Great! You can contribute via [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/ultimate-member).
If you are a developer and you need to know the list of UM Hooks, make this via our [Hooks Documentation](https://docs.ultimatemember.com/article/1324-hooks-list).
If you are a developer and you need to know the list of UM Hooks, make this via our [Hooks Documentation](https://docs.ultimatemember.com/article/1324-hooks-list) or [Hooks Documentation v2](https://ultimatemember.github.io/ultimatemember/hooks/).
If you are a developer and you need to know the structure of our code, make this via our [Documentation API](https://ultimatemember.com/php-docs/).
If you are a developer and you need to know the structure of our code, make this via our [Documentation API](https://ultimatemember.github.io/ultimatemember/phpdoc/).
= Documentation & Support =
@@ -163,6 +163,36 @@ No, you do not need to use our plugins login or registration pages and can us
* To learn more about version 2.1 please see this [docs](https://docs.ultimatemember.com/article/1512-upgrade-2-1-0)
* UM2.1+ is a significant update to the Member Directories' code base from 2.0.x. Please make sure you take a full-site backup with restore point before updating the plugin
= 2.6.3: June 14, 2023 =
* Enhancements:
- Added: `um_profile_menu_link_{$id}_attrs` hook for changing link attributes
- Added: `get_member_directory_id()` function for getting member directory ID based on page ID
- Added: The "Order" and "Data type" settings for custom sorting fields based on metakey in Member Directory
- Added: New hooks `um_profile_permalink`,`um_external_profile_url`
- Added: Users dropdown field to Admin Forms class
- Added: Spotify URL field type
- Added: New developer docs [here](http://ultimatemember.github.io/ultimatemember/). It will be upgraded from version to version
* Bugfixes:
- Fixed: PHP8.2 PHP errors (deprecated, warnings, etc.)
- Fixed: Filters visibility on member directory page based on public or private visibility for filter's field
- Fixed: Incorrect Member Directory numerical sorting order
- Fixed: wp_editor() doesn't work correctly in content restriction settings for Mac users
- Fixed: Profile links when WPML plugin is active
- Fixed: ACF and UM blocks conflict
- Fixed: `UM()->mail()->locate_template()` function's visibility
* Deprecated:
- Deprecated: `um_localize_permalink_filter`. Use `post_link` instead
* Templates required update:
- members.php
= 2.6.2: May 31, 2023 =
* Bugfixes:
+9 -1
View File
@@ -6,7 +6,7 @@
*
* Page: "Members"
*
* @version 2.6.1
* @version 2.6.3
*
* @var array $args
*/
@@ -139,6 +139,14 @@ if ( ! empty( $search_filters ) ) {
$search_filters = array_values( $search_filters );
}
// Hide filter fields based on the field visibility.
foreach ( $search_filters as $key => $filter ) {
$filter_data = UM()->fields()->get_field( $filter );
if ( ! um_can_view_field( $filter_data ) ) {
unset( $search_filters[ $key ] );
}
}
// Classes
$classes = '';
if ( $search && $show_search ) {
+1 -1
View File
@@ -3,7 +3,7 @@
Plugin Name: Ultimate Member
Plugin URI: http://ultimatemember.com/
Description: The easiest way to create powerful online communities and beautiful user profiles with WordPress
Version: 2.6.2
Version: 2.6.3
Author: Ultimate Member
Author URI: http://ultimatemember.com/
Text Domain: ultimate-member