0cadafda by Jeff Balicki

Ultimate Member update

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent 7c037e3f
Showing 128 changed files with 1364 additions and 1518 deletions
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
[{.jshintrc,*.json,*.yml,*.sass}]
indent_style = space
indent_size = 2
[{*.txt,wp-config-sample.php}]
end_of_line = crlf
\ No newline at end of file
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
---
name: "\U0001F46E‍♂️Security issue"
about: Please report security issues *only* via https://ultimatemember.com/feedback/
title: ''
labels: ''
assignees: ''
---
For security reasons, please report all security issues via https://ultimatemember.com/feedback/.
Please disclose responsibly and not via GitHub (which allows for exploiting issues in the wild before the patch is released).
\ No newline at end of file
---
name: "\U0001F41E Bug report"
about: Report a bug if something isn't working as expected in the core Ultimate Member
plugin.
title: ''
labels: ''
assignees: ''
---
**Expected behavior**
A clear and concise description of what you expected to happen.
**Isolating the problem (mark completed items with an [x]):**
- [ ] I have deactivated other plugins and confirmed this bug occurs when only Ultimate Member plugin is active.
- [ ] This bug happens with a default WordPress theme active, or [UM Theme](https://ultimatemember.com/theme/).
- [ ] I can reproduce this bug consistently using the steps above.
**Describe the bug**
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Do you use UM extensions?**
- [ ] Followers
- [ ] ForumWP
- [ ] Friends
- [ ] Google reCAPTCHA
- [ ] Groups
- [ ] Instagram
- [ ] MailChimp
- [ ] myCRED
- [ ] Notices
- [ ] Online Users
- [ ] Private Content
- [ ] Private Messages
- [ ] Profile Completeness
- [ ] Real-time Notifications
- [ ] Social Activity
- [ ] Social Login
- [ ] Terms & Conditions
- [ ] Unsplash
- [ ] User Bookmarks
- [ ] User Photos
- [ ] User Reviews
- [ ] User Tags
- [ ] Verified Users
- [ ] WooCommerce
**WordPress Environment**
<details>
```
Copy and paste the install info from ** Ultimate Member > Settings > Install Info ** in WordPress admin.
```
</details>
\ No newline at end of file
---
name: " New Enhancement"
about: If you have an idea to improve an existing feature in core or need something
for development (such as a new hook) please let us know or submit a Pull Request!
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
\ No newline at end of file
---
name: "\U0001F680 Feature request"
about: "Suggest a new feature \U0001F389 We'll consider building it if it receives
sufficient interest! \U0001F44D"
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
\ No newline at end of file
---
name: " Support Question"
about: "If you have a question \U0001F4AC please see our docs or use our forums & support page"
title: ''
labels: ''
assignees: ''
---
We don't offer technical support on GitHub so we recommend using the following:
**Reading our documentation**
Usage docs can be found here: https://docs.ultimatemember.com
If you have a problem, you may want to start with the self help guide here: https://docs.ultimatemember.com/article/1507-ultimate-member-self-service-guide/
**Technical support for premium extensions or if you're a UltimateMember.com customer**
Please submit a ticket via the support page
https://ultimatemember.com/support/ticket/
**General questions**
- WordPress.org Forums: https://wordpress.org/support/plugin/ultimate-member/
# 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/).
<!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>
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;
}
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 }}
name: Ultimate Member - Checking Code quality through PHPCS + WPCS
on:
push:
branches:
- development/3.0
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run CS
run: vendor/bin/phpcs --standard=phpcs.xml .
name: Generate POT file manually
on: workflow_dispatch
jobs:
WP_Generate_POT_File:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: WordPress .pot File Generator
uses: iamdharmesh/action-wordpress-pot-generator@main
with:
destination_path: './languages'
slug: 'ultimate-member'
text_domain: 'ultimate-member'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Generate POT file
on:
push:
branches:
- master
jobs:
WP_Generate_POT_File:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: WordPress .pot File Generator
uses: iamdharmesh/action-wordpress-pot-generator@main
with:
destination_path: './languages'
slug: 'ultimate-member'
text_domain: 'ultimate-member'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.ideanpg
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
*.publishproj
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[cod]
# Packages
*.egg
*.egg-info
dist/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
node_modules/
assets/vendor/
/vendor/
package-lock.json
.idea/
composer.lock
# exclude Composer installation
composer.phar
/vendor
# exclude WP-CLI installation
wp-cli.phar
# exclude generated by phpDocumentor docs
/documentor
#wp-hookdoc generated docs
hookdocs
{
"bitwise": true,
"browser": true,
"curly": true,
"eqeqeq": true,
"eqnull": true,
"esnext": true,
"immed": true,
"jquery": true,
"latedef": true,
"newcap": true,
"noarg": true,
"node": true,
"strict": false,
"trailing": true
}
# Travis CI Configuration File
# Tell Travis CI we're using PHP
language: php
dist: trusty
# Setup a global environment and overide as needed
env:
global:
- WP_TRAVISCI=phpunit
cache:
directories:
- $HOME/.composer/cache/files
- $HOME/.cache/yarn
# Test main supported versions of PHP against latest WP.
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
env:
- WP_VERSION=latest WP_MULTISITE=0
# Next we define our matrix of additional build configurations to test against.
# The versions listed above will automatically create our first configuration,
# so it doesn't need to be re-defined below.
# Test WP trunk/master and two latest versions on minimum (5.2).
# Test WP latest two versions (4.5, 4.3) on most popular (5.5, 5.6).
# Test WP latest stable (4.5) on other supported PHP (5.3, 5.4).
# Test WP trunk/master on edge platforms (7.0, PHP nightly).
# WP_VERSION specifies the tag to use. The way these tests are configured to run
# requires at least WordPress 3.8. Specify "master" to test against SVN trunk.
matrix:
fast_finish: true
include:
- name: "Coding standard check"
php: 7.2
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
- name: "e2e tests"
php: 7.2
env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
addons:
chrome: beta
apt:
packages:
- nginx
- name: "Unit tests code coverage"
php: 7.3
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
- name: "Ultimate Member unit tests using WordPress nightly"
php: 7.3
env: WP_VERSION=nightly WP_MULTISITE=0
- php: 7.4snapshot
env: WP_VERSION=nightly WP_MULTISITE=0
allow_failures:
- php: 7.3
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
- php: 7.4snapshot
env: WP_VERSION=nightly WP_MULTISITE=0
# whitelist branches for the "push" build check.
branches:
only:
- master
#- master-stable
#- /^branch-.*$/
#- feature/*
# Clones WordPress and configures our testing environment.
before_script:
- phpenv config-rm xdebug.ini
- export PLUGIN_SLUG=$(basename $(pwd))
- source ~/.nvm/nvm.sh
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- |
if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
composer global require "phpunit/phpunit=5.7.*"
elif [[ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]]; then
composer global require "phpunit/phpunit=4.8.*"
fi
- nvm install 6
- nvm use 6
- chmod +x ./tests/prepare-wordpress.sh
- chmod +x ./tests/run-travis.sh
- ./tests/prepare-wordpress.sh
## - mysql -e "set global wait_timeout = 3600;"
script:
- ./tests/run-travis.sh
sudo: false
# We need notifications for successful builds
notifications:
webhooks: https://ultimatemember.com/travis.php
email:
- heychampsupertramp@gmail.com
- nsinelnikov.work@gmail.com
# Encrypted Slack notification address.
#- secure: "WQdTdmYuifSW0hiJGXpQGKystMASC50QvxHlyUL5SM3h5GP8aCgeSsHuXvKPe3dT3Pffhk0dSHBfDtdWFwSHW/upURhg0vs4dm7+nxxvGZiTPzKcuAIjgvCoqWM7teyda/XqFGNSnv+XsT34uoyPhhFgd45T3oS+QQ3aNCruFak="
<p align="center"><a href="https://ultimatemember.com/"><img src="https://ultimatemember.com/wp-content/uploads/2022/05/icon-128×128.png" alt="Ultimate Member" ></a><br/>
<h1 align="center">Ultimate Member</h1>
</p>
[![Active Installs](https://img.shields.io/wordpress/plugin/installs/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/installs/ultimate-member?color=7856ff)
[![Ratings](https://img.shields.io/wordpress/plugin/rating/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/rating/ultimate-member?color=7856ff)
[![Latest Version](https://img.shields.io/wordpress/plugin/v/ultimate-member?label=Latest&color=7856ff)](https://img.shields.io/wordpress/plugin/v/ultimate-member?label=Latest)
[![WP Tested](https://img.shields.io/wordpress/plugin/tested/ultimate-member?label=wp&color=7856ff)](https://img.shields.io/wordpress/plugin/tested/ultimate-member?label=wp)
[![WP Version Required](https://img.shields.io/wordpress/plugin/wp-version/ultimate-member?label=wp&color=7856ff)](https://img.shields.io/wordpress/plugin/wp-version/ultimate-member?label=wp)
[![Downloads](https://img.shields.io/wordpress/plugin/dt/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/dt/ultimate-member?color=7856ff)
[![Build Status](https://img.shields.io/travis/ultimatemember/ultimatemember/master?color=7856ff)](https://travis-ci.org/ultimatemember/ultimatemember)
Ultimate Member is the #1 user profile & membership plugin for WordPress. The plugin makes it a breeze for users to sign-up and become members of your website. The plugin allows you to add beautiful user profiles to your site and is perfect for creating advanced online communities and membership sites. Lightweight and highly extendible, Ultimate Member will enable you to create almost any type of site where users can join and become members with absolute ease.
If you are not a developer, please use the [Ultimate Member plugin page](https://wordpress.org/plugins/ultimate-member/) on WordPress.org.
## Documentation
- [Ultimate Member Features](https://ultimatemember.com/features/)
- [Ultimate Member Documentation](https://docs.ultimatemember.com)
- [Ultimate Member Developer Documentation](https://docs.ultimatemember.com/collection/28-for-developers)
- [Ultimate Member Extensions Roadmap](https://ultimatemember.com/roadmap/)
- [Ultimate Member Extended Features](https://github.com/ultimatemember/Extended)
## Reporting Security Issues
To disclose a security issue to our team, [please submit a report here](https://ultimatemember.com/feedback/).
## Support
This repository is not suitable for support. Please don't use our issue tracker for support requests, but for Ultimate Member core plugin issues only. Support can take place through the appropriate channels:
- If you have a problem, you may want to start with the [support page](https://ultimatemember.com/support/).
- The [Ultimate Member premium extensions' support portal](https://ultimatemember.com/support/ticket/) for customers who have purchased themes or extensions.
- [Our community forum on wp.org](https://wordpress.org/support/plugin/ultimate-member/) which is available for all Ultimate Member users.
Support requests in issues on this repository will be closed on sight.
## License
GNU Version 2 or Any Later Version
## Releases
### IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
[Official Release Version: 2.8.2](https://github.com/ultimatemember/ultimatemember/releases/tag/2.8.2).
## Changelog
[ From v1.0.0 to latest version ](https://wordpress.org/plugins/ultimate-member/changelog/).
.um-form-table .um-forms-line[data-conditional] {
display: none; }
.um-form-table .um-forms-line[data-field_type="checkbox"] td label {
font-style: italic; }
.um-form-table .um-forms-line label .um-req {
color: #a00;
margin: 0 0 0 3px;
......@@ -68,9 +65,12 @@
display: block;
margin: 0 0 5px 0; }
.um-form-table .description {
font-style: italic;
clear: both; }
.um-external-link-icon {
width: 1em;
height: 1em;
margin: 0;
vertical-align: middle;
fill: currentcolor; }
.um_admin_fonticon_wrapper {
display: flex;
......
......@@ -7,10 +7,6 @@
.#{$prefix}forms-line
&[data-conditional]
display: none
&[data-field_type="checkbox"]
td
label
font-style: italic
label
.#{$prefix}req
color: $required-asterisk
......@@ -88,6 +84,7 @@
label
margin: 0 0 5px 0
display: inline-block
//font-weight: bold
&[data-field_type="icon"]
td
......@@ -95,9 +92,16 @@
width: 100%
display: block
margin: 0 0 5px 0
.description
font-style: italic
clear: both
//.description
// font-style: italic
// clear: both
.um-external-link-icon
width: 1em
height: 1em
margin: 0
vertical-align: middle
fill: currentcolor
.um_admin_fonticon_wrapper
+flex( row, flex-start, center, nowrap )
......
......@@ -32,3 +32,8 @@
float: left;
display: block;
line-height: 37px; }
#um-admin-form-publish #major-publishing-actions {
padding-top: 0;
padding-left: 0;
padding-right: 0; }
......
#um-roles .row-actions .reset a{color:#a00}#um-roles .row-actions .reset a:hover{color:red}.wp-list-table.roles .column-core,.wp-list-table.roles .column-users{width:15%;text-align:center!important}.wp-list-table.roles .column-admin_access,.wp-list-table.roles .column-priority{width:10%;text-align:center!important}@media screen and (max-width:782px){.wp-list-table.roles .column-admin_access,.wp-list-table.roles .column-core,.wp-list-table.roles .column-priority,.wp-list-table.roles .column-users{text-align:left!important}}#um-admin-form-wp-capabilities .um-metadata-line th{width:auto}#um-admin-form-wp-capabilities .um-metadata-line td{width:20px}#um_edit_role #titlewrap>span{width:40px;font-size:24px;float:left;display:block;line-height:37px}
\ No newline at end of file
#um-roles .row-actions .reset a{color:#a00}#um-roles .row-actions .reset a:hover{color:red}.wp-list-table.roles .column-core,.wp-list-table.roles .column-users{width:15%;text-align:center!important}.wp-list-table.roles .column-admin_access,.wp-list-table.roles .column-priority{width:10%;text-align:center!important}@media screen and (max-width:782px){.wp-list-table.roles .column-admin_access,.wp-list-table.roles .column-core,.wp-list-table.roles .column-priority,.wp-list-table.roles .column-users{text-align:left!important}}#um-admin-form-wp-capabilities .um-metadata-line th{width:auto}#um-admin-form-wp-capabilities .um-metadata-line td{width:20px}#um_edit_role #titlewrap>span{width:40px;font-size:24px;float:left;display:block;line-height:37px}#um-admin-form-publish #major-publishing-actions{padding-top:0;padding-left:0;padding-right:0}
\ No newline at end of file
......
......@@ -42,3 +42,10 @@
float: left
display: block
line-height: 37px
#um-admin-form-publish
#major-publishing-actions
padding-top: 0
padding-left: 0
padding-right: 0
......
#um-settings-wrap .subsubsub {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-left: -3px;
margin-right: -3px; }
#um-settings-wrap .subsubsub a {
margin: 0 3px; }
.um-settings-section .description {
font-style: italic; }
......@@ -37,8 +26,8 @@
width: 25%; }
.column-configure {
width: 60px;
text-align: center; }
width: 10%;
text-align: right; }
th.column-email.column-primary {
padding-left: 48px; }
......@@ -46,16 +35,19 @@ th.column-email.column-primary {
.um-form-table .um-forms-line td {
padding-right: 0; }
#um-settings-template-versions .wp-list-table .column-core_version {
width: 100px;
text-align: center; }
#um-settings-template-versions .wp-list-table .column-theme_version {
width: 100px;
text-align: center; }
#um-settings-emails {
margin: 15px 0; }
#um-settings-template-versions .wp-list-table .column-status {
width: 260px; }
#um-settings-template-versions {
margin: 15px 0; }
#um-settings-template-versions .wp-list-table .column-core_version {
width: 100px;
text-align: center; }
#um-settings-template-versions .wp-list-table .column-theme_version {
width: 100px;
text-align: center; }
#um-settings-template-versions .wp-list-table .column-status {
width: 260px; }
#um-settings-form {
float: left;
......@@ -64,6 +56,12 @@ th.column-email.column-primary {
#um-settings-form .subsubsub {
float: left;
width: 100%; }
#um-settings-form h2.title a.um-back-button {
font-weight: normal;
font-size: 30px;
line-height: 1;
text-decoration: none;
margin-right: 5px; }
.um-settings-line .multi-checkbox-line {
float: left;
......
#um-settings-wrap .subsubsub{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-wrap:wrap;margin-left:-3px;margin-right:-3px}#um-settings-wrap .subsubsub a{margin:0 3px}.um-settings-section .description{font-style:italic}.um-notification-status{margin-right:18px;font-size:28px;line-height:22px;color:#c74a4a;float:left;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.um-notification-status.um-notification-is-active{color:#7acf58}.um-email-configure span{line-height:24px}.um-long-field{width:100%}.um-medium-field{width:50%}.um-small-field{width:25%}.column-configure{width:60px;text-align:center}th.column-email.column-primary{padding-left:48px}.um-form-table .um-forms-line td{padding-right:0}#um-settings-template-versions .wp-list-table .column-core_version{width:100px;text-align:center}#um-settings-template-versions .wp-list-table .column-theme_version{width:100px;text-align:center}#um-settings-template-versions .wp-list-table .column-status{width:260px}#um-settings-form{float:left;width:100%;margin:0}#um-settings-form .subsubsub{float:left;width:100%}.um-settings-line .multi-checkbox-line{float:left;width:100%;clear:both;margin:0 0 10px 0;padding:0}.um-settings-line .multi-checkbox-column{float:left;margin:0;padding:0}.um-settings-line .multi-checkbox-column label{float:left;width:100%}.wrap-licenses .form-table,.wrap-licenses caption,.wrap-licenses tbody,.wrap-licenses td,.wrap-licenses tfoot,.wrap-licenses th,.wrap-licenses thead,.wrap-licenses tr{display:block}.wrap-licenses .form-table tr{float:left;margin:0 15px 15px 0;background:#fff;border:1px solid #ccc;width:30.5%;max-width:350px;padding:14px;min-height:240px;position:relative;box-sizing:border-box}.wrap-licenses .form-table th{background:#f9f9f9;padding:14px;border-bottom:1px solid #ccc;margin:-14px -14px 20px;width:100%}.wrap-licenses .form-table td{padding:0}.wrap-licenses td input.regular-text{margin:0 0 8px;width:100%}.wrap-licenses .edd-license-data[class*=edd-license-]{position:absolute;background:#fafafa;padding:14px;border-top:1px solid #eee;margin:20px -14px -14px;min-height:67px;width:100%;bottom:14px;box-sizing:border-box}.wrap-licenses .edd-license-data[class*=edd-license-] a{color:#444}.wrap-licenses .edd-license-data[class*=edd-license-] a:hover{text-decoration:none}.wrap-licenses .edd-license-data.license-expires-soon-notice{background-color:#00a0d2;color:#fff;border-color:#00a0d2}.wrap-licenses .edd-license-data.license-expires-soon-notice a{color:#fff}.wrap-licenses .edd-license-data.license-expires-soon-notice a:hover{text-decoration:none}.wrap-licenses .edd-license-data.edd-license-expired{background-color:#e24e4e;color:#fff;border-color:#e24e4e}.wrap-licenses .edd-license-data.edd-license-expired a{color:#fff}.wrap-licenses .edd-license-data.edd-license-expired a:hover{text-decoration:none}.wrap-licenses .edd-license-data.edd-license-valid{background-color:#5abc55;color:#fff;border-color:#5abc55}.wrap-licenses .edd-license-data.edd-license-error,.wrap-licenses .edd-license-data.edd-license-invalid,.wrap-licenses .edd-license-data.edd-license-item_name_mismatch,.wrap-licenses .edd-license-data.edd-license-missing,.wrap-licenses .edd-license-data.edd-license-site_inactive{background-color:#ffebcd;border-color:#ffebcd}.wrap-licenses .edd-license-data p{font-size:13px;margin-top:0}.wrap-licenses~p.submit{clear:both}@media screen and (max-width:980px){.wrap-licenses .form-table tr{width:calc(50% - 15px);max-width:none}}@media screen and (max-width:782px){#um-settings-template-versions .wp-list-table .column-core_version,#um-settings-template-versions .wp-list-table .column-theme_version{width:auto;text-align:left}.wrap-licenses .form-table tr{width:100%;margin-right:0;max-width:none}.um-settings-line .multi-checkbox-column{width:100%!important}.um-settings-line .multi-checkbox-column label{line-height:30px!important}.um-medium-field{width:100%}.um-small-field{width:50%}}.um_setting_ajax_button_response.complete{color:#7acf58;font-style:italic}.wp-core-ui .button.um_license_activate,.wp-core-ui .button.um_license_deactivate,.wp-core-ui .button.um_license_reactivate{margin-top:5px}.um-media-upload .um-media-upload-url{margin-bottom:5px}
\ No newline at end of file
.um-settings-section .description{font-style:italic}.um-notification-status{margin-right:18px;font-size:28px;line-height:22px;color:#c74a4a;float:left;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.um-notification-status.um-notification-is-active{color:#7acf58}.um-email-configure span{line-height:24px}.um-long-field{width:100%}.um-medium-field{width:50%}.um-small-field{width:25%}.column-configure{width:10%;text-align:right}th.column-email.column-primary{padding-left:48px}.um-form-table .um-forms-line td{padding-right:0}#um-settings-emails{margin:15px 0}#um-settings-template-versions{margin:15px 0}#um-settings-template-versions .wp-list-table .column-core_version{width:100px;text-align:center}#um-settings-template-versions .wp-list-table .column-theme_version{width:100px;text-align:center}#um-settings-template-versions .wp-list-table .column-status{width:260px}#um-settings-form{float:left;width:100%;margin:0}#um-settings-form .subsubsub{float:left;width:100%}#um-settings-form h2.title a.um-back-button{font-weight:400;font-size:30px;line-height:1;text-decoration:none;margin-right:5px}.um-settings-line .multi-checkbox-line{float:left;width:100%;clear:both;margin:0 0 10px 0;padding:0}.um-settings-line .multi-checkbox-column{float:left;margin:0;padding:0}.um-settings-line .multi-checkbox-column label{float:left;width:100%}.wrap-licenses .form-table,.wrap-licenses caption,.wrap-licenses tbody,.wrap-licenses td,.wrap-licenses tfoot,.wrap-licenses th,.wrap-licenses thead,.wrap-licenses tr{display:block}.wrap-licenses .form-table tr{float:left;margin:0 15px 15px 0;background:#fff;border:1px solid #ccc;width:30.5%;max-width:350px;padding:14px;min-height:240px;position:relative;box-sizing:border-box}.wrap-licenses .form-table th{background:#f9f9f9;padding:14px;border-bottom:1px solid #ccc;margin:-14px -14px 20px;width:100%}.wrap-licenses .form-table td{padding:0}.wrap-licenses td input.regular-text{margin:0 0 8px;width:100%}.wrap-licenses .edd-license-data[class*=edd-license-]{position:absolute;background:#fafafa;padding:14px;border-top:1px solid #eee;margin:20px -14px -14px;min-height:67px;width:100%;bottom:14px;box-sizing:border-box}.wrap-licenses .edd-license-data[class*=edd-license-] a{color:#444}.wrap-licenses .edd-license-data[class*=edd-license-] a:hover{text-decoration:none}.wrap-licenses .edd-license-data.license-expires-soon-notice{background-color:#00a0d2;color:#fff;border-color:#00a0d2}.wrap-licenses .edd-license-data.license-expires-soon-notice a{color:#fff}.wrap-licenses .edd-license-data.license-expires-soon-notice a:hover{text-decoration:none}.wrap-licenses .edd-license-data.edd-license-expired{background-color:#e24e4e;color:#fff;border-color:#e24e4e}.wrap-licenses .edd-license-data.edd-license-expired a{color:#fff}.wrap-licenses .edd-license-data.edd-license-expired a:hover{text-decoration:none}.wrap-licenses .edd-license-data.edd-license-valid{background-color:#5abc55;color:#fff;border-color:#5abc55}.wrap-licenses .edd-license-data.edd-license-error,.wrap-licenses .edd-license-data.edd-license-invalid,.wrap-licenses .edd-license-data.edd-license-item_name_mismatch,.wrap-licenses .edd-license-data.edd-license-missing,.wrap-licenses .edd-license-data.edd-license-site_inactive{background-color:#ffebcd;border-color:#ffebcd}.wrap-licenses .edd-license-data p{font-size:13px;margin-top:0}.wrap-licenses~p.submit{clear:both}@media screen and (max-width:980px){.wrap-licenses .form-table tr{width:calc(50% - 15px);max-width:none}}@media screen and (max-width:782px){#um-settings-template-versions .wp-list-table .column-core_version,#um-settings-template-versions .wp-list-table .column-theme_version{width:auto;text-align:left}.wrap-licenses .form-table tr{width:100%;margin-right:0;max-width:none}.um-settings-line .multi-checkbox-column{width:100%!important}.um-settings-line .multi-checkbox-column label{line-height:30px!important}.um-medium-field{width:100%}.um-small-field{width:50%}}.um_setting_ajax_button_response.complete{color:#7acf58;font-style:italic}.wp-core-ui .button.um_license_activate,.wp-core-ui .button.um_license_deactivate,.wp-core-ui .button.um_license_reactivate{margin-top:5px}.um-media-upload .um-media-upload-url{margin-bottom:5px}
\ No newline at end of file
......
......@@ -2,13 +2,13 @@
@import "mixins"
@import "colors"
##{$prefix}settings-wrap
.subsubsub
+flex( row, flex-start, center, wrap )
margin-left: -3px
margin-right: -3px
a
margin: 0 3px
//##{$prefix}settings-wrap
// .subsubsub
// +flex( row, flex-start, center, wrap )
// margin-left: -3px
// margin-right: -3px
// a
// margin: 0 3px
.#{$prefix}settings-section
.description
......@@ -38,8 +38,8 @@
width: 25%
.column-configure
width: 60px
text-align: center
width: 10%
text-align: right
th.column-email.column-primary
padding-left: 48px
......@@ -50,7 +50,11 @@ th.column-email.column-primary
td
padding-right: 0
##{$prefix}settings-emails
margin: 15px 0
##{$prefix}settings-template-versions
margin: 15px 0
.wp-list-table
.column-core_version
width: 100px
......@@ -68,6 +72,13 @@ th.column-email.column-primary
.subsubsub
float: left
width: 100%
h2.title
a.um-back-button
font-weight: normal
font-size: 30px
line-height: 1
text-decoration: none
margin-right: 5px
.#{$prefix}settings-line
......
......@@ -62,6 +62,15 @@
color: #555;
}
div.uimob340 .um-account-main div.um-account-heading.uimob340-hide,
div.uimob500 .um-account-main div.um-account-heading.uimob500-hide {
display:none;
}
.um-account-side .um-account-link {
box-sizing: content-box;
}
.um-account-main div.um-account-heading i {
margin-right: 10px;
font-size: 26px;
......@@ -193,8 +202,9 @@
border-right: 1px solid #ccc;
color: #444;
float: left;
padding: 0px 15px;
padding: 0 15px;
font-weight: normal !important;
box-sizing: content-box;
}
.um-account-side li a span.um-account-icon i {
......@@ -244,4 +254,4 @@
background-color: #44b0ec;
color: #fff;
text-decoration: none;
}
\ No newline at end of file
}
......
.um-account i{vertical-align:baseline!important}.um-account p.um-notice{margin:0 0 20px 0!important;padding:12px 15px!important}.um-account a:focus{outline:0!important}.um-account-side{float:left;width:30%;padding:0;box-sizing:border-box}.um-account-main{float:left;width:70%;padding:0 0 0 1.5em;box-sizing:border-box}.um-account-main a{border-bottom:none!important}.um-account-tab{display:none}.um-account-tab .um-field .um-field-label{display:flex;flex-direction:row;align-items:baseline;flex-wrap:nowrap;justify-content:flex-start}.um-account-main div.um-account-heading{display:flex;flex-wrap:nowrap;flex-direction:row;justify-content:flex-start;align-items:baseline;margin:0!important;font-size:18px;line-height:18px;font-weight:700;color:#555}.um-account-main div.um-account-heading i{margin-right:10px;font-size:26px;position:relative;top:2px}.um-account-main p{margin:20px 0 0 0!important;padding:0!important}.um-account-main label{font-size:15px}.um-account-meta{text-align:center;margin-bottom:20px}.um-account-meta img{margin:0!important;position:static!important;float:none!important;display:inline-block}.um-account-meta.radius-1 img{-moz-border-radius:999px;-webkit-border-radius:999px;border-radius:999px}.um-account-meta.radius-2 img{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.um-account-meta.radius-3 img{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.um-account-name{padding-top:12px}.um-account-name a{font-weight:700;color:#555;text-decoration:none!important;font-size:18px;line-height:1.4em}.um-account-profile-link a{font-size:13px;font-weight:400}.um-account-nav a{display:block;height:44px;line-height:44px;color:#666!important;text-decoration:none!important;position:relative;padding-left:40px;border-bottom:1px solid #eee!important;transition:all .2s linear;font-size:14px}.um-account-nav a.current{font-weight:700}.um-account-nav span.arr{position:absolute;right:0;top:1px;font-size:28px}.um-account-nav span.ico{position:absolute;left:0;top:0;font-size:21px;width:21px;text-align:center}.um-account-side li,.um-account-side ul{margin:0!important;padding:0!important;list-style-type:none!important}.um-account-side li{margin-bottom:1px!important;background:#eee}.um-account-side li a{display:block;padding:4px 0;font-size:14px;height:30px;line-height:20px;color:#999;position:relative}.um-account-side li a span.um-account-arrow{position:absolute;right:10px;top:6px;font-size:26px;opacity:.6}.um-account-side li a span.um-account-icon,.um-account-side li a.current span.um-account-icon,.um-account-side li a.current:hover span.um-account-icon{text-align:center;font-size:20px;width:20px;height:30px;border-right:1px solid #ccc;color:#444;float:left;padding:0 15px;font-weight:400!important}.um-account-side li a span.um-account-icon i{display:block;height:30px;line-height:30px}.um-account-side li a span.um-account-title{padding-left:20px;float:left;height:30px;line-height:30px;color:#555}.um-account-side li a:hover{color:#444;background:#ddd}.um-account-side li a.current,.um-account-side li a.current:hover{color:#444;font-weight:700;text-decoration:none!important}.um-field-export_data .um-field-error{display:none}.um-field-export_data .um-field-area-response{display:none;line-height:1.5;padding:10px 0}.um-request-button{display:inline-block;background-color:#3ba1da;border-radius:5px;color:#fff;margin:10px 0 0;padding:5px 10px;text-decoration:none}.um-request-button:hover{background-color:#44b0ec;color:#fff;text-decoration:none}
\ No newline at end of file
.um-account i{vertical-align:baseline!important}.um-account p.um-notice{margin:0 0 20px 0!important;padding:12px 15px!important}.um-account a:focus{outline:0!important}.um-account-side{float:left;width:30%;padding:0;box-sizing:border-box}.um-account-main{float:left;width:70%;padding:0 0 0 1.5em;box-sizing:border-box}.um-account-main a{border-bottom:none!important}.um-account-tab{display:none}.um-account-tab .um-field .um-field-label{display:flex;flex-direction:row;align-items:baseline;flex-wrap:nowrap;justify-content:flex-start}.um-account-main div.um-account-heading{display:flex;flex-wrap:nowrap;flex-direction:row;justify-content:flex-start;align-items:baseline;margin:0!important;font-size:18px;line-height:18px;font-weight:700;color:#555}div.uimob340 .um-account-main div.um-account-heading.uimob340-hide,div.uimob500 .um-account-main div.um-account-heading.uimob500-hide{display:none}.um-account-side .um-account-link{box-sizing:content-box}.um-account-main div.um-account-heading i{margin-right:10px;font-size:26px;position:relative;top:2px}.um-account-main p{margin:20px 0 0 0!important;padding:0!important}.um-account-main label{font-size:15px}.um-account-meta{text-align:center;margin-bottom:20px}.um-account-meta img{margin:0!important;position:static!important;float:none!important;display:inline-block}.um-account-meta.radius-1 img{-moz-border-radius:999px;-webkit-border-radius:999px;border-radius:999px}.um-account-meta.radius-2 img{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.um-account-meta.radius-3 img{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.um-account-name{padding-top:12px}.um-account-name a{font-weight:700;color:#555;text-decoration:none!important;font-size:18px;line-height:1.4em}.um-account-profile-link a{font-size:13px;font-weight:400}.um-account-nav a{display:block;height:44px;line-height:44px;color:#666!important;text-decoration:none!important;position:relative;padding-left:40px;border-bottom:1px solid #eee!important;transition:all .2s linear;font-size:14px}.um-account-nav a.current{font-weight:700}.um-account-nav span.arr{position:absolute;right:0;top:1px;font-size:28px}.um-account-nav span.ico{position:absolute;left:0;top:0;font-size:21px;width:21px;text-align:center}.um-account-side li,.um-account-side ul{margin:0!important;padding:0!important;list-style-type:none!important}.um-account-side li{margin-bottom:1px!important;background:#eee}.um-account-side li a{display:block;padding:4px 0;font-size:14px;height:30px;line-height:20px;color:#999;position:relative}.um-account-side li a span.um-account-arrow{position:absolute;right:10px;top:6px;font-size:26px;opacity:.6}.um-account-side li a span.um-account-icon,.um-account-side li a.current span.um-account-icon,.um-account-side li a.current:hover span.um-account-icon{text-align:center;font-size:20px;width:20px;height:30px;border-right:1px solid #ccc;color:#444;float:left;padding:0 15px;font-weight:400!important;box-sizing:content-box}.um-account-side li a span.um-account-icon i{display:block;height:30px;line-height:30px}.um-account-side li a span.um-account-title{padding-left:20px;float:left;height:30px;line-height:30px;color:#555}.um-account-side li a:hover{color:#444;background:#ddd}.um-account-side li a.current,.um-account-side li a.current:hover{color:#444;font-weight:700;text-decoration:none!important}.um-field-export_data .um-field-error{display:none}.um-field-export_data .um-field-area-response{display:none;line-height:1.5;padding:10px 0}.um-request-button{display:inline-block;background-color:#3ba1da;border-radius:5px;color:#fff;margin:10px 0 0;padding:5px 10px;text-decoration:none}.um-request-button:hover{background-color:#44b0ec;color:#fff;text-decoration:none}
\ No newline at end of file
......
......@@ -898,12 +898,32 @@ small.um-max-filesize span{
.um-search-area .um-search-field {
width: 100%;
margin: 0;
padding-left: 25px;
}
.rtl .um-search-area .um-search-field {
padding-right: 25px;
padding-left: initial;
}
.um-search-area .um-search-icon {
position: absolute;
top: 7px;
right: 10px;
height: 100%;
left: 6px;
top: 0;
}
.rtl .um-search-area .um-search-icon {
right: 6px;
left: initial;
}
.um-faicon-search:before {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
/*
......
......@@ -97,6 +97,52 @@ function um_admin_init_users_select() {
}
function um_admin_init_pages_select() {
// multiple select with AJAX search
jQuery('.um-pages-select2').select2({
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
action: 'um_get_pages_list', // AJAX action for admin-ajax.php
page: params.page || 1, // infinite scroll pagination
nonce: um_admin_scripts.nonce
};
},
processResults: function( data, params ) {
params.page = params.page || 1;
var options = [];
if ( data ) {
// data is the array of arrays, and each of them contains ID and the Label of the option
jQuery.each( data, function( index, text ) { // do not forget that "index" is just auto incremented value
if ( index === 'total_count' ) {
return;
}
options.push( { id: text[0], text: text[1] } );
});
}
return {
results: options,
pagination: {
more: ( params.page * 10 ) < data.total_count
}
};
},
cache: true
},
placeholder: jQuery(this).data('placeholder'),
minimumInputLength: 0, // the minimum of symbols to input before perform a search
allowClear: true,
});
}
/**
*
* @param field_key
......@@ -123,6 +169,7 @@ function um_same_page_something_wrong( field_key ) {
jQuery(document).ready( function() {
um_admin_init_users_select();
um_admin_init_pages_select();
/**
* Same page upgrade field
......@@ -130,9 +177,9 @@ jQuery(document).ready( function() {
jQuery( document.body ).on( 'click', '.um-forms-field[data-log-object]', function() {
var obj = jQuery( this ).data( 'log-object' );
if ( jQuery( this ).is( ':checked' ) ) {
jQuery( this ).siblings( '.um-same-page-update-' + obj ).show();
jQuery( this ).parents('label').siblings( '.um-same-page-update-' + obj ).show();
} else {
jQuery( this ).siblings( '.um-same-page-update-' + obj ).hide();
jQuery( this ).parents('label').siblings( '.um-same-page-update-' + obj ).hide();
}
});
......
......@@ -593,7 +593,11 @@ function um_modal_responsive() {
if ( w <= 500 ) {
modal.animate({ 'bottom' : 0 }, 300);
} else {
modal.animate({ 'bottom' : half_gap }, 300);
if ( h - parseInt(half_gap) > h ) {
modal.animate({ 'bottom' : 0 }, 300);
} else {
modal.animate({ 'bottom' : half_gap }, 300);
}
}
}
}
......
{
"name": "roots",
"version": "7.0.3",
"homepage": "http://roots.io",
"authors": [
"Ben Word <ben@benword.com>"
],
"license": "MIT",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"assets"
],
"dependencies": {
/* "modernizr": "2.8.2",
"jquery": "1.11.1",
"bootstrap": "3.3.1",
"respond": "1.4.2",
"fitvids": "~1.1.0",
"devbridge-autocomplete": "~1.2.16",
"raty": "~2.7.0",
"featherlight": "~1.0.4",
"sharrre": "~1.3.5",
"fullcalendar": "~2.3.0",
"jquery.countdown": "~2.0.4",
"mustache": "~2.1.3",
"formvalidation": "https://github.com/formvalidation/formvalidation.git"*/
}
}
{
"name": "ultimatemember/ultimatemember",
"description": "The easiest way to create powerful online communities and beautiful user profiles with WordPress.",
"type": "wordpress-plugin",
"homepage": "https://wordpress.org/plugins/ultimate-member/",
"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": "*",
"ext-dom": "*",
"ext-exif": "*",
"ext-gd": "*",
"ext-fileinfo": "*",
"ext-curl": "*",
"ext-iconv": "*",
"woocommerce/action-scheduler": "3.2.1"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"wp-cli/wp-cli": "*",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
"object-calisthenics/phpcs-calisthenics-rules": "*",
"phpcompatibility/phpcompatibility-wp": "*",
"wp-coding-standards/wpcs": "2.3.0",
"squizlabs/php_codesniffer": "3.*",
"phpdocumentor/phpdocumentor": "3.1.*"
},
"extra": {
"installer-paths": {
"vendor/{$vendor}/{$name}/": ["woocommerce/action-scheduler"]
}
}
}
# 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/).
/*
Ultimate Member dependencies
*/
var gulp = require('gulp')
, uglify = require('gulp-uglify'),
sass = require('gulp-sass'),
rename = require('gulp-rename'),
cleanCSS = require( 'gulp-clean-css' );
// task
gulp.task( 'default', function ( done ) {
sass.compiler = require( 'node-sass' );
gulp.src(['assets/sass/*.sass']).pipe( sass().on( 'error', sass.logError ) ).pipe( gulp.dest( 'assets/css' ) );
gulp.src(['assets/js/*.js','!assets/js/*.min.js']) // path to your files
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/js/' ) );
gulp.src(['assets/js/admin/*.js','!assets/js/admin/*.min.js']) // path to your files
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/js/admin/' ) );
gulp.src(['assets/css/admin/*.css', '!assets/css/admin/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/css/admin/' ) );
gulp.src(['assets/css/*.css', '!assets/css/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/css/' ) );
// full CSS files
gulp.src(['assets/css/admin/*.sass'])
.pipe( sass().on( 'error', sass.logError ) )
.pipe( gulp.dest( 'assets/css/admin/' ) );
// min CSS files
gulp.src(['assets/css/admin/*.sass'])
.pipe( sass().on( 'error', sass.logError ) )
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/css/admin/' ) );
// full CSS files
gulp.src(['assets/css/*.sass'])
.pipe( sass().on( 'error', sass.logError ) )
.pipe( gulp.dest( 'assets/css/' ) );
// min CSS files
gulp.src(['assets/css/*.sass'])
.pipe( sass().on( 'error', sass.logError ) )
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/css/' ) );
gulp.src(['assets/libs/legacy/fonticons/*.css', '!assets/libs/legacy/fonticons/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/libs/legacy/fonticons/' ) );
// Raty lib
gulp.src(['assets/libs/raty/*.css', '!assets/libs/raty/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/libs/raty/' ) );
gulp.src(['assets/libs/raty/*.js', '!assets/libs/raty/*.min.js',])
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/libs/raty/' ) );
// Tipsy lib
gulp.src(['assets/libs/tipsy/*.css', '!assets/libs/tipsy/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/libs/tipsy/' ) );
gulp.src(['assets/libs/tipsy/*.js', '!assets/libs/tipsy/*.min.js',])
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/libs/tipsy/' ) );
// Pickadate lib
gulp.src(['assets/libs/pickadate/*.css', '!assets/libs/pickadate/*.min.css',])
.pipe( cleanCSS() )
.pipe( rename( { suffix: '.min' } ) )
.pipe( gulp.dest( 'assets/libs/pickadate/' ) );
gulp.src(['assets/libs/pickadate/*.js', '!assets/libs/pickadate/*.min.js',])
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/libs/pickadate/' ) );
gulp.src(['assets/libs/pickadate/translations/*.js', '!assets/libs/pickadate/translations/*.min.js',])
.pipe( uglify() )
.pipe( rename({ suffix: '.min' }) )
.pipe( gulp.dest( 'assets/libs/pickadate/translations/' ) );
done();
});
{
"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"
]
}
}
}
}
<?php
namespace um\admin;
use WP_Query;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
......@@ -69,6 +71,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
add_action( 'um_admin_do_action__check_templates_version', array( &$this, 'check_templates_version' ) );
add_action( 'um_admin_do_action__install_core_pages', array( &$this, 'install_core_pages' ) );
add_action( 'um_admin_do_action__install_predefined_page', array( &$this, 'install_predefined_page' ) );
add_action( 'parent_file', array( &$this, 'parent_file' ), 9 );
add_filter( 'gettext', array( &$this, 'gettext' ), 10, 4 );
......@@ -1617,31 +1620,106 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
public function install_core_pages() {
UM()->setup()->install_default_pages();
//check empty pages in settings
// Auto dismiss 'wrong_pages' notice if it's visible
$this->dismiss_wrong_pages();
$url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
wp_safe_redirect( $url );
exit;
}
/**
* Install predefined page based on $_REQUEST['um_page_slug'] argument.
*/
public function install_predefined_page() {
if ( ! current_user_can( 'manage_options' ) ) {
$url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
wp_safe_redirect( $url );
exit;
}
$predefined_pages = array_keys( UM()->config()->get( 'predefined_pages' ) );
// phpcs:ignore WordPress.Security.NonceVerification -- early nonce verification based on `um_adm_action`
$page_slug = array_key_exists( 'um_page_slug', $_REQUEST ) ? sanitize_key( $_REQUEST['um_page_slug'] ) : '';
if ( empty( $page_slug ) || ! in_array( $page_slug, $predefined_pages, true ) ) {
$url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
wp_safe_redirect( $url );
exit;
}
$post_ids = new WP_Query(
array(
'post_type' => 'page',
'meta_query' => array(
array(
'key' => '_um_core',
'value' => $page_slug,
),
),
'posts_per_page' => -1,
'fields' => 'ids',
)
);
$post_ids = $post_ids->get_posts();
if ( ! empty( $post_ids ) ) {
foreach ( $post_ids as $post_id ) {
delete_post_meta( $post_id, '_um_core' );
}
}
UM()->setup()->predefined_page( $page_slug );
// Auto dismiss 'wrong_pages' notice if it's visible
$this->dismiss_wrong_pages();
$url = add_query_arg(
array(
'page' => 'um_options',
'update' => 'um_settings_updated',
),
admin_url( 'admin.php' )
);
wp_safe_redirect( $url );
exit;
}
/**
* Dismiss 'wrong_pages' notice if it's visible.
*/
public function dismiss_wrong_pages() {
// Check empty pages in settings.
$empty_pages = array();
$pages = UM()->config()->permalinks;
if ( $pages && is_array( $pages ) ) {
foreach ( $pages as $slug => $page_id ) {
$page = get_post( $page_id );
$predefined_pages = array_keys( UM()->config()->get( 'predefined_pages' ) );
foreach ( $predefined_pages as $slug ) {
$page_id = um_get_predefined_page_id( $slug );
if ( ! $page_id ) {
$empty_pages[] = $slug;
continue;
}
if ( ! isset( $page->ID ) && array_key_exists( $slug, UM()->config()->core_pages ) ) {
$empty_pages[] = $slug;
}
$page = get_post( $page_id );
if ( ! $page ) {
$empty_pages[] = $slug;
continue;
}
}
//if there aren't empty pages - then hide pages notice
// If there aren't empty pages - then hide pages notice
if ( empty( $empty_pages ) ) {
$hidden_notices = get_option( 'um_hidden_admin_notices', array() );
$hidden_notices = get_option( 'um_hidden_admin_notices', array() );
if ( ! is_array( $hidden_notices ) ) {
$hidden_notices = array();
}
$hidden_notices[] = 'wrong_pages';
update_option( 'um_hidden_admin_notices', $hidden_notices );
}
$url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
wp_safe_redirect( $url );
exit;
}
/**
......@@ -1826,24 +1904,13 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
* Manual check templates versions.
*/
public function check_templates_version() {
$templates = UM()->admin_settings()->get_override_templates( true );
$out_date = false;
foreach ( $templates as $template ) {
if ( 0 === $template['status_code'] ) {
$out_date = true;
break;
}
}
if ( false === $out_date ) {
delete_option( 'um_override_templates_outdated' );
}
UM()->common()->theme()->flush_transient_templates_data();
$url = add_query_arg(
array(
'page' => 'um_options',
'tab' => 'override_templates',
'page' => 'um_options',
'tab' => 'advanced',
'section' => 'override_templates',
),
admin_url( 'admin.php' )
);
......
......@@ -351,9 +351,10 @@ final class Enqueue extends \um\common\Enqueue {
$forms_data = array(
'successfully_redirect' => add_query_arg(
array(
'page' => 'um_options',
'tab' => 'misc',
'msg' => 'updated',
'page' => 'um_options',
'tab' => 'advanced',
'section' => 'features',
'msg' => 'updated',
),
admin_url( 'admin.php' )
),
......@@ -554,7 +555,7 @@ final class Enqueue extends \um\common\Enqueue {
wp_enqueue_style( 'um_admin_common' );
if ( self::$um_cpt_form_screen ) {
if ( defined( 'UM_LEGACY_BUILDER_OFF' ) && UM_LEGACY_BUILDER_OFF ) {
if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE && UM()->options()->get( 'enable_new_form_builder' ) ) {
// Do new assets.
} else {
$this->load_builder();
......@@ -583,10 +584,16 @@ final class Enqueue extends \um\common\Enqueue {
wp_enqueue_style( 'um_admin_roles' );
} elseif ( 'ultimate-member_page_um_options' === $hook ) {
// phpcs:ignore WordPress.Security.NonceVerification
if ( isset( $_GET['tab'] ) && 'secure' === $_GET['tab'] ) {
wp_register_script( 'um_admin_secure', $js_url . 'admin/secure' . $suffix . '.js', array( 'jquery', 'wp-i18n' ), UM_VERSION, true );
wp_set_script_translations( 'um_admin_secure', 'ultimate-member' );
wp_enqueue_script( 'um_admin_secure' );
if ( isset( $_GET['tab'], $_GET['section'] ) && 'advanced' === $_GET['tab'] && 'security' === $_GET['section'] ) {
wp_register_script( 'um_admin_security', $js_url . 'admin/security' . $suffix . '.js', array( 'jquery', 'wp-i18n' ), UM_VERSION, true );
wp_set_script_translations( 'um_admin_security', 'ultimate-member' );
wp_enqueue_script( 'um_admin_security' );
}
// phpcs:ignore WordPress.Security.NonceVerification
if ( isset( $_GET['tab'] ) && 'appearance' === $_GET['tab'] && empty( $_GET['section'] ) ) {
// Init WP Media Uploader on the UM > Settings > Appearance > Profile screen.
wp_enqueue_media();
}
wp_register_style( 'um_admin_settings', $css_url . 'admin/settings' . $suffix . '.css', array(), UM_VERSION );
......
......@@ -90,12 +90,6 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
*/
public function admin_init() {
global $wpdb;
// Dismiss admin notice after the first visit to Secure settings page.
if ( isset( $_REQUEST['page'] ) && isset( $_REQUEST['tab'] ) &&
'um_options' === sanitize_key( $_REQUEST['page'] ) && 'secure' === sanitize_key( $_REQUEST['tab'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
UM()->admin()->notices()->dismiss( 'secure_settings' );
}
if ( isset( $_REQUEST['um_secure_expire_all_sessions'] ) && ! wp_doing_ajax() ) {
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-secure-expire-session-nonce' ) || ! current_user_can( 'manage_options' ) ) {
// This nonce is not valid or current logged-in user has no administrative rights.
......@@ -236,16 +230,18 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
'description' => __( 'Scan your site to check for vulnerabilities prior to Ultimate Member version 2.6.7 and get recommendations to secure your site.', 'ultimate-member' ),
),
array(
'id' => 'lock_register_forms',
'type' => 'checkbox',
'label' => __( 'Lock All Register Forms', 'ultimate-member' ),
'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ),
'id' => 'lock_register_forms',
'type' => 'checkbox',
'label' => __( 'Lock All Register Forms', 'ultimate-member' ),
'checkbox_label' => __( 'Lock Forms', 'ultimate-member' ),
'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ),
),
array(
'id' => 'display_login_form_notice',
'type' => 'checkbox',
'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ),
'description' => __( 'Enforces users to reset their passwords( one-time ) and prevent from entering old password.', 'ultimate-member' ),
'id' => 'display_login_form_notice',
'type' => 'checkbox',
'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ),
'checkbox_label' => __( 'Enable Login form notice', 'ultimate-member' ),
'description' => __( 'Enforces users to reset their passwords (one-time) and prevent from entering old password.', 'ultimate-member' ),
),
);
......@@ -265,17 +261,19 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
$secure_fields,
array(
array(
'id' => 'secure_ban_admins_accounts',
'type' => 'checkbox',
'label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ),
'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ),
'id' => 'secure_ban_admins_accounts',
'type' => 'checkbox',
'label' => __( 'Administrative capabilities ban', 'ultimate-member' ),
'checkbox_label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ),
'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ),
),
array(
'id' => 'secure_notify_admins_banned_accounts',
'type' => 'checkbox',
'label' => __( 'Notify Administrators', 'ultimate-member' ),
'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ),
'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ),
'id' => 'secure_notify_admins_banned_accounts',
'type' => 'checkbox',
'label' => __( 'Notify Administrators', 'ultimate-member' ),
'checkbox_label' => __( 'Enable notification', 'ultimate-member' ),
'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ),
'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ),
),
array(
'id' => 'secure_notify_admins_banned_accounts__interval',
......@@ -292,14 +290,21 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
'id' => 'secure_allowed_redirect_hosts',
'type' => 'textarea',
'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ),
'description' => __( 'Extend allowed hosts for frontend pages redirects', 'ultimate-member' ),
'description' => __( 'Extend allowed hosts for frontend pages redirects.', 'ultimate-member' ),
),
)
);
$settings['secure'] = array(
'title' => __( 'Secure', 'ultimate-member' ),
'fields' => $secure_fields,
$settings['advanced']['sections'] = UM()->array_insert_before(
$settings['advanced']['sections'],
'developers',
array(
'security' => array(
'title' => __( 'Security', 'ultimate-member' ),
'description' => __( 'This feature scans for suspicious registered accounts, bans the usage of administrative capabilities to site subscribers/members, allows the website administrators to force all users to reset their passwords, preventing users from logging-in using their old passwords that may have been exposed.', 'ultimate-member' ),
'fields' => $secure_fields,
),
)
);
return $settings;
......
......@@ -13,10 +13,68 @@ if ( ! defined( 'ABSPATH' ) ) {
class Site_Health {
/**
* String of a badge color.
* Options: blue, green, red, orange, purple and gray.
*
* @see https://make.wordpress.org/core/2019/04/25/site-health-check-in-5-2/
*
* @since 2.8.3
*/
const BADGE_COLOR = 'blue';
/**
* Site_Health constructor.
*/
public function __construct() {
add_filter( 'debug_information', array( $this, 'debug_information' ), 20 );
add_filter( 'site_status_tests', array( $this, 'register_site_status_tests' ) );
}
public function register_site_status_tests( $tests ) {
$custom_templates = UM()->common()->theme()->get_custom_templates_list();
if ( ! empty( $custom_templates ) ) {
$tests['direct']['um_override_templates'] = array(
'label' => esc_html__( 'Are the Ultimate Member templates out of date?', 'ultimate-member' ),
'test' => array( $this, 'override_templates_test' ),
);
}
return $tests;
}
public function override_templates_test() {
$result = array(
'label' => __( 'You have the most recent version of custom Ultimate Member templates', 'ultimate-member' ),
'status' => 'good',
'badge' => array(
'label' => UM_PLUGIN_NAME,
'color' => self::BADGE_COLOR,
),
'description' => sprintf(
'<p>%s</p>',
__( 'Your custom Ultimate Member templates that are situated in the theme have the most recent version and are ready to use.', 'ultimate-member' )
),
'actions' => '',
'test' => 'um_override_templates',
);
if ( UM()->common()->theme()->is_outdated_template_exist() ) {
$result['label'] = __( 'Your custom templates are out of date', 'ultimate-member' );
$result['status'] = 'critical';
$result['badge']['color'] = 'red';
$result['description'] = sprintf(
'<p>%s</p>',
__( 'Your custom Ultimate Member templates that are situated in the theme are out of date and may break the website\'s functionality.', 'ultimate-member' )
);
$result['actions'] = sprintf(
'<p><a href="%s">%s</a></p>',
admin_url( 'admin.php?page=um_options&tab=advanced&section=override_templates' ),
esc_html__( 'Check status and update', 'ultimate-member' )
);
}
return $result;
}
private function get_roles() {
......@@ -290,7 +348,7 @@ class Site_Health {
}
$account_settings['um-account_email'] = array(
'label' => __( 'Allow users to change e-mail', 'ultimate-member' ),
'label' => __( 'Allow users to change email', 'ultimate-member' ),
'value' => UM()->options()->get( 'account_email' ) ? $labels['yes'] : $labels['no'],
);
......@@ -485,7 +543,7 @@ class Site_Health {
// Email settings
$email_settings = array(
'um-admin_email' => array(
'label' => __( 'Admin E-mail Address', 'ultimate-member' ),
'label' => __( 'Admin Email Address', 'ultimate-member' ),
'value' => UM()->options()->get( 'admin_email' ),
),
'um-mail_from' => array(
......@@ -497,7 +555,7 @@ class Site_Health {
'value' => UM()->options()->get( 'mail_from_addr' ),
),
'um-email_html' => array(
'label' => __( 'Use HTML for E-mails?', 'ultimate-member' ),
'label' => __( 'Use HTML for Emails?', 'ultimate-member' ),
'value' => UM()->options()->get( 'email_html' ) ? $labels['yes'] : $labels['no'],
),
);
......@@ -1362,7 +1420,7 @@ class Site_Health {
$info[ 'ultimate-member-' . $key ]['fields'],
array(
'um-url_email_activate' => array(
'label' => __( 'URL redirect after e-mail activation', 'ultimate-member' ),
'label' => __( 'URL redirect after email activation', 'ultimate-member' ),
'value' => $rolemeta['_um_url_email_activate'],
),
)
......@@ -1788,7 +1846,7 @@ class Site_Health {
'first_name' => __( 'First Name', 'ultimate-member' ),
'last_name' => __( 'Last Name', 'ultimate-member' ),
'nickname' => __( 'Nickname', 'ultimate-member' ),
'secondary_user_email' => __( 'Secondary E-mail Address', 'ultimate-member' ),
'secondary_user_email' => __( 'Secondary Email Address', 'ultimate-member' ),
'description' => __( 'Biography', 'ultimate-member' ),
'phone_number' => __( 'Phone Number', 'ultimate-member' ),
'mobile_number' => __( 'Mobile Number', 'ultimate-member' ),
......
<?php
namespace um\admin\core;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) {
/**
* Class Admin_Forms_Settings
* @package um\admin\core
......@@ -17,41 +17,42 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) {
* Admin_Forms constructor.
* @param bool $form_data
*/
function __construct( $form_data = false ) {
public function __construct( $form_data = false ) {
parent::__construct( $form_data );
}
/**
* Get field value
* Get field value.
*
* @param array $field_data
* @param array $field_data
* @param string $i
*
* @return string|array
*/
function get_field_value( $field_data, $i = '' ) {
$default = isset( $field_data['default' . $i] ) ? $field_data['default' . $i] : UM()->options()->get_default( $field_data['id' . $i] );
if ( $field_data['type'] == 'checkbox' || $field_data['type'] == 'multi_checkbox' ) {
if ( isset( $field_data['value' . $i] ) ) {
return $field_data['value' . $i];
} else {
$value = UM()->options()->get( $field_data['id' . $i] );
$value = is_string( $value ) ? stripslashes( $value ) : $value;
return '' !== $value ? $value : $default;
}
} else {
if ( isset( $field_data['value' . $i] ) ) {
return $field_data['value'. $i];
} else {
$value = UM()->options()->get( $field_data['id' . $i] );
$value = is_string( $value ) ? stripslashes( $value ) : $value;
return isset( $value ) ? $value : $default;
public function get_field_value( $field_data, $i = '' ) {
$default_key = 'default' . $i;
$value_key = 'value' . $i;
$id_key = 'id' . $i;
$default = isset( $field_data[ $default_key ] ) ? $field_data[ $default_key ] : UM()->options()->get_default( $field_data[ $id_key ] );
if ( in_array( $field_data['type'], array( 'checkbox', 'multi_checkbox' ), true ) ) {
if ( isset( $field_data[ $value_key ] ) ) {
return $field_data[ $value_key ];
}
$value = UM()->options()->get( $field_data[ $id_key ] );
$value = is_string( $value ) ? stripslashes( $value ) : $value;
return '' !== $value ? $value : $default;
}
}
if ( isset( $field_data[ $value_key ] ) ) {
return $field_data[ $value_key ];
}
$value = UM()->options()->get( $field_data[ $id_key ] );
$value = is_string( $value ) ? stripslashes( $value ) : $value;
return isset( $value ) ? $value : $default;
}
}
}
......
......@@ -52,7 +52,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
* @param bool $echo
* @return string
*/
function render_form( $echo = true ) {
public function render_form( $echo = true ) {
if ( empty( $this->form_data['fields'] ) ) {
return '';
......@@ -64,7 +64,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
ob_start();
foreach ( $this->form_data['fields'] as $field_data ) {
if ( isset( $field_data['type'] ) && 'hidden' == $field_data['type'] ) {
if ( isset( $field_data['type'] ) && 'hidden' === $field_data['type'] ) {
echo $this->render_form_row( $field_data );
}
}
......@@ -97,19 +97,18 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
}
/**
* @param array $data
*
* @return string
*/
function render_form_row( $data ) {
public function render_form_row( $data ) {
if ( empty( $data['type'] ) ) {
return '';
}
if ( !empty( $data['value'] ) && $data['type'] != 'email_template' ) {
if ( ! empty( $data['value'] ) && $data['type'] != 'email_template' ) {
$data['value'] = wp_unslash( $data['value'] );
/*for multi_text*/
......@@ -169,8 +168,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<p class="description">' . $data['description'] . '</p>';
}
$html .= '</div>';
......@@ -190,8 +190,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<p class="description">' . $data['description'] . '</p>';
}
$html .= '</div>';
......@@ -209,8 +210,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<p class="description">' . $data['description'] . '</p>';
}
$html .= '</div>';
......@@ -233,8 +235,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
}
$html .= '</td></tr>';
......@@ -255,8 +258,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
}
$html .= '</td></tr>';
......@@ -276,15 +280,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
}
if ( ! empty( $data['description'] ) )
if ( ! empty( $data['description'] ) ) {
$html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
}
$html .= '</td></tr>';
}
}
}
} else {
$html .= $this->render_hidden( $data );
}
......@@ -927,10 +930,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
*
* @return bool|string
*/
function render_checkbox( $field_data ) {
public function render_checkbox( $field_data ) {
if ( empty( $field_data['id'] ) )
if ( empty( $field_data['id'] ) ) {
return false;
}
$id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id'];
$id_attr = ' id="' . esc_attr( $id ) . '" ';
......@@ -941,7 +945,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" ';
$data = array(
'field_id' => $field_data['id']
'field_id' => $field_data['id'],
);
if ( ! empty( $field_data['data'] ) ) {
......@@ -959,20 +963,22 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$value = $this->get_field_value( $field_data );
$html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" />
<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" />";
$checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : '';
return $html;
$field_html = "<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />";
if ( '' !== $checkbox_label ) {
$field_html = "<label>$field_html $checkbox_label</label>";
}
$html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}";
return apply_filters( 'um_admin_render_checkbox_field_html', $html, $field_data );
}
/**
* @param $field_data
*
* @return bool|string
*/
function render_same_page_update( $field_data ) {
public function render_same_page_update( $field_data ) {
if ( empty( $field_data['id'] ) ) {
return false;
......@@ -987,7 +993,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" ';
$data = array(
'field_id' => $field_data['id']
'field_id' => $field_data['id'],
);
if ( ! empty( $field_data['data'] ) ) {
......@@ -1009,8 +1015,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
$value = $this->get_field_value( $field_data );
$html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" />
<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" />";
$checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : '';
$field_html = "<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />";
if ( '' !== $checkbox_label ) {
$field_html = "<label>$field_html $checkbox_label</label>";
}
$html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}";
if ( ! empty( $field_data['upgrade_cb'] ) ) {
$html .= '<div class="um-same-page-update-wrapper um-same-page-update-' . esc_attr( $field_data['upgrade_cb'] ) . '"><div class="um-same-page-update-description">' . $field_data['upgrade_description'] . '</div><input type="button" data-upgrade_cb="' . $field_data['upgrade_cb'] . '" class="button button-primary um-admin-form-same-page-update" value="' . esc_attr__( 'Run', 'ultimate-member' ) . '"/>
......@@ -1020,7 +1031,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
return $html;
}
/**
* @param $field_data
*
......@@ -1083,6 +1093,79 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
return $html;
}
/**
* @param $field_data
*
* @since 2.8.3
*
* @return bool|string
*/
public function render_page_select( $field_data ) {
if ( empty( $field_data['id'] ) ) {
return false;
}
$multiple = ! empty( $field_data['multi'] ) ? 'multiple' : '';
$id = ( ! empty( $this->form_data['prefix_id'] ) ? sanitize_title( $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_attr = ' class="um-forms-field um-pages-select2 ' . esc_attr( $class ) . '" ';
$data = array(
'field_id' => $field_data['id'],
);
if ( ! empty( $field_data['placeholder'] ) ) {
$data['placeholder'] = $field_data['placeholder'];
}
$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;
$hidden_name_attr = ' name="' . $name . '" ';
$name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' );
$name_attr = ' name="' . $name . '" ';
$value = $this->get_field_value( $field_data );
$options = '<option value="">' . esc_html( $data['placeholder'] ) . '</option>';
if ( ! empty( $field_data['options'] ) ) {
foreach ( $field_data['options'] as $key => $option ) {
if ( ! empty( $field_data['multi'] ) ) {
if ( ! is_array( $value ) || empty( $value ) ) {
$value = array();
}
$options .= '<option value="' . $key . '" ' . selected( in_array( $key, $value ), true, false ) . '>' . esc_html( $option ) . '</option>';
} else {
$options .= '<option value="' . $key . '" ' . selected( (string)$key == $value, true, false ) . '>' . esc_html( $option ) . '</option>';
}
}
}
$hidden = '';
if ( ! empty( $multiple ) ) {
$hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />";
}
$button = '';
$slug = str_replace( 'core_', '', $field_data['id'] );
if ( ! um_get_predefined_page_id( $slug ) || 'publish' !== get_post_status( um_get_predefined_page_id( $slug ) ) ) {
$button = '&nbsp;<a href="' . esc_url( add_query_arg( array( 'um_adm_action' => 'install_predefined_page', 'um_page_slug' => $slug, '_wpnonce' => wp_create_nonce( 'install_predefined_page' ), ) ) ) . '" class="button button-primary">' . esc_html__( 'Create Default', 'ultimate-member' ) . '</a>';
}
$html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr>$options</select>$button";
return $html;
}
/**
* @param $field_data
......@@ -1739,7 +1822,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
return $html;
}
/**
* Get field value
*
......@@ -1770,5 +1852,24 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
return $value;
}
public function render_external_link( $data ) {
$defaults = array(
'url' => '',
'html' => '',
);
$data = wp_parse_args( $data, $defaults );
if ( empty( $data['url'] ) || empty( $data['html'] ) ) {
return '';
}
ob_start();
?>
<a target="_blank" href="<?php echo esc_url( $data['url'] ); ?>">
<?php echo esc_html( $data['html'] ); ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="um-external-link-icon" aria-hidden="true" focusable="false"><path d="M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"></path></svg>
</a>
<?php
return ob_get_clean();
}
}
}
......
......@@ -16,18 +16,16 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
*/
class Admin_Menu {
/**
* @var string
*/
var $pagehook;
var $slug = 'ultimatemember';
/**
* Admin_Menu constructor.
*/
function __construct() {
public function __construct() {
add_action( 'admin_menu', array( &$this, 'primary_admin_menu' ), 0 );
add_action( 'admin_menu', array( &$this, 'secondary_menu_items' ), 1000 );
add_action( 'admin_menu', array( &$this, 'extension_menu' ), 9999 );
......@@ -35,8 +33,46 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
add_action( 'admin_head', array( $this, 'menu_order_count' ) );
add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1000 );
add_action( 'load-ultimate-member_page_um_options', array( &$this, 'maybe_settings_redirect' ) );
}
/**
* Trigger redirect on the Settings screen if there is a wrong tab or section.
*
* @since 2.8.2
*/
public function maybe_settings_redirect() {
$current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] );
$current_subtab = empty( $_GET['section'] ) ? '' : sanitize_key( $_GET['section'] );
$settings_struct = UM()->admin_settings()->settings_structure[ $current_tab ];
// Remove not option hidden fields.
if ( ! empty( $settings_struct['fields'] ) ) {
foreach ( $settings_struct['fields'] as $field_key => $field_options ) {
if ( isset( $field_options['is_option'] ) && false === $field_options['is_option'] ) {
unset( $settings_struct['fields'][ $field_key ] );
}
}
}
if ( empty( $settings_struct['fields'] ) && empty( $settings_struct['sections'] ) && empty( $settings_struct['form_sections'] ) ) {
wp_safe_redirect( add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) ) );
exit;
}
if ( ! empty( $settings_struct['sections'] ) ) {
if ( empty( $settings_struct['sections'][ $current_subtab ] ) ) {
$args = array( 'page' => 'um_options' );
if ( ! empty( $current_tab ) ) {
$args['tab'] = $current_tab;
}
wp_safe_redirect( add_query_arg( $args, admin_url( 'admin.php' ) ) );
exit;
}
}
}
/**
* Change the admin footer text on UM admin pages
......@@ -143,8 +179,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
/**
* Setup admin menu
*/
function primary_admin_menu() {
$this->pagehook = add_menu_page( __( 'Ultimate Member', 'ultimate-member' ), __( 'Ultimate Member', 'ultimate-member' ), 'manage_options', $this->slug, array( &$this, 'admin_page' ), 'dashicons-admin-users', '42.78578');
public function primary_admin_menu() {
$this->pagehook = add_menu_page( __( 'Ultimate Member', 'ultimate-member' ), __( 'Ultimate Member', 'ultimate-member' ), 'manage_options', $this->slug, array( &$this, 'admin_page' ), 'dashicons-admin-users', '42.78578' );
add_action( 'load-' . $this->pagehook, array( &$this, 'on_load_page' ) );
......@@ -155,7 +191,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
/**
* Secondary admin menu (after settings)
*/
function secondary_menu_items() {
public function secondary_menu_items() {
add_submenu_page( $this->slug, __( 'Settings', 'ultimate-member' ), __( 'Settings', 'ultimate-member' ), 'manage_options', 'um_options', array( UM()->admin_settings(), 'settings_page' ) );
add_submenu_page( $this->slug, __( 'Forms', 'ultimate-member' ), __( 'Forms', 'ultimate-member' ), 'manage_options', 'edit.php?post_type=um_form', '' );
add_submenu_page( $this->slug, __( 'User Roles', 'ultimate-member' ), __( 'User Roles', 'ultimate-member' ), 'manage_options', 'um_roles', array( &$this, 'um_roles_pages' ) );
......
......@@ -1021,7 +1021,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
public function add_metabox_form() {
add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( $this, 'custom_submitdiv' ), 'um_form', 'side', 'high' );
if ( defined( 'UM_LEGACY_BUILDER_OFF' ) && UM_LEGACY_BUILDER_OFF ) {
if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE && UM()->options()->get( 'enable_new_form_builder' ) ) {
// Do new metabox.
} else {
add_meta_box( 'um-admin-form-mode', __( 'Select Form Type', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'normal', 'default' );
......@@ -1267,7 +1267,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
}
// Set post meta for legacy support in the future.
add_post_meta( $post_id, 'um_form_version', UM_VERSION );
add_post_meta( $post_id, 'um_form_version', UM_VERSION, true );
if ( empty( $_POST['post_title'] ) ) {
$where = array( 'ID' => $post_id );
......@@ -1494,7 +1494,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
break;
case '_validate':
if ( array_key_exists( 'mode', $form_data ) && 'login' === $form_data['mode'] && in_array( $field_args['metakey'], array( 'username', 'user_login', 'user_email' ), true ) ) {
if ( array_key_exists( 'mode', $form_data ) && 'login' === $form_data['mode'] && array_key_exists( 'metakey', $field_args ) && in_array( $field_args['metakey'], array( 'username', 'user_login', 'user_email' ), true ) ) {
return;
}
?>
......
......@@ -31,8 +31,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
add_action( 'wp_ajax_um_dismiss_notice', array( &$this, 'dismiss_notice' ) );
add_action( 'admin_init', array( &$this, 'force_dismiss_notice' ) );
add_action( 'current_screen', array( &$this, 'create_list_for_screen' ) );
}
/**
......@@ -51,8 +49,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
$this->extensions_page();
$this->template_version();
$this->child_theme_required();
// Removed for now to avoid the bad reviews.
......@@ -82,13 +78,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
do_action( 'um_admin_create_notices' );
}
public function create_list_for_screen() {
if ( UM()->admin()->screen()->is_own_screen() ) {
$this->secure_settings();
}
}
/**
* @return array
*/
......@@ -587,9 +576,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
}
}
function check_wrong_licenses() {
$invalid_license = 0;
public function check_wrong_licenses() {
$invalid_license = 0;
$arr_inactive_license_keys = array();
if ( empty( UM()->admin_settings()->settings_structure['licenses']['fields'] ) ) {
......@@ -599,10 +587,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
foreach ( UM()->admin_settings()->settings_structure['licenses']['fields'] as $field_data ) {
$license = get_option( "{$field_data['id']}_edd_answer" );
if ( ( is_object( $license ) && 'valid' == $license->license ) || 'valid' == $license )
if ( ( is_object( $license ) && isset( $license->license ) && 'valid' === $license->license ) || 'valid' === $license ) {
continue;
}
if ( ( is_object( $license ) && 'inactive' == $license->license ) || 'inactive' == $license ) {
if ( ( is_object( $license ) && isset( $license->license ) && 'inactive' === $license->license ) || 'inactive' === $license ) {
$arr_inactive_license_keys[] = $license->item_name;
}
......@@ -614,7 +603,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
'license_key',
array(
'class' => 'error',
// translators: %1$s is a inactive license number; %2$s is a plugin name; %3$s is a store link.
// translators: %1$s is an inactive license number; %2$s is a plugin name; %3$s is a store link.
'message' => '<p>' . sprintf( __( 'There are %1$s inactive %2$s license keys for this site. This site is not authorized to get plugin updates. You can active this site on <a href="%3$s">www.ultimatemember.com</a>.', 'ultimate-member' ), count( $arr_inactive_license_keys ), UM_PLUGIN_NAME, UM()->store_url ) . '</p>',
),
3
......@@ -622,12 +611,20 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
}
if ( $invalid_license ) {
$licenses_page_url = add_query_arg(
array(
'page' => 'um_options',
'tab' => 'licenses',
),
admin_url( 'admin.php' )
);
$this->add_notice(
'license_key',
array(
'class' => 'error',
// translators: %1$s is a invalid license; %2$s is a plugin name; %3$s is a license link.
'message' => '<p>' . sprintf( __( 'You have %1$s invalid or expired license keys for %2$s. Please go to the <a href="%3$s">Licenses page</a> to correct this issue.', 'ultimate-member' ), $invalid_license, UM_PLUGIN_NAME, add_query_arg( array( 'page' => 'um_options', 'tab' => 'licenses' ), admin_url( 'admin.php' ) ) ) . '</p>',
// translators: %1$s is an invalid license; %2$s is a plugin name; %3$s is a license link.
'message' => '<p>' . sprintf( __( 'You have %1$s invalid or expired license keys for %2$s. Please go to the <a href="%3$s">Licenses page</a> to correct this issue.', 'ultimate-member' ), $invalid_license, UM_PLUGIN_NAME, $licenses_page_url ) . '</p>',
),
3
);
......@@ -776,36 +773,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
}
/**
* Check Templates Versions notice
*/
public function template_version() {
if ( true === (bool) get_option( 'um_override_templates_outdated' ) ) {
$link = admin_url( 'admin.php?page=um_options&tab=override_templates' );
ob_start();
?>
<p>
<?php
// translators: %s override templates page link.
echo wp_kses( sprintf( __( 'Your templates are out of date. Please visit <a href="%s">override templates status page</a> and update templates.', 'ultimate-member' ), $link ), UM()->get_allowed_html( 'admin_notice' ) );
?>
</p>
<?php
$message = ob_get_clean();
UM()->admin()->notices()->add_notice(
'um_override_templates_notice',
array(
'class' => 'error',
'message' => $message,
'dismissible' => false,
),
10
);
}
}
/**
* Check if there isn't installed child-theme. Child theme is required for safely saved customizations.
*/
public function child_theme_required() {
......@@ -820,7 +787,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
<p>
<?php
// translators: %s child-theme article link.
echo wp_kses( sprintf( __( 'We highly recommend using a <a href="%s">child-theme</a> for Ultimate Member customization, which hasn\'t dependencies with the official themes repo, so your custom files cannot be rewritten after a theme upgrade.<br />Otherwise, the customization files may be deleted after every theme upgrade.', 'ultimate-member' ), 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), UM()->get_allowed_html( 'admin_notice' ) );
echo wp_kses( sprintf( __( 'We recommend using a <a href="%s">child-theme</a> for Ultimate Member customization. Unlike official theme repositories, child themes don\'t have dependencies that could lead to your custom files being overwritten during a theme upgrade.<br />Without a child theme, your customization files may be deleted after every theme update.', 'ultimate-member' ), 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), UM()->get_allowed_html( 'admin_notice' ) );
?>
</p>
......@@ -838,39 +805,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
}
}
/**
* First time installed Secure settings.
*/
public function secure_settings() {
ob_start();
?>
<p>
<strong><?php esc_html_e( 'Important Update', 'ultimate-member' ); ?></strong><br/>
<?php esc_html_e( 'Ultimate Member has a new additional feature to secure your Ultimate Member forms to prevent attacks from injecting accounts with administrative roles &amp; capabilities.', 'ultimate-member' ); ?>
</p>
<p>
<a class="button button-primary" href="<?php echo esc_attr( admin_url( 'admin.php?page=um_options&tab=secure&um_dismiss_notice=secure_settings&um_admin_nonce=' . wp_create_nonce( 'um-admin-nonce' ) ) ); ?>"><?php esc_html_e( 'Manage Security Settings', 'ultimate-member' ); ?></a>
<a class="button" target="_blank" href="https://docs.ultimatemember.com/article/1869-security-feature"><?php esc_html_e( 'Read the documentation', 'ultimate-member' ); ?></a>
</p>
<?php
$message = ob_get_clean();
$this->add_notice(
'secure_settings',
array(
'class' => 'warning',
'message' => $message,
'dismissible' => true,
),
1
);
}
public function common_secure() {
if ( UM()->options()->get( 'lock_register_forms' ) ) {
ob_start();
?>
<p>
<?php esc_html_e( 'Your Register forms are now locked. You can unlock them in Ultimate Member > Settings > Secure > Lock All Register Forms.', 'ultimate-member' ); ?>
<?php esc_html_e( 'Your Register forms are now locked. You can unlock them in Ultimate Member > Settings > Advanced > Security > Lock All Register Forms.', 'ultimate-member' ); ?>
</p>
<?php
$message = ob_get_clean();
......@@ -889,7 +829,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
ob_start();
?>
<p>
<?php esc_html_e( 'Mandatory password changes has been enabled. You can disable them in Ultimate Member > Settings > Secure > Display Login form notice to reset passwords.', 'ultimate-member' ); ?>
<?php esc_html_e( 'Mandatory password changes has been enabled. You can disable them in Ultimate Member > Settings > Advanced > Security > Display Login form notice to reset passwords.', 'ultimate-member' ); ?>
</p>
<?php
$message = ob_get_clean();
......@@ -908,7 +848,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
ob_start();
?>
<p>
<?php esc_html_e( 'Ban for administrative capabilities is enabled. You can disable them in Ultimate Member > Settings > Secure > Enable ban for administrative capabilities.', 'ultimate-member' ); ?>
<?php esc_html_e( 'Ban for administrative capabilities is enabled. You can disable them in Ultimate Member > Settings > Advanced > Security > Enable ban for administrative capabilities.', 'ultimate-member' ); ?>
</p>
<?php
$message = ob_get_clean();
......
......@@ -85,7 +85,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
}
$old_version = get_option( 'theme_version ' . $theme->get( 'Name' ) );
$version = $theme->get( 'Version' );
$version = $theme->get( 'Version' );
if ( $old_version === $version ) {
return;
}
......@@ -98,14 +98,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
$um_dir = $theme->get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'ultimate-member';
@mkdir( $um_dir, 0777, true );
$src = realpath( $temp_dir );
$src = realpath( $temp_dir );
$dest = realpath( $um_dir );
if ( $src && $dest ) {
self::recurse_copy( $src, $dest );
error_log( "UM Log. Theme '" . $theme->get( 'template' ) . "' templates restored." );
error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates restored." );
UM()->files()->remove_dir( $src );
} else {
error_log( "UM Error. Can not restore theme templates." );
error_log( 'UM Error. Can not restore theme templates.' );
}
delete_option( 'theme_version ' . $theme->get( 'Name' ) );
......@@ -140,13 +140,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
$temp_dir = UM()->uploader()->get_core_temp_dir() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $theme->get( 'template' );
@mkdir( $temp_dir, 0777, true );
$src = realpath( $um_dir );
$src = realpath( $um_dir );
$dest = realpath( $temp_dir );
if ( $src && $dest ) {
self::recurse_copy( $src, $dest );
error_log( "UM Log. Theme '" . $theme->get( 'template' ) . "' templates saved." );
error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates saved." );
} else {
error_log( "UM Error. Can not save theme templates." );
error_log( 'UM Error. Can not save theme templates.' );
}
update_option( 'theme_version ' . $theme->get( 'Name' ), $theme->get( 'Version' ) );
......@@ -156,7 +156,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
/**
* Filter: upgrader_package_options
*
*
* @param array $options
* @return array
*/
......@@ -170,7 +170,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
/**
* Action: upgrader_process_complete
*
*
* @param \WP_Upgrader $WP_Upgrader
* @param array $options
*/
......@@ -184,4 +184,4 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
}
}
\ No newline at end of file
}
......
......@@ -247,7 +247,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
'label' => __( 'Put as Pending Review', 'ultimate-member' )
),
'um_resend_activation' => array(
'label' => __( 'Resend Activation E-mail', 'ultimate-member' )
'label' => __( 'Resend Activation Email', 'ultimate-member' )
),
'um_deactivate' => array(
'label' => __( 'Deactivate', 'ultimate-member' )
......@@ -407,7 +407,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
$status = array(
'approved' => __( 'Approved', 'ultimate-member' ),
'awaiting_admin_review' => __( 'Pending review', 'ultimate-member' ),
'awaiting_email_confirmation' => __( 'Waiting e-mail confirmation', 'ultimate-member' ),
'awaiting_email_confirmation' => __( 'Waiting email confirmation', 'ultimate-member' ),
'inactive' => __( 'Inactive', 'ultimate-member' ),
'rejected' => __( 'Rejected', 'ultimate-member' ),
);
......
......@@ -99,6 +99,15 @@ class UM_Emails_List_Table extends WP_List_Table {
$this->_column_headers = array( $columns, $hidden, $sortable );
}
/**
* Generates the table navigation above or below the table
*
* @since 3.1.0
* @param string $which
*/
protected function display_tablenav( $which ) {
// Stop displaying tablenav.
}
/**
* @param object $item
......@@ -221,12 +230,14 @@ class UM_Emails_List_Table extends WP_List_Table {
function column_email( $item ) {
$active = UM()->options()->get( $item['key'] . '_on' );
$icon = ! empty( $active ) ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt';
$link = add_query_arg( array( 'email' => $item['key'] ) );
$text = '<span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span><a href="' . esc_url( $link ) . '"><strong>' . $item['title'] . '</strong></a>';
$icon = ! empty( $active ) ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt';
$icon_title = ! empty( $active ) ? __( 'Enabled', 'ultimate-member' ) : __( 'Disabled', 'ultimate-member' );
$link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) );
$text = '<span class="dashicons um-notification-status ' . esc_attr( $icon ) . '" title="' . esc_attr( $icon_title ) . '"></span><a href="' . esc_url( $link ) . '"><strong>' . esc_html( $item['title'] ) . '</strong></a>';
if ( ! empty( $item['description'] ) ) {
$text .= ' <span class="um_tooltip dashicons dashicons-editor-help" title="' . esc_attr__( $item['description'], 'ultimate-member' ) . '"></span>';
$text .= ' <span class="um_tooltip dashicons dashicons-editor-help" title="' . esc_attr( $item['description'] ) . '"></span>';
}
return $text;
......@@ -239,11 +250,11 @@ class UM_Emails_List_Table extends WP_List_Table {
* @return string
*/
function column_recipients( $item ) {
if ( $item['recipient'] == 'admin' ) {
if ( 'admin' === $item['recipient'] ) {
return UM()->options()->get( 'admin_email' );
} else {
return __( 'Member', 'ultimate-member' );
}
return __( 'Member', 'ultimate-member' );
}
......@@ -253,7 +264,8 @@ class UM_Emails_List_Table extends WP_List_Table {
* @return string
*/
function column_configure( $item ) {
return '<a class="button um-email-configure" href="' . add_query_arg( array( 'email' => $item['key'] ) ) . '" title="' . esc_attr__( 'Edit template', 'ultimate-member' ) . '"><span class="dashicons dashicons-admin-generic"></span></a>';
$edit_link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) );
return '<a class="button um-email-configure" href="' . esc_url( $edit_link ) . '" title="' . esc_attr__( 'Manage', 'ultimate-member' ) . '">' . esc_html__( 'Manage', 'ultimate-member' ) . '</a>';
}
......@@ -276,13 +288,13 @@ class UM_Emails_List_Table extends WP_List_Table {
}
$ListTable = new UM_Emails_List_Table( array(
'singular' => __( 'Email Notification', 'ultimate-member' ),
'plural' => __( 'Email Notifications', 'ultimate-member' ),
'ajax' => false
'singular' => __( 'Email Notification', 'ultimate-member' ),
'plural' => __( 'Email Notifications', 'ultimate-member' ),
'ajax' => false,
));
$per_page = 20;
$paged = $ListTable->get_pagenum();
$per_page = 999;
$paged = $ListTable->get_pagenum();
/**
* UM hook
......@@ -306,9 +318,9 @@ $paged = $ListTable->get_pagenum();
* ?>
*/
$columns = apply_filters( 'um_email_templates_columns', array(
'email' => __( 'Email', 'ultimate-member' ),
'recipients' => __( 'Recipient(s)', 'ultimate-member' ),
'configure' => '',
'email' => __( 'Email', 'ultimate-member' ),
'recipients' => __( 'Recipient(s)', 'ultimate-member' ),
'configure' => '',
) );
$ListTable->set_columns( $columns );
......@@ -317,18 +329,21 @@ $emails = UM()->config()->email_notifications;
$ListTable->prepare_items();
$ListTable->items = array_slice( $emails, ( $paged - 1 ) * $per_page, $per_page );
$ListTable->wpc_set_pagination_args( array( 'total_items' => count( $emails ), 'per_page' => $per_page ) ); ?>
<p class="description" style="margin: 20px 0 0 0;">
<?php
// translators: %s: doc link.
echo wp_kses( sprintf( __( 'You may get more details about email notifications customization <a href="%s">here</a>', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/1335-email-templates' ), UM()->get_allowed_html( 'admin_notice' ) );
?>
$ListTable->wpc_set_pagination_args( array( 'total_items' => count( $emails ), 'per_page' => $per_page ) );
?>
<h2 class="title"><?php esc_html_e( 'Email notifications', 'ultimate-member' ); ?></h2>
<p>
<?php esc_html_e( 'Email notifications sent from Ultimate Member are listed below. Click on an email to configure it.', 'ultimate-member' ); ?>
<br />
<?php esc_html_e( 'Emails should be sent from an email using your website\'s domain name. We highly recommend using a SMTP service email delivery.', 'ultimate-member' ); ?>
<?php echo wp_kses( sprintf( __( 'Please see this <a href="%s" target="_blank">doc</a> for more information.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/116-not-receiving-user-emails-or-admin-notifications' ), UM()->get_allowed_html( 'admin_notice' ) ); ?>
</p>
<div class="clear"></div>
<form action="" method="get" name="um-settings-emails" id="um-settings-emails">
<input type="hidden" name="page" value="um_options" />
<input type="hidden" name="tab" value="email" />
<?php $ListTable->display(); ?>
</form>
<div class="clear"></div>
......
......@@ -58,8 +58,7 @@ class UM_Versions_List_Table extends WP_List_Table {
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, array(), $sortable );
$templates = get_option( 'um_template_statuses', array() );
$templates = is_array( $templates ) ? $templates : array();
$templates = UM()->common()->theme()->build_templates_data();
@uasort(
$templates,
......@@ -163,6 +162,16 @@ class UM_Versions_List_Table extends WP_List_Table {
$icon = 1 === $item['status_code'] ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt';
return $item['status'] . ' <span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span>';
}
/**
* Generates the table navigation above or below the table
*
* @since 3.1.0
* @param string $which
*/
protected function display_tablenav( $which ) {
// Stop displaying tablenav.
}
}
$list_table = new UM_Versions_List_Table(
......@@ -210,6 +219,7 @@ $list_table->prepare_items();
<form action="" method="get" name="um-settings-template-versions" id="um-settings-template-versions">
<input type="hidden" name="page" value="um_options" />
<input type="hidden" name="tab" value="override_templates" />
<input type="hidden" name="tab" value="advanced" />
<input type="hidden" name="section" value="override_templates" />
<?php $list_table->display(); ?>
</form>
......
......@@ -70,7 +70,7 @@
</td>
<td class="last t">
<a href="<?php echo esc_url( admin_url( 'users.php?um_status=awaiting_email_confirmation' ) ); ?>" class="warning">
<?php _e( 'Awaiting E-mail Confirmation', 'ultimate-member' ); ?>
<?php _e( 'Awaiting Email Confirmation', 'ultimate-member' ); ?>
</a>
</td>
</tr>
......
......@@ -166,12 +166,12 @@ $premium['profile-tabs'] = array(
'desc' => 'Add custom tabs to profiles',
);
//$premium['stripe'] = array(
// 'url' => 'https://ultimatemember.com/extensions/stripe/',
// 'img' => 'stripe.png',
// 'name' => 'Stripe',
// 'desc' => 'Sell paid memberships to access your website via Stripe subscriptions',
//);
$premium['stripe'] = array(
'url' => 'https://ultimatemember.com/extensions/stripe/',
'img' => 'stripe.png',
'name' => 'Stripe',
'desc' => 'Sell paid memberships to access your website via Stripe subscriptions',
);
$free['jobboardwp'] = array(
'url' => 'https://wordpress.org/plugins/um-jobboardwp',
......
......@@ -43,7 +43,7 @@
'id' => '_um_can_delete_everyone',
'type' => 'checkbox',
'label' => __( 'Can delete other member accounts?', 'ultimate-member' ),
'tooltip' => __( 'Allow this role to edit accounts of other members', 'ultimate-member' ),
'tooltip' => __( 'Allow this role to delete other user accounts.', 'ultimate-member' ),
'value' => ! empty( $role['_um_can_delete_everyone'] ) ? $role['_um_can_delete_everyone'] : 0,
),
array(
......@@ -58,4 +58,4 @@
)
)
) )->render_form(); ?>
</div>
\ No newline at end of file
</div>
......
<?php if ( ! defined( 'ABSPATH' ) ) {
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$role = $object['data']; ?>
$role = $object['data'];
?>
<div class="um-admin-metabox">
<?php
UM()->admin_forms(
$form = UM()->admin_forms(
array(
'class' => 'um-role-publish um-top-label',
'prefix_id' => 'role',
......@@ -20,7 +22,8 @@ $role = $object['data']; ?>
),
),
)
)->render_form();
);
$form->render_form();
?>
</div>
......@@ -31,3 +34,10 @@ $role = $object['data']; ?>
<div class="clear"></div>
</div>
</div>
<?php
echo $form->render_external_link(
array(
'html' => __( 'Learn more about role priorities', 'ultimate-member' ),
'url' => 'https://docs.ultimatemember.com/article/1494-how-to-set-role-priority-for-user-roles',
)
);
......
......@@ -76,8 +76,8 @@
array(
'id' => '_um_url_email_activate',
'type' => 'text',
'label' => __( 'URL redirect after e-mail activation', 'ultimate-member' ),
'tooltip' => __( 'If you want users to go to a specific page other than login page after e-mail activation, enter the URL here.', 'ultimate-member' ),
'label' => __( 'URL redirect after email activation', 'ultimate-member' ),
'tooltip' => __( 'If you want users to go to a specific page other than login page after email activation, enter the URL here.', 'ultimate-member' ),
'value' => ! empty( $role['_um_url_email_activate'] ) ? __( $role['_um_url_email_activate'], 'ultimate-member' ) : '',
'conditional' => array( '_um_status', '=', 'checkmail' ),
),
......
......@@ -20,10 +20,23 @@ if ( ! class_exists( 'um\ajax\Init' ) ) {
* @used-by \UM::includes()
*/
public function includes() {
$this->pages();
$this->secure();
}
/**
* @since 2.8.3
*
* @return Pages
*/
public function pages() {
if ( empty( UM()->classes['um\ajax\pages'] ) ) {
UM()->classes['um\ajax\pages'] = new Pages();
}
return UM()->classes['um\ajax\pages'];
}
/**
* @since 2.6.8
*
* @return Secure
......
<?php
namespace um\ajax;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Pages
*
* @package um\ajax
*/
class Pages {
/**
* Pages constructor.
*/
public function __construct() {
add_action( 'wp_ajax_um_get_pages_list', array( $this, 'get_pages_list' ) );
}
/**
* AJAX callback for getting the pages list
*/
public function get_pages_list() {
UM()->admin()->check_ajax_nonce();
// we will pass post IDs and titles to this array
$return = array();
$pre_result = apply_filters( 'um_admin_settings_get_pages_list', false );
if ( false === $pre_result ) {
$query_args = array(
'post_type' => 'page',
'post_status' => 'publish', // if you don't want drafts to be returned
'ignore_sticky_posts' => 1,
'posts_per_page' => 10, // how much to show at once
'paged' => absint( $_GET['page'] ),
'orderby' => 'title',
'order' => 'asc',
);
if ( ! empty( $_GET['search'] ) ) {
$query_args['s'] = sanitize_text_field( $_GET['search'] ); // the search query
}
$search_results = new \WP_Query( $query_args );
if ( $search_results->have_posts() ) {
while ( $search_results->have_posts() ) {
$search_results->the_post();
// shorten the title a little
$title = ( mb_strlen( $search_results->post->post_title ) > 50 ) ? mb_substr( $search_results->post->post_title, 0, 49 ) . '...' : $search_results->post->post_title;
$title = sprintf( __( '%s (ID: %s)', 'ultimate-member' ), $title, $search_results->post->ID );
$return[] = array( $search_results->post->ID, $title ); // array( Post ID, Post Title )
}
}
$return['total_count'] = $search_results->found_posts;
} else {
// got already calculated posts array from 3rd-party integrations (e.g. WPML, Polylang)
$return = $pre_result;
}
wp_send_json( $return );
}
}
......@@ -282,10 +282,10 @@ class Secure {
$content .= $br . '<div style="padding:10px; border:1px solid #ccc;">' . wp_kses( __( '<strong style="color:red">WARNING:</strong> Ensure that you\'ve created a full backup of your site as your restoration point before changing anything on your site with our recommendations.', 'ultimate-member' ), UM()->get_allowed_html( 'admin_notice' ) ) . '</div>';
if ( $suspicious_accounts_count > 0 ) {
$lock_register_forms_url = admin_url( 'admin.php?page=um_options&tab=secure&um_secure_lock_register_forms=1&_wpnonce=' . wp_create_nonce( 'um_secure_lock_register_forms' ) );
$lock_register_forms_url = admin_url( 'admin.php?page=um_options&tab=advanced&section=secure&um_secure_lock_register_forms=1&_wpnonce=' . wp_create_nonce( 'um_secure_lock_register_forms' ) );
$content .= $br . esc_html__( '1. Please temporarily lock all your active Register forms.', 'ultimate-member' );
$content .= ' <a href="' . esc_attr( $lock_register_forms_url ) . '" target="_blank">' . esc_html__( 'Click here to lock them now.', 'ultimate-member' ) . '</a>';
$content .= ' ' . esc_html__( 'You can unblock the Register forms later. Just go to Ultimate Member > Settings > Secure > uncheck the option "Lock All Register Forms".', 'ultimate-member' );
$content .= ' ' . esc_html__( 'You can unblock the Register forms later. Just go to Ultimate Member > Settings > Advanced > Security and uncheck the option "Lock All Register Forms".', 'ultimate-member' );
$content .= $br . $br;
$suspicious_accounts_url = admin_url( 'users.php?um_status=inactive' );
......
......@@ -228,7 +228,8 @@ if ( ! class_exists( 'UM' ) ) {
// init widgets
add_action( 'widgets_init', array( &$this, 'widgets_init' ) );
//include short non class functions
// Include short non-class functions
require_once 'um-core-functions.php';
require_once 'um-short-functions.php';
require_once 'um-deprecated-functions.php';
}
......@@ -585,8 +586,6 @@ if ( ! class_exists( 'UM' ) ) {
$this->theme_updater();
} elseif ( $this->is_request( 'frontend' ) ) {
$this->frontend()->includes();
$this->account();
$this->password();
$this->login();
$this->register();
$this->user_posts();
......@@ -594,6 +593,8 @@ if ( ! class_exists( 'UM' ) ) {
}
//common includes
$this->account();
$this->password();
$this->rewrite();
$this->mail();
$this->rest_api();
......
......@@ -24,6 +24,7 @@ if ( ! class_exists( 'um\common\Init' ) ) {
$this->screen();
$this->secure()->hooks();
$this->site_health();
$this->theme()->hooks();
}
/**
......@@ -73,5 +74,17 @@ if ( ! class_exists( 'um\common\Init' ) ) {
}
return UM()->classes['um\common\site_health'];
}
/**
* @since 2.8.3
*
* @return Theme
*/
public function theme() {
if ( empty( UM()->classes['um\common\theme'] ) ) {
UM()->classes['um\common\theme'] = new Theme();
}
return UM()->classes['um\common\theme'];
}
}
}
......
......@@ -18,7 +18,7 @@ if ( ! class_exists( 'um\common\Screen' ) ) {
* Screen constructor.
*/
public function __construct() {
add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000, 1 );
add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000 );
}
/**
......
<?php
namespace um\common;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Theme
*
* @package um\common
*/
class Theme {
public function hooks() {
add_action( 'after_switch_theme', array( &$this, 'flush_transient_templates_data' ) );
}
/**
* Find outdated UM templates and notify Administrator.
*
*/
public function flush_transient_templates_data() {
// Flush transient with the custom templates list.
delete_transient( 'um_custom_templates_list' );
}
/**
* Scan the template files.
*
* @param string $template_path Path to the template directory.
* @return array
*/
public static function scan_template_files( $template_path ) {
$files = @scandir( $template_path ); // @codingStandardsIgnoreLine.
$result = array();
if ( ! empty( $files ) ) {
foreach ( $files as $value ) {
if ( ! in_array( $value, array( '.', '..' ), true ) ) {
if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
$sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
foreach ( $sub_files as $sub_file ) {
$result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
}
} else {
$result[] = $value;
}
}
}
}
return $result;
}
public static function get_all_templates() {
$scan_files['um'] = self::scan_template_files( UM_PATH . '/templates/' );
/**
* Filters an array of the template files for scanning versions.
*
* @since 2.6.1
* @hook um_override_templates_scan_files
*
* @param {array} $scan_files Template files for scanning versions.
*
* @return {array} Template files for scanning versions.
*/
return apply_filters( 'um_override_templates_scan_files', $scan_files );
}
/**
* @param $file string
*
* @return string
*/
public static function get_file_version( $file ) {
// Avoid notices if file does not exist.
if ( ! file_exists( $file ) ) {
return '';
}
// We don't need to write to the file, so just open for reading.
$fp = fopen( $file, 'r' ); // @codingStandardsIgnoreLine.
// Pull only the first 8kiB of the file in.
$file_data = fread( $fp, 8192 ); // @codingStandardsIgnoreLine.
// PHP will close a file handle, but we are good citizens.
fclose( $fp ); // @codingStandardsIgnoreLine.
// Make sure we catch CR-only line endings.
$file_data = str_replace( "\r", "\n", $file_data );
$version = '';
if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) {
$version = _cleanup_header_comment( $match[1] );
}
return $version;
}
public function get_custom_templates_list() {
$files_in_theme = array();
$scan_files = self::get_all_templates();
foreach ( $scan_files as $key => $files ) {
foreach ( $files as $file ) {
if ( false === strpos( $file, 'email/' ) ) {
/**
* Filters an array of the template files for scanning versions based on $key.
*
* Note: $key - means um or extension key.
*
* @since 2.6.1
* @hook um_override_templates_get_template_path__{$key}
*
* @param {array} $located Template file paths for scanning versions.
* @param {string} $file Template file name.
*
* @return {array} Template file paths for scanning versions.
*/
$located = apply_filters( "um_override_templates_get_template_path__{$key}", array(), $file );
$exceptions = array(
'members-grid.php',
'members-header.php',
'members-list.php',
'members-pagination.php',
'searchform.php',
'login-to-view.php',
'profile/comments.php',
'profile/comments-single.php',
'profile/posts.php',
'profile/posts-single.php',
'modal/um_upload_single.php',
'modal/um_view_photo.php',
);
$theme_file = false;
if ( ! empty( $located ) ) {
$theme_file = $located['theme'];
} elseif ( in_array( $file, $exceptions, true ) && file_exists( get_stylesheet_directory() . '/ultimate-member/' . $file ) ) {
$theme_file = get_stylesheet_directory() . '/ultimate-member/' . $file;
} elseif ( file_exists( get_stylesheet_directory() . '/ultimate-member/templates/' . $file ) ) {
$theme_file = get_stylesheet_directory() . '/ultimate-member/templates/' . $file;
}
if ( ! empty( $theme_file ) ) {
if ( ! empty( $located ) ) {
$core_path = $located['core'];
} else {
$core_path = UM_PATH . 'templates/' . $file;
}
$files_in_theme[] = array(
'core' => $core_path,
'theme' => $theme_file,
);
}
}
}
}
return $files_in_theme;
}
public function is_outdated_template_exist() {
$outdated_exists = false;
$templates = $this->get_custom_templates_list();
foreach ( $templates as $files ) {
if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) {
continue;
}
$core_path = $files['core'];
$theme_file = $files['theme'];
$core_version = self::get_file_version( $core_path );
$theme_version = self::get_file_version( $theme_file );
if ( '' === $theme_version || version_compare( $theme_version, $core_version, '<' ) ) {
$outdated_exists = true;
break;
}
}
return $outdated_exists;
}
public function build_templates_data() {
$templates_data = array();
// Get from cache if isn't empty and request isn't force.
$transient = get_transient( 'um_custom_templates_list' );
if ( false !== $transient && array_key_exists( 'data', $transient ) ) {
return $transient['data'];
}
$templates = $this->get_custom_templates_list();
foreach ( $templates as $files ) {
if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) {
continue;
}
$core_path = $files['core'];
$theme_file = $files['theme'];
$core_version = self::get_file_version( $core_path );
$theme_version = self::get_file_version( $theme_file );
$status = esc_html__( 'Theme version up to date', 'ultimate-member' );
$status_code = 1;
if ( '' === $theme_version ) {
$status = esc_html__( 'Theme version is empty', 'ultimate-member' );
$status_code = 0;
} elseif ( version_compare( $theme_version, $core_version, '<' ) ) {
$status = esc_html__( 'Theme version is out of date', 'ultimate-member' );
$status_code = 0;
}
$templates_data[] = array(
'core_version' => $core_version,
'theme_version' => $theme_version,
'core_file' => stristr( $core_path, 'wp-content' ),
'theme_file' => stristr( $theme_file, 'wp-content' ),
'status' => $status,
'status_code' => $status_code,
);
}
// Cache results via transient setting.
$transient = array(
'data' => $templates_data,
'time' => time(),
);
set_transient( 'um_custom_templates_list', $transient, 5 * MINUTE_IN_SECONDS );
return $templates_data;
}
}
......@@ -273,7 +273,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
),
'tel' => array(
'name' => __( 'Telephone Box', 'ultimate-member' ),
'name' => __( 'Telephone', 'ultimate-member' ),
'col1' => array('_title','_metakey','_help','_default','_min_chars','_visibility'),
'col2' => array('_label','_placeholder','_public','_roles','_validate','_custom_validate','_max_chars'),
'col3' => array('_required','_editable','_icon'),
......@@ -782,10 +782,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
),
'username' => array(
'title' => __('Username or E-mail','ultimate-member'),
'title' => __('Username or Email','ultimate-member'),
'metakey' => 'username',
'type' => 'text',
'label' => __('Username or E-mail','ultimate-member'),
'label' => __('Username or Email','ultimate-member'),
'required' => 1,
'public' => 1,
'editable' => false,
......@@ -871,10 +871,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
),
'user_email' => array(
'title' => __('E-mail Address','ultimate-member'),
'title' => __('Email Address','ultimate-member'),
'metakey' => 'user_email',
'type' => 'text',
'label' => __('E-mail Address','ultimate-member'),
'label' => __('Email Address','ultimate-member'),
'required' => 0,
'public' => 1,
'validate' => 'unique_email',
......@@ -882,10 +882,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
),
'secondary_user_email' => array(
'title' => __('Secondary E-mail Address','ultimate-member'),
'title' => __('Secondary Email Address','ultimate-member'),
'metakey' => 'secondary_user_email',
'type' => 'text',
'label' => __('Secondary E-mail Address','ultimate-member'),
'label' => __('Secondary Email Address','ultimate-member'),
'required' => 0,
'public' => 1,
'editable' => true,
......@@ -1271,7 +1271,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
),
'username_b' => array(
'title' => __('Username or E-mail','ultimate-member'),
'title' => __('Username or Email','ultimate-member'),
'metakey' => 'username_b',
'type' => 'text',
'placeholder' => __('Enter your username or email','ultimate-member'),
......@@ -1558,11 +1558,11 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
$array['skype'] = __('Skype ID','ultimate-member');
$array['soundcloud'] = __( 'SoundCloud Profile', 'ultimate-member' );
$array['twitter_url'] = __( 'X (formerly Twitter) URL', 'ultimate-member' );
$array['is_email'] = __('E-mail( Not Unique )','ultimate-member');
$array['unique_email'] = __('Unique E-mail','ultimate-member');
$array['is_email'] = __('Email( Not Unique )','ultimate-member');
$array['unique_email'] = __('Unique Email','ultimate-member');
$array['unique_value'] = __('Unique Metakey value','ultimate-member');
$array['unique_username'] = __('Unique Username','ultimate-member');
$array['unique_username_or_email'] = __('Unique Username/E-mail','ultimate-member');
$array['unique_username_or_email'] = __('Unique Username/Email','ultimate-member');
$array['url'] = __('Website URL','ultimate-member');
$array['youtube_url'] = __('YouTube Profile','ultimate-member');
$array['youtube_video'] = __('YouTube Video','ultimate-member');
......
......@@ -623,7 +623,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
* @return string
*/
public function show_error( $key ) {
return UM()->form()->errors[ $key ];
if ( empty( UM()->form()->errors ) ) {
return '';
}
return array_key_exists( $key, UM()->form()->errors ) ? UM()->form()->errors[ $key ] : '';
}
/**
......@@ -634,7 +637,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
* @return string
*/
public function show_notice( $key ) {
return UM()->form()->notices[ $key ];
if ( empty( UM()->form()->notices ) ) {
return '';
}
return array_key_exists( $key, UM()->form()->notices ) ? UM()->form()->notices[ $key ] : '';
}
/**
......
......@@ -305,7 +305,7 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
* }
* add_filter( 'um_email_template_body_attrs', 'my_email_template_body_attrs', 10, 3 );
*/
$body_attrs = apply_filters( 'um_email_template_body_attrs', 'style="background: #f2f2f2;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;"', $slug, $args );
$body_attrs = apply_filters( 'um_email_template_body_attrs', 'style="background: #fff;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;"', $slug, $args );
?>
<body <?php echo $body_attrs; ?>>
......@@ -351,8 +351,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
*/
$message = apply_filters( 'um_email_send_message_content', $message, $slug, $args );
add_filter( 'um_template_tags_patterns_hook', array( &$this, 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( &$this, 'add_replace_placeholder' ) );
// add_filter( 'um_template_tags_patterns_hook', array( &$this, 'add_placeholder' ) );
// add_filter( 'um_template_tags_replaces_hook', array( &$this, 'add_replace_placeholder' ) );
// Convert tags in email template.
return um_convert_tags( $message, $args );
......@@ -421,8 +421,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
$mail_from_addr = UM()->options()->get( 'mail_from_addr' ) ? UM()->options()->get( 'mail_from_addr' ) : get_bloginfo( 'admin_email' );
$this->headers = 'From: ' . stripslashes( $mail_from ) . ' <' . $mail_from_addr . '>' . "\r\n";
add_filter( 'um_template_tags_patterns_hook', array( UM()->mail(), 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->mail(), 'add_replace_placeholder' ) );
add_filter( 'um_template_tags_patterns_hook', array( $this, 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( $this, 'add_replace_placeholder' ) );
/**
* Filters email notification subject.
......@@ -623,6 +623,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
$placeholders[] = '{login_url}';
$placeholders[] = '{password}';
$placeholders[] = '{account_activation_link}';
$placeholders[] = '{action_url}';
$placeholders[] = '{action_title}';
return $placeholders;
}
......@@ -641,6 +643,16 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
$replace_placeholders[] = um_get_core_page( 'login' );
$replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' );
$replace_placeholders[] = um_user( 'account_activation_link' );
$set_password_required = get_user_meta( um_user( 'ID' ), 'um_set_password_required', true );
if ( empty( $set_password_required ) || 'pending' === um_user( 'status' ) ) {
$replace_placeholders[] = um_get_core_page( 'login' );
$replace_placeholders[] = esc_html__( 'Login to our site', 'ultimate-member' );
} else {
$replace_placeholders[] = um_user( 'password_reset_link' );
$replace_placeholders[] = esc_html__( 'Set your password', 'ultimate-member' );
}
return $replace_placeholders;
}
}
......
......@@ -58,7 +58,11 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
var $filter_types = array();
/**
* Fields used for searching from wp_users table.
*
* @var string[]
*/
var $core_search_fields = array(
'user_login',
'user_url',
......@@ -67,6 +71,19 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
'user_nicename',
);
/**
* Fields used for sorting from wp_users table.
*
* @var string[]
*/
var $core_users_fields = array(
'user_login',
'user_url',
'display_name',
'user_email',
'user_nicename',
'user_registered',
);
/**
* @var
......@@ -408,7 +425,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
'first_name' => __( 'First Name', 'ultimate-member' ),
'last_name' => __( 'Last Name', 'ultimate-member' ),
'nickname' => __( 'Nickname', 'ultimate-member' ),
'secondary_user_email' => __( 'Secondary E-mail Address', 'ultimate-member' ),
'secondary_user_email' => __( 'Secondary Email Address', 'ultimate-member' ),
'description' => __( 'Biography', 'ultimate-member' ),
'phone_number' => __( 'Phone Number', 'ultimate-member' ),
'mobile_number' => __( 'Mobile Number', 'ultimate-member' ),
......@@ -1314,24 +1331,24 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$this->query_args['paged'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
}
/**
* Add sorting attributes for \WP_Users_Query
*
* @param array $directory_data Member Directory options
*/
function sorting_query( $directory_data ) {
public function sorting_query( $directory_data ) {
// sort members by
$this->query_args['order'] = 'ASC';
$sortby = ! empty( $_POST['sorting'] ) ? sanitize_text_field( $_POST['sorting'] ) : $directory_data['sortby'];
$sortby = ( $sortby == 'other' ) ? $directory_data['sortby_custom'] : $sortby;
$sortby = ( 'other' === $sortby ) ? $directory_data['sortby_custom'] : $sortby;
$custom_sort = array();
if ( ! empty( $directory_data['sorting_fields'] ) ) {
$sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
foreach ( $sorting_fields as $field ) {
if ( is_array( $field ) ) {
$field_keys = array_keys( $field );
$field_keys = array_keys( $field );
$custom_sort[] = $field_keys[0];
}
}
......@@ -1384,7 +1401,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$this->query_args['order'] = 'ASC';
}
} elseif ( in_array( $sortby, array( 'last_name', 'first_name', 'nickname' ) ) ) {
} elseif ( in_array( $sortby, array( 'last_name', 'first_name', 'nickname' ), true ) ) {
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $sortby . '_c' => array(
'key' => $sortby,
......@@ -1426,7 +1443,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$this->query_args['orderby'] = array( 'last_name_c' => 'ASC', 'first_name_c' => 'ASC' );
unset( $this->query_args['order'] );
} elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys ) ) {
} elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys, true ) ) {
$order = 'DESC';
if ( strstr( $sortby, '_desc' ) ) {
......@@ -1458,18 +1475,23 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
)
);
$this->query_args['orderby'] = array( $sortby . '_ns' => $order, 'user_registered' => 'DESC' );
$this->query_args['orderby'] = array(
$sortby . '_ns' => $order,
'user_registered' => 'DESC',
);
unset( $this->query_args['order'] );
} elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby == $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort ) ) {
} elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby === $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort, true ) ) {
$custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC';
$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'] );
$sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
if ( ! empty( $sorting_fields ) && is_array( $sorting_fields ) ) {
foreach ( $sorting_fields as $field ) {
if ( isset( $field[ $sorting ] ) ) {
......@@ -2371,8 +2393,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
if ( UM()->roles()->um_current_user_can( 'edit', $user_id ) ) {
$actions['um-editprofile'] = array(
'title' => __( 'Edit Profile', 'ultimate-member' ),
'url' => um_edit_profile_url(),
'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
'url' => um_edit_profile_url(),
);
}
......@@ -2403,8 +2425,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$url = add_query_arg( array( 'um_action' => $id, 'uid' => $user_id ), um_get_core_page( 'user' ) );
$actions[ $id ] = array(
'title' => $arr['label'],
'url' => $url,
'title' => esc_html( $arr['label'] ),
'url' => esc_url( $url ),
);
}
}
......@@ -2415,25 +2437,24 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
if ( empty( UM()->user()->cannot_edit ) ) {
$actions['um-editprofile'] = array(
'title' => __( 'Edit Profile', 'ultimate-member' ),
'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
'url' => um_edit_profile_url(),
);
}
$actions['um-myaccount'] = array(
'title' => __( 'My Account', 'ultimate-member' ),
'title' => esc_html__( 'My Account', 'ultimate-member' ),
'url' => um_get_core_page( 'account' ),
);
$actions['um-logout'] = array(
'title' => __( 'Logout', 'ultimate-member' ),
'title' => esc_html__( 'Logout', 'ultimate-member' ),
'url' => um_get_core_page( 'logout' ),
);
$actions = apply_filters( 'um_member_directory_my_user_card_actions', $actions, $user_id );
}
return $actions;
}
......@@ -2450,7 +2471,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$dropdown_actions = $this->build_user_actions_list( $user_id );
$actions = array();
$actions = array();
$can_edit = UM()->roles()->um_current_user_can( 'edit', $user_id );
// Replace hook 'um_members_just_after_name'
......@@ -2464,21 +2485,21 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$hook_after_user_name = ob_get_clean();
$data_array = array(
'card_anchor' => substr( md5( $user_id ), 10, 5 ),
'id' => $user_id,
'role' => um_user( 'role' ),
'account_status' => um_user( 'account_status' ),
'account_status_name' => um_user( 'account_status_name' ),
'cover_photo' => um_user( 'cover_photo', $this->cover_size ),
'display_name' => um_user( 'display_name' ),
'profile_url' => um_user_profile_url(),
'can_edit' => $can_edit,
'edit_profile_url' => um_edit_profile_url(),
'avatar' => get_avatar( $user_id, $this->avatar_size ),
'display_name_html' => um_user( 'display_name', 'html' ),
'dropdown_actions' => $dropdown_actions,
'hook_just_after_name' => preg_replace( '/^\s+/im', '', $hook_just_after_name ),
'hook_after_user_name' => preg_replace( '/^\s+/im', '', $hook_after_user_name ),
'card_anchor' => esc_html( substr( md5( $user_id ), 10, 5 ) ),
'id' => absint( $user_id ),
'role' => esc_html( um_user( 'role' ) ),
'account_status' => esc_html( um_user( 'account_status' ) ),
'account_status_name' => esc_html( um_user( 'account_status_name' ) ),
'cover_photo' => wp_kses( um_user( 'cover_photo', $this->cover_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name' => esc_html( um_user( 'display_name' ) ),
'profile_url' => esc_url( um_user_profile_url() ),
'can_edit' => (bool) $can_edit,
'edit_profile_url' => esc_url( um_edit_profile_url() ),
'avatar' => wp_kses( get_avatar( $user_id, $this->avatar_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name_html' => wp_kses( um_user( 'display_name', 'html' ), UM()->get_allowed_html( 'templates' ) ),
'dropdown_actions' => $dropdown_actions,
'hook_just_after_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_just_after_name ), UM()->get_allowed_html( 'templates' ) ),
'hook_after_user_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_after_user_name ), UM()->get_allowed_html( 'templates' ) ),
);
if ( ! empty( $directory_data['show_tagline'] ) ) {
......@@ -2498,7 +2519,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
continue;
}
$data_array[ $key ] = $value;
$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
}
}
}
......@@ -2529,8 +2550,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
) );
}
$data_array[ "label_{$key}" ] = __( $label, 'ultimate-member' );
$data_array[ $key ] = $value;
$data_array[ "label_{$key}" ] = esc_html__( $label, 'ultimate-member' );
$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
}
}
}
......@@ -2540,7 +2561,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
UM()->fields()->show_social_urls();
$social_urls = ob_get_clean();
$data_array['social_urls'] = $social_urls;
$data_array['social_urls'] = wp_kses( $social_urls, UM()->get_allowed_html( 'templates' ) );
}
}
......@@ -2629,14 +2650,13 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
// Prepare default user query values
$this->query_args = array(
'fields' => 'ids',
'number' => 0,
'meta_query' => array(
'relation' => 'AND'
'fields' => 'ids',
'number' => 0,
'meta_query' => array(
'relation' => 'AND',
),
);
// handle different restrictions
$this->restriction_options();
......@@ -2770,7 +2790,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$this->cover_size = apply_filters( 'um_member_directory_cover_image_size', $this->cover_size, $directory_data );
$avatar_size = UM()->options()->get( 'profile_photosize' );
$avatar_size = UM()->options()->get( 'profile_photosize' );
$this->avatar_size = str_replace( 'px', '', $avatar_size );
$this->avatar_size = apply_filters( 'um_member_directory_avatar_image_size', $this->avatar_size, $directory_data );
......
<?php
namespace um\core;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Options' ) ) {
......@@ -125,6 +126,18 @@ if ( ! class_exists( 'um\core\Options' ) ) {
return $settings_defaults[ $option_id ];
}
/**
* Get predefined page option key
*
* @since 2.8.3
*
* @param string $slug
*
* @return string
*/
public function get_predefined_page_option_key( $slug ) {
return apply_filters( 'um_predefined_page_option_key', "core_{$slug}" );
}
/**
* Get core page ID
......
......@@ -38,20 +38,25 @@ if ( ! class_exists( 'um\core\Password' ) ) {
*
* @return bool|string
*/
function reset_url() {
public function reset_url() {
static $reset_key = null;
$user_id = um_user( 'ID' );
delete_option( "um_cache_userdata_{$user_id}" );
//new reset password key via WordPress native field. It maybe already exists here but generated twice to make sure that emailed with a proper and fresh hash
// New reset password key via WordPress native field. It maybe already exists here but generated twice to make sure that emailed with a proper and fresh hash.
// But doing that only once in 1 request using static variable. Different email placeholders can use reset_url() and we have to use 1 time generated to avoid invalid keys.
$user_data = get_userdata( $user_id );
$key = UM()->user()->maybe_generate_password_reset_key( $user_data );
if ( empty( $reset_key ) ) {
$reset_key = UM()->user()->maybe_generate_password_reset_key( $user_data );
}
// this link looks like WordPress native link e.g. wp-login.php?action=rp&key={hash}&login={user_login}
$url = add_query_arg(
array(
'act' => 'reset_password',
'hash' => $key,
'hash' => $reset_key,
'login' => $user_data->user_login,
),
um_get_core_page( 'password-reset' )
......@@ -155,6 +160,7 @@ if ( ! class_exists( 'um\core\Password' ) ) {
if ( false !== $this->change_password ) {
// then COOKIE are valid then get data from them and populate hidden fields for the password reset form
$args['rp_mode'] = 'pw_change';
$args['template'] = 'password-change';
$args['rp_key'] = '';
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
......@@ -163,6 +169,14 @@ if ( ! class_exists( 'um\core\Password' ) ) {
$args['login'] = $rp_login;
$args['rp_key'] = $rp_key;
$rp_user_obj = get_user_by( 'login', $rp_login );
if ( false !== $rp_user_obj ) {
$set_password_required = get_user_meta( $rp_user_obj->ID, 'um_set_password_required', true );
if ( ! empty( $set_password_required ) ) {
$args['rp_mode'] = 'pw_set';
}
}
}
}
......@@ -481,6 +495,7 @@ if ( ! class_exists( 'um\core\Password' ) ) {
if ( isset( $args['user_password'] ) && empty( $args['user_password'] ) ) {
UM()->form()->add_error( 'user_password', __( 'You must enter a new password', 'ultimate-member' ) );
return;
}
if ( isset( $args['user_password'] ) ) {
......@@ -599,6 +614,11 @@ if ( ! class_exists( 'um\core\Password' ) ) {
}
$this->setcookie( $rp_cookie, false );
$set_password_required = get_user_meta( $user->ID, 'um_set_password_required', true );
if ( ! empty( $set_password_required ) ) {
delete_user_meta( $user->ID, 'um_set_password_required' );
}
/**
* UM hook
*
......
......@@ -125,8 +125,14 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
wp_die( __( 'This activation link is expired.', 'ultimate-member' ) );
}
$redirect = um_get_core_page( 'login', 'account_active' );
$set_password_required = get_user_meta( $user_id, 'um_set_password_required', true );
um_fetch_user( $user_id );
UM()->user()->approve();
if ( ! empty( $set_password_required ) ) {
$redirect = um_user( 'password_reset_link' );
}
um_reset_user();
$user_role = UM()->roles()->get_priority_user_role( $user_id );
......@@ -167,7 +173,9 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
*/
do_action( 'um_after_email_confirmation', $user_id );
$redirect = empty( $user_role_data['url_email_activate'] ) ? um_get_core_page( 'login', 'account_active' ) : trim( $user_role_data['url_email_activate'] ); // Role setting "URL redirect after e-mail activation"
if ( empty( $set_password_required ) ) {
$redirect = empty( $user_role_data['url_email_activate'] ) ? um_get_core_page( 'login', 'account_active' ) : trim( $user_role_data['url_email_activate'] ); // Role setting "URL redirect after email activation"
}
$redirect = apply_filters( 'um_after_email_confirmation_redirect', $redirect, $user_id, $login );
exit( wp_redirect( $redirect ) );
......
......@@ -162,6 +162,13 @@ if ( ! class_exists( 'um\core\Rewrite' ) ) {
if ( empty( $custom_meta ) ) {
// Set default permalink base if custom meta is empty.
$permalink_base = 'user_login';
} else {
// Ignore username slug if custom meta slug exists.
$user_id = username_exists( um_queried_user() );
$custom_permalink = get_user_meta( $user_id, 'um_user_profile_url_slug_' . $permalink_base, true );
if ( ! empty( $custom_permalink ) && um_queried_user() !== $custom_permalink ) {
return false;
}
}
}
......
......@@ -191,27 +191,7 @@ KEY meta_value_indx (um_value(191))
$content = '[ultimatemember form_id="' . $setup_shortcodes[ $slug ] . '"]';
}
/**
* Filters Ultimate Member predefined pages content when set up the predefined page.
*
* @param {string} $content Predefined page content.
* @param {string} $slug Predefined page slug (key).
*
* @return {string} Predefined page content.
*
* @since 2.1.0
* @hook um_setup_predefined_page_content
*
* @example <caption>Set Ultimate Member predefined pages content with key = 'my_page_key'.</caption>
* function my_um_setup_predefined_page_content( $content, $slug ) {
* // your code here
* if ( 'my_page_key' === $slug ) {
* $content = __( 'My Page content', 'my-translate-key' );
* }
* return $pages;
* }
* add_filter( 'um_setup_predefined_page_content', 'my_um_setup_predefined_page_content' );
*/
/** This filter is documented in includes/core/class-setup.php */
$content = apply_filters( 'um_setup_predefined_page_content', $content, $slug );
$user_page = array(
......@@ -243,6 +223,72 @@ KEY meta_value_indx (um_value(191))
UM()->rewrite()->reset_rules();
}
public function predefined_page( $slug, $with_rewrite = true ) {
$page_exists = UM()->query()->find_post_id( 'page', '_um_core', $slug );
if ( $page_exists ) {
return;
}
$predefined_pages = UM()->config()->get( 'predefined_pages' );
if ( empty( $predefined_pages ) || ! array_key_exists( $slug, $predefined_pages ) ) {
return;
}
$data = $predefined_pages[ $slug ];
if ( empty( $data['title'] ) ) {
return;
}
$content = ! empty( $data['content'] ) ? $data['content'] : '';
/**
* Filters Ultimate Member predefined pages content when set up the predefined page.
*
* @param {string} $content Predefined page content.
* @param {string} $slug Predefined page slug (key).
*
* @return {string} Predefined page content.
*
* @since 2.1.0
* @hook um_setup_predefined_page_content
*
* @example <caption>Set Ultimate Member predefined pages content with key = 'my_page_key'.</caption>
* function my_um_setup_predefined_page_content( $content, $slug ) {
* // your code here
* if ( 'my_page_key' === $slug ) {
* $content = __( 'My Page content', 'my-translate-key' );
* }
* return $pages;
* }
* add_filter( 'um_setup_predefined_page_content', 'my_um_setup_predefined_page_content' );
*/
$content = apply_filters( 'um_setup_predefined_page_content', $content, $slug );
$user_page = array(
'post_title' => $data['title'],
'post_content' => $content,
'post_name' => $slug,
'post_type' => 'page',
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'comment_status' => 'closed',
);
$post_id = wp_insert_post( $user_page );
if ( empty( $post_id ) || is_wp_error( $post_id ) ) {
return;
}
update_post_meta( $post_id, '_um_core', $slug );
UM()->options()->update( UM()->options()->get_predefined_page_option_key( $slug ), $post_id );
if ( $with_rewrite ) {
// Reset rewrite rules after page creation and option upgrade.
UM()->rewrite()->reset_rules();
}
}
/**
* Set default UM settings.
*/
......
......@@ -74,6 +74,8 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
add_shortcode( 'um_show_content', array( &$this, 'um_shortcode_show_content_for_role' ) );
add_shortcode( 'ultimatemember_searchform', array( &$this, 'ultimatemember_searchform' ) );
add_shortcode( 'um_author_profile_link', array( &$this, 'author_profile_link' ) );
add_filter( 'body_class', array( &$this, 'body_class' ), 0 );
add_filter( 'um_shortcode_args_filter', array( &$this, 'display_logout_form' ), 99 );
......@@ -458,6 +460,63 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
return $output;
}
/**
* Display post author's link to UM User Profile.
*
* @since 2.8.2
*
* Example 1: [um_author_profile_link] current post author User Profile URL
* Example 2: [um_author_profile_link title="User profile" user_id="29"]
* Example 3: [um_author_profile_link title="User profile" user_id="29"]Visit Author Profile[/um_author_profile_link]
* Example 4: [um_author_profile_link raw="1"] for result like http://localhost:8000/user/janedoe/
*
* @param array $attr {
* Attributes of the shortcode.
*
* @type string $class A link class.
* @type string $title A link text.
* @type int $user_id User ID. Author ID if empty.
* @type bool $raw Get raw URL or link layout. `false` by default.
* }
* @param string $content
* @return string Profile link HTML or profile link URL if the link text is empty.
*/
public function author_profile_link( $attr = array(), $content = '' ) {
$default_user_id = 0;
if ( is_singular() ) {
$default_user_id = get_post()->post_author;
} elseif ( is_author() ) {
$default_user_id = get_the_author_meta( 'ID' );
}
$defaults_atts = array(
'class' => 'um-link um-profile-link',
'title' => __( 'Go to profile', 'ultimate-member' ),
'user_id' => $default_user_id,
'raw' => false,
);
$atts = shortcode_atts( $defaults_atts, $attr, 'um_author_profile_link' );
if ( empty( $atts['user_id'] ) ) {
return '';
}
$user_id = absint( $atts['user_id'] );
$url = um_user_profile_url( $user_id );
if ( empty( $url ) ) {
return '';
}
if ( ! empty( $atts['raw'] ) ) {
return $url;
}
$title = ! empty( $atts['title'] ) ? $atts['title'] : __( 'Go to profile', 'ultimate-member' );
$link_html = empty( $content ) ? $title : $content;
return '<a class="' . esc_attr( $atts['class'] ) . '" href="' . esc_url( $url ) . '" title="' . esc_attr( $title ) . '">' . wp_kses_post( $link_html ) . '</a>';
}
/**
* @param array $args
......
......@@ -968,28 +968,29 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
/**
* Profile photo image process
*
* @param array $response
* @param array $response
* @param string $image_path
* @param string $src
* @param string $key
* @param integer $user_id
* @param int $user_id
* @param string $coord
* @param array $crop
* @param array $crop
*
* @since 2.0.22
*
* @return array
*/
public function profile_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) {
$sizes = UM()->options()->get( 'photo_thumb_sizes' );
$sizes = UM()->options()->get( 'photo_thumb_sizes' );
$quality = UM()->options()->get( 'image_compression' );
$image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor
$temp_image_path = $image_path;
//refresh image_path to make temporary image permanently after upload
$image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . pathinfo( $image_path, PATHINFO_EXTENSION );
// Refresh image_path to make temporary image permanently after upload
$photo_ext = pathinfo( $image_path, PATHINFO_EXTENSION );
$image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . $photo_ext;
if ( ! is_wp_error( $image ) ) {
$src_x = $crop[0];
......@@ -1004,12 +1005,16 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
$image->resize( $max_w, $src_h );
}
$image->save( $image_path );
$save_result = $image->save( $image_path );
if ( is_wp_error( $save_result ) ) {
// translators: %s is the file src.
wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
}
$image->set_quality( $quality );
$sizes_array = array();
foreach ( $sizes as $size ) {
$sizes_array[] = array( 'width' => $size );
}
......@@ -1020,50 +1025,49 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
unlink( $temp_image_path );
$src = str_replace( '/' . $key . '_temp.', '/' . $key . '.', $src );
$basename = $key . '_temp.' . $photo_ext;
$src = str_replace( '/' . $basename, '/' . $save_result['file'], $src );
$response['image']['source_url'] = $src;
$response['image']['source_path'] = $image_path;
$response['image']['filename'] = wp_basename( $image_path );
$response['image']['source_url'] = $src;
$response['image']['source_path'] = $save_result['path'];
$response['image']['filename'] = $save_result['file'];
update_user_meta( $this->user_id, $key, wp_basename( wp_basename( $image_path ) ) );
update_user_meta( $this->user_id, $key, $save_result['file'] );
delete_user_meta( $this->user_id, "{$key}_metadata_temp" );
} else {
wp_send_json_error( esc_js( __( "Unable to crop image file: {$src}", 'ultimate-member' ) ) );
// translators: %s is the file src.
wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
}
return $response;
}
/**
* Cover photo image process
*
* @param string $src
* @param integer $user_id
* @param int $user_id
* @param string $coord
* @param array $crop
* @param array $response
* @param array $crop
* @param array $response
*
* @since 2.0.22
*
* @return array
*/
public function cover_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) {
$sizes = UM()->options()->get( 'cover_thumb_sizes' );
$sizes = UM()->options()->get( 'cover_thumb_sizes' );
$quality = UM()->options()->get( 'image_compression' );
$image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor
$temp_image_path = $image_path;
//refresh image_path to make temporary image permanently after upload
$image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . pathinfo( $image_path, PATHINFO_EXTENSION );
// Refresh image_path to make temporary image permanently after upload
$photo_ext = pathinfo( $image_path, PATHINFO_EXTENSION );
$image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . $photo_ext;
if ( ! is_wp_error( $image ) ) {
$src_x = $crop[0];
$src_y = $crop[1];
$src_w = $crop[2];
......@@ -1076,7 +1080,12 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
$image->resize( $max_w, $src_h );
}
$image->save( $image_path );
$save_result = $image->save( $image_path );
if ( is_wp_error( $save_result ) ) {
// translators: %s is the file src.
wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
}
$image->set_quality( $quality );
......@@ -1090,7 +1099,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
// change filenames of resized images
foreach ( $resize as $row ) {
$new_filename = str_replace( "x{$row['height']}" , '', $row['file'] );
$new_filename = str_replace( "x{$row['height']}", '', $row['file'] );
$old_filename = $row['file'];
rename( dirname( $image_path ) . DIRECTORY_SEPARATOR . $old_filename, dirname( $image_path ) . DIRECTORY_SEPARATOR . $new_filename );
......@@ -1098,16 +1107,18 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
unlink( $temp_image_path );
$src = str_replace( '/' . $key . '_temp.', '/' . $key . '.', $src );
$basename = $key . '_temp.' . $photo_ext;
$src = str_replace( '/' . $basename, '/' . $save_result['file'], $src );
$response['image']['source_url'] = $src;
$response['image']['source_path'] = $image_path;
$response['image']['filename'] = wp_basename( $image_path );
$response['image']['source_url'] = $src;
$response['image']['source_path'] = $save_result['path'];
$response['image']['filename'] = $save_result['file'];
update_user_meta( $this->user_id, $key, wp_basename( wp_basename( $image_path ) ) );
update_user_meta( $this->user_id, $key, $save_result['file'] );
delete_user_meta( $this->user_id, "{$key}_metadata_temp" );
} else {
wp_send_json_error( esc_js( __( "Unable to crop image file: {$src}", 'ultimate-member' ) ) );
// translators: %s is the file src.
wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
}
return $response;
......@@ -1195,15 +1206,15 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
$response = array(
'image' => array(
'source_url' => $src,
'source_path' => $image_path,
'filename' => wp_basename( $image_path ),
'source_url' => $src,
'source_path' => $image_path,
'filename' => wp_basename( $image_path ),
),
);
$response = apply_filters( "um_upload_image_process__{$key}", $response, $image_path, $src, $key, $user_id, $coord, $crop );
if ( ! in_array( $key, array( 'profile_photo', 'cover_photo' ) ) ) {
if ( ! in_array( $key, array( 'profile_photo', 'cover_photo' ), true ) ) {
$response = apply_filters( 'um_upload_stream_image_process', $response, $image_path, $src, $key, $user_id, $coord, $crop );
}
......
......@@ -1301,7 +1301,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
}
if ( $this->usermeta['account_status'][0] == 'awaiting_email_confirmation' ) {
$this->usermeta['account_status_name'][0] = __( 'Awaiting E-mail Confirmation', 'ultimate-member' );
$this->usermeta['account_status_name'][0] = __( 'Awaiting Email Confirmation', 'ultimate-member' );
}
if ( $this->usermeta['account_status'][0] == 'awaiting_admin_review' ) {
......@@ -1607,7 +1607,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
$expiry_time = UM()->options()->get( 'activation_link_expiry_time' );
if ( ! empty( $expiry_time ) && is_numeric( $expiry_time ) ) {
$this->profile['account_secret_hash_expiry'] = time() + $expiry_time;
$this->profile['account_secret_hash_expiry'] = time() + $expiry_time * DAY_IN_SECONDS;
$this->update_usermeta_info( 'account_secret_hash_expiry' );
}
......@@ -1676,7 +1676,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
/**
* This method approves a user membership and sends them an optional welcome/approval e-mail.
* This method approves a user membership and sends them an optional welcome/approval email.
*
* @usage <?php UM()->user()->approve(); ?>
*
......@@ -1690,7 +1690,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
?>
*
*/
function approve( $repeat = true ) {
public function approve( $repeat = true ) {
$user_id = um_user( 'ID' );
if ( ! $repeat ) {
......@@ -1702,7 +1702,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
delete_option( "um_cache_userdata_{$user_id}" );
if ( um_user( 'account_status' ) == 'awaiting_admin_review' ) {
if ( 'awaiting_admin_review' === um_user( 'account_status' ) ) {
$userdata = get_userdata( $user_id );
$this->maybe_generate_password_reset_key( $userdata );
......@@ -1758,7 +1758,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
/**
* This method puts a user under manual review by administrator and sends them an optional e-mail.
* This method puts a user under manual review by administrator and sends them an optional email.
*
* @usage <?php UM()->user()->pending(); ?>
*
......@@ -1784,7 +1784,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
/**
* This method rejects a user membership and sends them an optional e-mail.
* This method rejects a user membership and sends them an optional email.
*
* @usage <?php UM()->user()->reject(); ?>
*
......@@ -1811,7 +1811,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
/**
* This method deactivates a user membership and sends them an optional e-mail.
* This method deactivates a user membership and sends them an optional email.
*
* @usage <?php UM()->user()->deactivate(); ?>
*
......
......@@ -157,15 +157,15 @@ function um_submit_account_errors_hook( $args ) {
if ( isset( $args['user_email'] ) ) {
if ( strlen( trim( $args['user_email'] ) ) === 0 ) {
UM()->form()->add_error( 'user_email', __( 'You must provide your e-mail', 'ultimate-member' ) );
UM()->form()->add_error( 'user_email', __( 'You must provide your email', 'ultimate-member' ) );
}
if ( ! is_email( $args['user_email'] ) ) {
UM()->form()->add_error( 'user_email', __( 'Please provide a valid e-mail', 'ultimate-member' ) );
UM()->form()->add_error( 'user_email', __( 'Please provide a valid email', 'ultimate-member' ) );
}
if ( email_exists( $args['user_email'] ) && email_exists( $args['user_email'] ) !== get_current_user_id() ) {
UM()->form()->add_error( 'user_email', __( 'Please provide a valid e-mail', 'ultimate-member' ) );
UM()->form()->add_error( 'user_email', __( 'Please provide a valid email', 'ultimate-member' ) );
}
}
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.