0cadafda by Jeff Balicki

Ultimate Member update

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent 7c037e3f
Showing 128 changed files with 1290 additions and 1444 deletions
1 # This file is for unifying the coding style for different editors and IDEs
2 # editorconfig.org
3
4 # WordPress Coding Standards
5 # https://make.wordpress.org/core/handbook/coding-standards/
6
7 root = true
8
9 [*]
10 charset = utf-8
11 end_of_line = lf
12 insert_final_newline = true
13 trim_trailing_whitespace = true
14 indent_style = tab
15
16 [{.jshintrc,*.json,*.yml,*.sass}]
17 indent_style = space
18 indent_size = 2
19
20 [{*.txt,wp-config-sample.php}]
21 end_of_line = crlf
...\ No newline at end of file ...\ No newline at end of file
1 # Auto detect text files and perform LF normalization
2 * text=auto
3
4 # Custom for Visual Studio
5 *.cs diff=csharp
6 *.sln merge=union
7 *.csproj merge=union
8 *.vbproj merge=union
9 *.fsproj merge=union
10 *.dbproj merge=union
11
12 # Standard to msysgit
13 *.doc diff=astextplain
14 *.DOC diff=astextplain
15 *.docx diff=astextplain
16 *.DOCX diff=astextplain
17 *.dot diff=astextplain
18 *.DOT diff=astextplain
19 *.pdf diff=astextplain
20 *.PDF diff=astextplain
21 *.rtf diff=astextplain
22 *.RTF diff=astextplain
1 ---
2 name: "\U0001F46E‍♂️Security issue"
3 about: Please report security issues *only* via https://ultimatemember.com/feedback/
4 title: ''
5 labels: ''
6 assignees: ''
7
8 ---
9
10 For security reasons, please report all security issues via https://ultimatemember.com/feedback/.
11
12 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 ...\ No newline at end of file
1 ---
2 name: "\U0001F41E Bug report"
3 about: Report a bug if something isn't working as expected in the core Ultimate Member
4 plugin.
5 title: ''
6 labels: ''
7 assignees: ''
8
9 ---
10
11 **Expected behavior**
12 A clear and concise description of what you expected to happen.
13
14 **Isolating the problem (mark completed items with an [x]):**
15 - [ ] I have deactivated other plugins and confirmed this bug occurs when only Ultimate Member plugin is active.
16 - [ ] This bug happens with a default WordPress theme active, or [UM Theme](https://ultimatemember.com/theme/).
17 - [ ] I can reproduce this bug consistently using the steps above.
18
19 **Describe the bug**
20 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.
21
22 **To Reproduce**
23 Steps to reproduce the behavior:
24 1. Go to '...'
25 2. Click on '....'
26 3. Scroll down to '....'
27 4. See error
28
29 **Expected behavior**
30 A clear and concise description of what you expected to happen.
31
32 **Screenshots**
33 If applicable, add screenshots to help explain your problem.
34
35 **Do you use UM extensions?**
36 - [ ] Followers
37 - [ ] ForumWP
38 - [ ] Friends
39 - [ ] Google reCAPTCHA
40 - [ ] Groups
41 - [ ] Instagram
42 - [ ] MailChimp
43 - [ ] myCRED
44 - [ ] Notices
45 - [ ] Online Users
46 - [ ] Private Content
47 - [ ] Private Messages
48 - [ ] Profile Completeness
49 - [ ] Real-time Notifications
50 - [ ] Social Activity
51 - [ ] Social Login
52 - [ ] Terms & Conditions
53 - [ ] Unsplash
54 - [ ] User Bookmarks
55 - [ ] User Photos
56 - [ ] User Reviews
57 - [ ] User Tags
58 - [ ] Verified Users
59 - [ ] WooCommerce
60
61
62 **WordPress Environment**
63 <details>
64 ```
65 Copy and paste the install info from ** Ultimate Member > Settings > Install Info ** in WordPress admin.
66 ```
67 </details>
...\ No newline at end of file ...\ No newline at end of file
1 ---
2 name: " New Enhancement"
3 about: If you have an idea to improve an existing feature in core or need something
4 for development (such as a new hook) please let us know or submit a Pull Request!
5 title: ''
6 labels: ''
7 assignees: ''
8
9 ---
10
11 **Is your feature request related to a problem? Please describe.**
12 A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
13
14 **Describe the solution you'd like**
15 A clear and concise description of what you want to happen.
16
17 **Describe alternatives you've considered**
18 A clear and concise description of any alternative solutions or features you've considered.
19
20 **Additional context**
21 Add any other context or screenshots about the feature request here.
...\ No newline at end of file ...\ No newline at end of file
1 ---
2 name: "\U0001F680 Feature request"
3 about: "Suggest a new feature \U0001F389 We'll consider building it if it receives
4 sufficient interest! \U0001F44D"
5 title: ''
6 labels: ''
7 assignees: ''
8
9 ---
10
11 **Is your feature request related to a problem? Please describe.**
12 A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
13
14 **Describe the solution you'd like**
15 A clear and concise description of what you want to happen.
16
17 **Describe alternatives you've considered**
18 A clear and concise description of any alternative solutions or features you've considered.
19
20 **Additional context**
21 Add any other context or screenshots about the feature request here.
...\ No newline at end of file ...\ No newline at end of file
1 ---
2 name: " Support Question"
3 about: "If you have a question \U0001F4AC please see our docs or use our forums & support page"
4 title: ''
5 labels: ''
6 assignees: ''
7
8 ---
9
10 We don't offer technical support on GitHub so we recommend using the following:
11
12 **Reading our documentation**
13 Usage docs can be found here: https://docs.ultimatemember.com
14
15 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/
16
17 **Technical support for premium extensions or if you're a UltimateMember.com customer**
18 Please submit a ticket via the support page
19 https://ultimatemember.com/support/ticket/
20
21 **General questions**
22 - WordPress.org Forums: https://wordpress.org/support/plugin/ultimate-member/
1 # Welcome to the Ultimate Member Plugin Hook Documentation
2
3 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.
4
5 For more information about using Ultimate Member with WordPress, please see the [Ultimate Member Docs](https://docs.ultimatemember.com/).
6
7 To report an issue with Ultimate Member, please visit the [Support forum](https://wordpress.org/support/plugin/ultimate-member/).
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title><?js= title ?> - Ultimate Member Hook Docs</title>
6
7 <script src="scripts/prettify/prettify.js"> </script>
8 <script src="scripts/prettify/lang-css.js"> </script>
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14
15 <link href="https://fonts.googleapis.com/css?family=IBM+Plex+Mono|IBM+Plex+Sans:300,400|Playfair+Display:900&display=swap" rel="stylesheet">
16 <link type="text/css" rel="stylesheet" href="styles-um.css">
17 </head>
18
19 <body<?js if (title === 'Home') { ?> class="home"<?js } ?>>
20
21 <div id="main">
22
23 <?js if (title !== 'Home') { ?>
24 <h1 class="page-title"><?js= title ?></h1>
25 <?js } ?>
26
27 <?js= content ?>
28
29 <footer>
30 <a href="https://wordpress.org/plugins/ultimate-member/">Ultimate Member Plugin</a> &bull;
31 <a href="https://docs.ultimatemember.com/">Official Docs</a>
32 </footer>
33
34
35 </div>
36
37 <nav>
38 <?js= this.nav ?>
39 </nav>
40
41 <br class="clear">
42
43 <script> prettyPrint(); </script>
44 <script src="scripts/linenumber.js"> </script>
45 </body>
46 </html>
1 body {
2 background: #fefefe;
3 color: #232323;
4 font-family: 'IBM Plex Sans', sans-serif;
5 font-size: 1.3rem;
6 font-weight: 300;
7 }
8
9 h1, h2, h3 {
10 line-height: 1.2;
11 font-family: 'Playfair Display', sans-serif;
12 font-weight: 900;
13 letter-spacing: -.01em;
14 }
15
16 h1.page-title {
17 font-size: 42px;
18 margin-top: .5em;
19 }
20
21 nav ul {
22 font-size: 1.2rem;
23 }
24
25 nav li a {
26 background-image: none;
27 }
28
29 nav li a:hover {
30 text-decoration: underline;
31 }
32
33 code, pre,
34 nav ul a, nav ul a:visited, nav ul a:active,
35 .name, .signature,
36 .params .name, .props .name,
37 .name code {
38 font-family: 'IBM Plex Mono', monospace;
39 }
40
41 article h1 {
42 margin: 12px 0 32px;
43 }
44
45 a {
46 background-image: linear-gradient(transparent calc(100% - 7px), #f2dede 0),
47 linear-gradient(transparent calc(100% - 7px), #cef8f7 0);
48 background-position: 0 0;
49 background-repeat: no-repeat;
50 background-size: 0 100%, 100% 100%;
51 color: #232323;
52 text-decoration: none;
53 transition: all .1s;
54 }
55
56 a:visited,
57 a:active {
58 color: #232323;
59 }
60
61 a:focus,
62 a:hover {
63 background-size: 100% 100%, 100% 100%;
64 color: #232323;
65 text-decoration: none;
66 }
67
68 a.banner {
69 background-image: none;
70 margin-left: -10px;
71 }
72
73 a.banner img {
74 width: 100%;
75 max-width: 888px;
76 }
77
78 footer {
79 text-align: center;
80 font-size: .8em;
81 font-style: normal;
82 font-weight: 300;
83 }
84
85 .home #main > section:first-of-type,
86 .home nav > h2 {
87 display: none;
88 }
89
90 .prettyprint.source {
91 font-size: 14px;
92 }
93
94 .prettyprint code {
95 font-size: 16px;
96 padding: 2px 10px;
97 line-height: 18px;
98 max-height: 150px;
99 }
1 name: Build Hook Docs
2
3 on:
4 push:
5 branches:
6 - master
7
8 jobs:
9 hookdocs:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v3
13 - uses: actions/setup-node@v3
14 with:
15 node-version: 16
16 - name: npm install, and build docs
17 run: |
18 npm install
19 npm run build:docs
20 - name: Install dependencies
21 run: composer install --prefer-dist --no-progress --no-suggest
22 - name: PhpDocumentor
23 uses: gpupo/actions-phpDocumentor@1.0
24 with:
25 dir: './'
26 - name: Deploy to GH Pages
27 uses: JamesIves/github-pages-deploy-action@v4.3.3
28 with:
29 branch: gh-pages # The branch the action should deploy to.
30 folder: 'docs/' # The folder the action should deploy.
31 token: ${{ secrets.GH_PAT }}
1 name: Ultimate Member - Checking Code quality through PHPCS + WPCS
2
3 on:
4 push:
5 branches:
6 - development/3.0
7
8 jobs:
9 build:
10
11 runs-on: ubuntu-latest
12
13 steps:
14 - uses: actions/checkout@v2
15
16 - name: Install dependencies
17 run: composer install --prefer-dist --no-progress --no-suggest
18
19 - name: Run CS
20 run: vendor/bin/phpcs --standard=phpcs.xml .
1 name: Generate POT file manually
2
3 on: workflow_dispatch
4
5 jobs:
6 WP_Generate_POT_File:
7 runs-on: ubuntu-latest
8 steps:
9 - uses: actions/checkout@v2
10 - name: WordPress .pot File Generator
11 uses: iamdharmesh/action-wordpress-pot-generator@main
12 with:
13 destination_path: './languages'
14 slug: 'ultimate-member'
15 text_domain: 'ultimate-member'
16 env:
17 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 name: Generate POT file
2
3 on:
4 push:
5 branches:
6 - master
7
8 jobs:
9 WP_Generate_POT_File:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v2
13 - name: WordPress .pot File Generator
14 uses: iamdharmesh/action-wordpress-pot-generator@main
15 with:
16 destination_path: './languages'
17 slug: 'ultimate-member'
18 text_domain: 'ultimate-member'
19 env:
20 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 #################
2 ## Eclipse
3 #################
4
5 *.pydevproject
6 .project
7 .metadata
8 bin/
9 tmp/
10 *.tmp
11 *.bak
12 *.swp
13 *~.nib
14 local.properties
15 .classpath
16 .ideanpg
17 .settings/
18 .loadpath
19
20 # External tool builders
21 .externalToolBuilders/
22
23 # Locally stored "Eclipse launch configurations"
24 *.launch
25
26 # CDT-specific
27 .cproject
28
29 # PDT-specific
30 .buildpath
31
32
33 #################
34 ## Visual Studio
35 #################
36
37 ## Ignore Visual Studio temporary files, build results, and
38 ## files generated by popular Visual Studio add-ons.
39
40 # User-specific files
41 *.suo
42 *.user
43 *.sln.docstates
44
45 # Build results
46
47 [Dd]ebug/
48 [Rr]elease/
49 x64/
50 [Bb]in/
51 [Oo]bj/
52
53 # MSTest test Results
54 [Tt]est[Rr]esult*/
55 [Bb]uild[Ll]og.*
56
57 *_i.c
58 *_p.c
59 *.ilk
60 *.meta
61 *.obj
62 *.pch
63 *.pdb
64 *.pgc
65 *.pgd
66 *.rsp
67 *.sbr
68 *.tlb
69 *.tli
70 *.tlh
71 *.tmp
72 *.tmp_proj
73 *.log
74 *.vspscc
75 *.vssscc
76 .builds
77 *.pidb
78 *.log
79 *.scc
80
81 # Visual C++ cache files
82 ipch/
83 *.aps
84 *.ncb
85 *.opensdf
86 *.sdf
87 *.cachefile
88
89 # Visual Studio profiler
90 *.psess
91 *.vsp
92 *.vspx
93
94 # Guidance Automation Toolkit
95 *.gpState
96
97 # ReSharper is a .NET coding add-in
98 _ReSharper*/
99 *.[Rr]e[Ss]harper
100
101 # TeamCity is a build add-in
102 _TeamCity*
103
104 # DotCover is a Code Coverage Tool
105 *.dotCover
106
107 # NCrunch
108 *.ncrunch*
109 .*crunch*.local.xml
110
111 # Installshield output folder
112 [Ee]xpress/
113
114 # DocProject is a documentation generator add-in
115 DocProject/buildhelp/
116 DocProject/Help/*.HxT
117 DocProject/Help/*.HxC
118 DocProject/Help/*.hhc
119 DocProject/Help/*.hhk
120 DocProject/Help/*.hhp
121 DocProject/Help/Html2
122 DocProject/Help/html
123
124 # Click-Once directory
125 publish/
126
127 # Publish Web Output
128 *.Publish.xml
129 *.pubxml
130 *.publishproj
131
132 # NuGet Packages Directory
133 ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
134 #packages/
135
136 # Windows Azure Build Output
137 csx
138 *.build.csdef
139
140 # Windows Store app package directory
141 AppPackages/
142
143 # Others
144 sql/
145 *.Cache
146 ClientBin/
147 [Ss]tyle[Cc]op.*
148 ~$*
149 *~
150 *.dbmdl
151 *.[Pp]ublish.xml
152 *.pfx
153 *.publishsettings
154
155 # RIA/Silverlight projects
156 Generated_Code/
157
158 # Backup & report files from converting an old project file to a newer
159 # Visual Studio version. Backup files are not needed, because we have git ;-)
160 _UpgradeReport_Files/
161 Backup*/
162 UpgradeLog*.XML
163 UpgradeLog*.htm
164
165 # SQL Server files
166 App_Data/*.mdf
167 App_Data/*.ldf
168
169 #############
170 ## Windows detritus
171 #############
172
173 # Windows image file caches
174 Thumbs.db
175 ehthumbs.db
176
177 # Folder config file
178 Desktop.ini
179
180 # Recycle Bin used on file shares
181 $RECYCLE.BIN/
182
183 # Mac crap
184 .DS_Store
185
186
187 #############
188 ## Python
189 #############
190
191 *.py[cod]
192
193 # Packages
194 *.egg
195 *.egg-info
196 dist/
197 eggs/
198 parts/
199 var/
200 sdist/
201 develop-eggs/
202 .installed.cfg
203
204 # Installer logs
205 pip-log.txt
206
207 # Unit test / coverage reports
208 .coverage
209 .tox
210
211 #Translations
212 *.mo
213
214 #Mr Developer
215 .mr.developer.cfg
216
217 node_modules/
218 assets/vendor/
219 /vendor/
220 package-lock.json
221 .idea/
222 composer.lock
223
224 # exclude Composer installation
225 composer.phar
226 /vendor
227
228 # exclude WP-CLI installation
229 wp-cli.phar
230
231 # exclude generated by phpDocumentor docs
232 /documentor
233
234 #wp-hookdoc generated docs
235 hookdocs
1 {
2 "bitwise": true,
3 "browser": true,
4 "curly": true,
5 "eqeqeq": true,
6 "eqnull": true,
7 "esnext": true,
8 "immed": true,
9 "jquery": true,
10 "latedef": true,
11 "newcap": true,
12 "noarg": true,
13 "node": true,
14 "strict": false,
15 "trailing": true
16 }
1 # Travis CI Configuration File
2
3 # Tell Travis CI we're using PHP
4 language: php
5
6 dist: trusty
7
8 # Setup a global environment and overide as needed
9 env:
10 global:
11 - WP_TRAVISCI=phpunit
12
13 cache:
14 directories:
15 - $HOME/.composer/cache/files
16 - $HOME/.cache/yarn
17
18 # Test main supported versions of PHP against latest WP.
19 php:
20 - 5.6
21 - 7.0
22 - 7.1
23 - 7.2
24 - 7.3
25
26 env:
27 - WP_VERSION=latest WP_MULTISITE=0
28
29 # Next we define our matrix of additional build configurations to test against.
30 # The versions listed above will automatically create our first configuration,
31 # so it doesn't need to be re-defined below.
32
33 # Test WP trunk/master and two latest versions on minimum (5.2).
34 # Test WP latest two versions (4.5, 4.3) on most popular (5.5, 5.6).
35 # Test WP latest stable (4.5) on other supported PHP (5.3, 5.4).
36 # Test WP trunk/master on edge platforms (7.0, PHP nightly).
37
38 # WP_VERSION specifies the tag to use. The way these tests are configured to run
39 # requires at least WordPress 3.8. Specify "master" to test against SVN trunk.
40
41 matrix:
42
43 fast_finish: true
44 include:
45 - name: "Coding standard check"
46 php: 7.2
47 env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
48 - name: "e2e tests"
49 php: 7.2
50 env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
51 addons:
52 chrome: beta
53 apt:
54 packages:
55 - nginx
56 - name: "Unit tests code coverage"
57 php: 7.3
58 env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
59 - name: "Ultimate Member unit tests using WordPress nightly"
60 php: 7.3
61 env: WP_VERSION=nightly WP_MULTISITE=0
62 - php: 7.4snapshot
63 env: WP_VERSION=nightly WP_MULTISITE=0
64 allow_failures:
65 - php: 7.3
66 env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
67 - php: 7.4snapshot
68 env: WP_VERSION=nightly WP_MULTISITE=0
69
70 # whitelist branches for the "push" build check.
71 branches:
72 only:
73 - master
74 #- master-stable
75 #- /^branch-.*$/
76 #- feature/*
77
78 # Clones WordPress and configures our testing environment.
79 before_script:
80 - phpenv config-rm xdebug.ini
81 - export PLUGIN_SLUG=$(basename $(pwd))
82 - source ~/.nvm/nvm.sh
83 - export PATH="$HOME/.composer/vendor/bin:$PATH"
84 - |
85 if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
86 composer global require "phpunit/phpunit=5.7.*"
87 elif [[ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]]; then
88 composer global require "phpunit/phpunit=4.8.*"
89 fi
90 - nvm install 6
91 - nvm use 6
92 - chmod +x ./tests/prepare-wordpress.sh
93 - chmod +x ./tests/run-travis.sh
94 - ./tests/prepare-wordpress.sh
95 ## - mysql -e "set global wait_timeout = 3600;"
96
97 script:
98 - ./tests/run-travis.sh
99
100 sudo: false
101
102 # We need notifications for successful builds
103
104 notifications:
105 webhooks: https://ultimatemember.com/travis.php
106 email:
107 - heychampsupertramp@gmail.com
108 - nsinelnikov.work@gmail.com
109 # Encrypted Slack notification address.
110 #- secure: "WQdTdmYuifSW0hiJGXpQGKystMASC50QvxHlyUL5SM3h5GP8aCgeSsHuXvKPe3dT3Pffhk0dSHBfDtdWFwSHW/upURhg0vs4dm7+nxxvGZiTPzKcuAIjgvCoqWM7teyda/XqFGNSnv+XsT34uoyPhhFgd45T3oS+QQ3aNCruFak="
1 <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/>
2 <h1 align="center">Ultimate Member</h1>
3 </p>
4
5 [![Active Installs](https://img.shields.io/wordpress/plugin/installs/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/installs/ultimate-member?color=7856ff)
6 [![Ratings](https://img.shields.io/wordpress/plugin/rating/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/rating/ultimate-member?color=7856ff)
7 [![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)
8 [![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)
9 [![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)
10 [![Downloads](https://img.shields.io/wordpress/plugin/dt/ultimate-member?color=7856ff)](https://img.shields.io/wordpress/plugin/dt/ultimate-member?color=7856ff)
11 [![Build Status](https://img.shields.io/travis/ultimatemember/ultimatemember/master?color=7856ff)](https://travis-ci.org/ultimatemember/ultimatemember)
12
13 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.
14
15 If you are not a developer, please use the [Ultimate Member plugin page](https://wordpress.org/plugins/ultimate-member/) on WordPress.org.
16
17 ## Documentation
18
19 - [Ultimate Member Features](https://ultimatemember.com/features/)
20 - [Ultimate Member Documentation](https://docs.ultimatemember.com)
21 - [Ultimate Member Developer Documentation](https://docs.ultimatemember.com/collection/28-for-developers)
22 - [Ultimate Member Extensions Roadmap](https://ultimatemember.com/roadmap/)
23 - [Ultimate Member Extended Features](https://github.com/ultimatemember/Extended)
24
25 ## Reporting Security Issues
26
27 To disclose a security issue to our team, [please submit a report here](https://ultimatemember.com/feedback/).
28
29 ## Support
30
31 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:
32
33 - If you have a problem, you may want to start with the [support page](https://ultimatemember.com/support/).
34 - The [Ultimate Member premium extensions' support portal](https://ultimatemember.com/support/ticket/) for customers who have purchased themes or extensions.
35 - [Our community forum on wp.org](https://wordpress.org/support/plugin/ultimate-member/) which is available for all Ultimate Member users.
36
37 Support requests in issues on this repository will be closed on sight.
38
39 ## License
40
41 GNU Version 2 or Any Later Version
42
43 ## Releases
44
45 ### 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
46
47 [Official Release Version: 2.8.2](https://github.com/ultimatemember/ultimatemember/releases/tag/2.8.2).
48
49 ## Changelog
50
51 [ From v1.0.0 to latest version ](https://wordpress.org/plugins/ultimate-member/changelog/).
1 .um-form-table .um-forms-line[data-conditional] { 1 .um-form-table .um-forms-line[data-conditional] {
2 display: none; } 2 display: none; }
3 3
4 .um-form-table .um-forms-line[data-field_type="checkbox"] td label {
5 font-style: italic; }
6
7 .um-form-table .um-forms-line label .um-req { 4 .um-form-table .um-forms-line label .um-req {
8 color: #a00; 5 color: #a00;
9 margin: 0 0 0 3px; 6 margin: 0 0 0 3px;
...@@ -68,9 +65,12 @@ ...@@ -68,9 +65,12 @@
68 display: block; 65 display: block;
69 margin: 0 0 5px 0; } 66 margin: 0 0 5px 0; }
70 67
71 .um-form-table .description { 68 .um-external-link-icon {
72 font-style: italic; 69 width: 1em;
73 clear: both; } 70 height: 1em;
71 margin: 0;
72 vertical-align: middle;
73 fill: currentcolor; }
74 74
75 .um_admin_fonticon_wrapper { 75 .um_admin_fonticon_wrapper {
76 display: flex; 76 display: flex;
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
7 .#{$prefix}forms-line 7 .#{$prefix}forms-line
8 &[data-conditional] 8 &[data-conditional]
9 display: none 9 display: none
10 &[data-field_type="checkbox"]
11 td
12 label
13 font-style: italic
14 label 10 label
15 .#{$prefix}req 11 .#{$prefix}req
16 color: $required-asterisk 12 color: $required-asterisk
...@@ -88,6 +84,7 @@ ...@@ -88,6 +84,7 @@
88 label 84 label
89 margin: 0 0 5px 0 85 margin: 0 0 5px 0
90 display: inline-block 86 display: inline-block
87 //font-weight: bold
91 88
92 &[data-field_type="icon"] 89 &[data-field_type="icon"]
93 td 90 td
...@@ -95,9 +92,16 @@ ...@@ -95,9 +92,16 @@
95 width: 100% 92 width: 100%
96 display: block 93 display: block
97 margin: 0 0 5px 0 94 margin: 0 0 5px 0
98 .description 95 //.description
99 font-style: italic 96 // font-style: italic
100 clear: both 97 // clear: both
98
99 .um-external-link-icon
100 width: 1em
101 height: 1em
102 margin: 0
103 vertical-align: middle
104 fill: currentcolor
101 105
102 .um_admin_fonticon_wrapper 106 .um_admin_fonticon_wrapper
103 +flex( row, flex-start, center, nowrap ) 107 +flex( row, flex-start, center, nowrap )
......
...@@ -32,3 +32,8 @@ ...@@ -32,3 +32,8 @@
32 float: left; 32 float: left;
33 display: block; 33 display: block;
34 line-height: 37px; } 34 line-height: 37px; }
35
36 #um-admin-form-publish #major-publishing-actions {
37 padding-top: 0;
38 padding-left: 0;
39 padding-right: 0; }
......
1 #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 ...\ No newline at end of file
1 #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 ...\ No newline at end of file
......
...@@ -42,3 +42,10 @@ ...@@ -42,3 +42,10 @@
42 float: left 42 float: left
43 display: block 43 display: block
44 line-height: 37px 44 line-height: 37px
45
46 #um-admin-form-publish
47 #major-publishing-actions
48 padding-top: 0
49 padding-left: 0
50 padding-right: 0
51
......
1 #um-settings-wrap .subsubsub {
2 display: flex;
3 flex-direction: row;
4 justify-content: flex-start;
5 align-items: center;
6 flex-wrap: wrap;
7 margin-left: -3px;
8 margin-right: -3px; }
9 #um-settings-wrap .subsubsub a {
10 margin: 0 3px; }
11
12 .um-settings-section .description { 1 .um-settings-section .description {
13 font-style: italic; } 2 font-style: italic; }
14 3
...@@ -37,8 +26,8 @@ ...@@ -37,8 +26,8 @@
37 width: 25%; } 26 width: 25%; }
38 27
39 .column-configure { 28 .column-configure {
40 width: 60px; 29 width: 10%;
41 text-align: center; } 30 text-align: right; }
42 31
43 th.column-email.column-primary { 32 th.column-email.column-primary {
44 padding-left: 48px; } 33 padding-left: 48px; }
...@@ -46,15 +35,18 @@ th.column-email.column-primary { ...@@ -46,15 +35,18 @@ th.column-email.column-primary {
46 .um-form-table .um-forms-line td { 35 .um-form-table .um-forms-line td {
47 padding-right: 0; } 36 padding-right: 0; }
48 37
49 #um-settings-template-versions .wp-list-table .column-core_version { 38 #um-settings-emails {
39 margin: 15px 0; }
40
41 #um-settings-template-versions {
42 margin: 15px 0; }
43 #um-settings-template-versions .wp-list-table .column-core_version {
50 width: 100px; 44 width: 100px;
51 text-align: center; } 45 text-align: center; }
52 46 #um-settings-template-versions .wp-list-table .column-theme_version {
53 #um-settings-template-versions .wp-list-table .column-theme_version {
54 width: 100px; 47 width: 100px;
55 text-align: center; } 48 text-align: center; }
56 49 #um-settings-template-versions .wp-list-table .column-status {
57 #um-settings-template-versions .wp-list-table .column-status {
58 width: 260px; } 50 width: 260px; }
59 51
60 #um-settings-form { 52 #um-settings-form {
...@@ -64,6 +56,12 @@ th.column-email.column-primary { ...@@ -64,6 +56,12 @@ th.column-email.column-primary {
64 #um-settings-form .subsubsub { 56 #um-settings-form .subsubsub {
65 float: left; 57 float: left;
66 width: 100%; } 58 width: 100%; }
59 #um-settings-form h2.title a.um-back-button {
60 font-weight: normal;
61 font-size: 30px;
62 line-height: 1;
63 text-decoration: none;
64 margin-right: 5px; }
67 65
68 .um-settings-line .multi-checkbox-line { 66 .um-settings-line .multi-checkbox-line {
69 float: left; 67 float: left;
......
1 #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 ...\ No newline at end of file
1 .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 ...\ No newline at end of file
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
2 @import "mixins" 2 @import "mixins"
3 @import "colors" 3 @import "colors"
4 4
5 ##{$prefix}settings-wrap 5 //##{$prefix}settings-wrap
6 .subsubsub 6 // .subsubsub
7 +flex( row, flex-start, center, wrap ) 7 // +flex( row, flex-start, center, wrap )
8 margin-left: -3px 8 // margin-left: -3px
9 margin-right: -3px 9 // margin-right: -3px
10 a 10 // a
11 margin: 0 3px 11 // margin: 0 3px
12 12
13 .#{$prefix}settings-section 13 .#{$prefix}settings-section
14 .description 14 .description
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
38 width: 25% 38 width: 25%
39 39
40 .column-configure 40 .column-configure
41 width: 60px 41 width: 10%
42 text-align: center 42 text-align: right
43 43
44 th.column-email.column-primary 44 th.column-email.column-primary
45 padding-left: 48px 45 padding-left: 48px
...@@ -50,7 +50,11 @@ th.column-email.column-primary ...@@ -50,7 +50,11 @@ th.column-email.column-primary
50 td 50 td
51 padding-right: 0 51 padding-right: 0
52 52
53 ##{$prefix}settings-emails
54 margin: 15px 0
55
53 ##{$prefix}settings-template-versions 56 ##{$prefix}settings-template-versions
57 margin: 15px 0
54 .wp-list-table 58 .wp-list-table
55 .column-core_version 59 .column-core_version
56 width: 100px 60 width: 100px
...@@ -68,6 +72,13 @@ th.column-email.column-primary ...@@ -68,6 +72,13 @@ th.column-email.column-primary
68 .subsubsub 72 .subsubsub
69 float: left 73 float: left
70 width: 100% 74 width: 100%
75 h2.title
76 a.um-back-button
77 font-weight: normal
78 font-size: 30px
79 line-height: 1
80 text-decoration: none
81 margin-right: 5px
71 82
72 83
73 .#{$prefix}settings-line 84 .#{$prefix}settings-line
......
...@@ -62,6 +62,15 @@ ...@@ -62,6 +62,15 @@
62 color: #555; 62 color: #555;
63 } 63 }
64 64
65 div.uimob340 .um-account-main div.um-account-heading.uimob340-hide,
66 div.uimob500 .um-account-main div.um-account-heading.uimob500-hide {
67 display:none;
68 }
69
70 .um-account-side .um-account-link {
71 box-sizing: content-box;
72 }
73
65 .um-account-main div.um-account-heading i { 74 .um-account-main div.um-account-heading i {
66 margin-right: 10px; 75 margin-right: 10px;
67 font-size: 26px; 76 font-size: 26px;
...@@ -193,8 +202,9 @@ ...@@ -193,8 +202,9 @@
193 border-right: 1px solid #ccc; 202 border-right: 1px solid #ccc;
194 color: #444; 203 color: #444;
195 float: left; 204 float: left;
196 padding: 0px 15px; 205 padding: 0 15px;
197 font-weight: normal !important; 206 font-weight: normal !important;
207 box-sizing: content-box;
198 } 208 }
199 209
200 .um-account-side li a span.um-account-icon i { 210 .um-account-side li a span.um-account-icon i {
......
1 .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 ...\ No newline at end of file
1 .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 ...\ No newline at end of file
......
...@@ -898,12 +898,32 @@ small.um-max-filesize span{ ...@@ -898,12 +898,32 @@ small.um-max-filesize span{
898 898
899 .um-search-area .um-search-field { 899 .um-search-area .um-search-field {
900 width: 100%; 900 width: 100%;
901 margin: 0;
902 padding-left: 25px;
903 }
904
905 .rtl .um-search-area .um-search-field {
906 padding-right: 25px;
907 padding-left: initial;
901 } 908 }
902 909
903 .um-search-area .um-search-icon { 910 .um-search-area .um-search-icon {
904 position: absolute; 911 position: absolute;
905 top: 7px; 912 height: 100%;
906 right: 10px; 913 left: 6px;
914 top: 0;
915 }
916
917 .rtl .um-search-area .um-search-icon {
918 right: 6px;
919 left: initial;
920 }
921
922 .um-faicon-search:before {
923 display: flex;
924 align-items: center;
925 justify-content: center;
926 height: 100%;
907 } 927 }
908 928
909 /* 929 /*
......
...@@ -97,6 +97,52 @@ function um_admin_init_users_select() { ...@@ -97,6 +97,52 @@ function um_admin_init_users_select() {
97 } 97 }
98 98
99 99
100 function um_admin_init_pages_select() {
101 // multiple select with AJAX search
102 jQuery('.um-pages-select2').select2({
103 ajax: {
104 url: wp.ajax.settings.url,
105 dataType: 'json',
106 delay: 250, // delay in ms while typing when to perform a AJAX search
107 data: function( params ) {
108 return {
109 search: params.term, // search query
110 action: 'um_get_pages_list', // AJAX action for admin-ajax.php
111 page: params.page || 1, // infinite scroll pagination
112 nonce: um_admin_scripts.nonce
113 };
114 },
115 processResults: function( data, params ) {
116 params.page = params.page || 1;
117 var options = [];
118
119 if ( data ) {
120
121 // data is the array of arrays, and each of them contains ID and the Label of the option
122 jQuery.each( data, function( index, text ) { // do not forget that "index" is just auto incremented value
123 if ( index === 'total_count' ) {
124 return;
125 }
126 options.push( { id: text[0], text: text[1] } );
127 });
128
129 }
130
131 return {
132 results: options,
133 pagination: {
134 more: ( params.page * 10 ) < data.total_count
135 }
136 };
137 },
138 cache: true
139 },
140 placeholder: jQuery(this).data('placeholder'),
141 minimumInputLength: 0, // the minimum of symbols to input before perform a search
142 allowClear: true,
143 });
144 }
145
100 /** 146 /**
101 * 147 *
102 * @param field_key 148 * @param field_key
...@@ -123,6 +169,7 @@ function um_same_page_something_wrong( field_key ) { ...@@ -123,6 +169,7 @@ function um_same_page_something_wrong( field_key ) {
123 169
124 jQuery(document).ready( function() { 170 jQuery(document).ready( function() {
125 um_admin_init_users_select(); 171 um_admin_init_users_select();
172 um_admin_init_pages_select();
126 173
127 /** 174 /**
128 * Same page upgrade field 175 * Same page upgrade field
...@@ -130,9 +177,9 @@ jQuery(document).ready( function() { ...@@ -130,9 +177,9 @@ jQuery(document).ready( function() {
130 jQuery( document.body ).on( 'click', '.um-forms-field[data-log-object]', function() { 177 jQuery( document.body ).on( 'click', '.um-forms-field[data-log-object]', function() {
131 var obj = jQuery( this ).data( 'log-object' ); 178 var obj = jQuery( this ).data( 'log-object' );
132 if ( jQuery( this ).is( ':checked' ) ) { 179 if ( jQuery( this ).is( ':checked' ) ) {
133 jQuery( this ).siblings( '.um-same-page-update-' + obj ).show(); 180 jQuery( this ).parents('label').siblings( '.um-same-page-update-' + obj ).show();
134 } else { 181 } else {
135 jQuery( this ).siblings( '.um-same-page-update-' + obj ).hide(); 182 jQuery( this ).parents('label').siblings( '.um-same-page-update-' + obj ).hide();
136 } 183 }
137 }); 184 });
138 185
......
...@@ -593,9 +593,13 @@ function um_modal_responsive() { ...@@ -593,9 +593,13 @@ function um_modal_responsive() {
593 if ( w <= 500 ) { 593 if ( w <= 500 ) {
594 modal.animate({ 'bottom' : 0 }, 300); 594 modal.animate({ 'bottom' : 0 }, 300);
595 } else { 595 } else {
596 if ( h - parseInt(half_gap) > h ) {
597 modal.animate({ 'bottom' : 0 }, 300);
598 } else {
596 modal.animate({ 'bottom' : half_gap }, 300); 599 modal.animate({ 'bottom' : half_gap }, 300);
597 } 600 }
598 } 601 }
602 }
599 } 603 }
600 604
601 function um_remove_modal() { 605 function um_remove_modal() {
......
1 {
2 "name": "roots",
3 "version": "7.0.3",
4 "homepage": "http://roots.io",
5 "authors": [
6 "Ben Word <ben@benword.com>"
7 ],
8 "license": "MIT",
9 "private": true,
10 "ignore": [
11 "**/.*",
12 "node_modules",
13 "assets"
14 ],
15 "dependencies": {
16 /* "modernizr": "2.8.2",
17 "jquery": "1.11.1",
18 "bootstrap": "3.3.1",
19 "respond": "1.4.2",
20 "fitvids": "~1.1.0",
21 "devbridge-autocomplete": "~1.2.16",
22 "raty": "~2.7.0",
23 "featherlight": "~1.0.4",
24 "sharrre": "~1.3.5",
25 "fullcalendar": "~2.3.0",
26 "jquery.countdown": "~2.0.4",
27 "mustache": "~2.1.3",
28 "formvalidation": "https://github.com/formvalidation/formvalidation.git"*/
29 }
30 }
1 {
2 "name": "ultimatemember/ultimatemember",
3 "description": "The easiest way to create powerful online communities and beautiful user profiles with WordPress.",
4 "type": "wordpress-plugin",
5 "homepage": "https://wordpress.org/plugins/ultimate-member/",
6 "license": "GPL-3.0-or-later",
7 "minimum-stability": "stable",
8 "prefer-stable": true,
9 "config": {
10 "allow-plugins": {
11 "symfony/flex": true,
12 "dealerdirect/phpcodesniffer-composer-installer": true
13 }
14 },
15 "require": {
16 "ext-mbstring": "*",
17 "ext-json": "*",
18 "ext-dom": "*",
19 "ext-exif": "*",
20 "ext-gd": "*",
21 "ext-fileinfo": "*",
22 "ext-curl": "*",
23 "ext-iconv": "*",
24 "woocommerce/action-scheduler": "3.2.1"
25 },
26 "require-dev": {
27 "roave/security-advisories": "dev-latest",
28 "wp-cli/wp-cli": "*",
29 "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
30 "object-calisthenics/phpcs-calisthenics-rules": "*",
31 "phpcompatibility/phpcompatibility-wp": "*",
32 "wp-coding-standards/wpcs": "2.3.0",
33 "squizlabs/php_codesniffer": "3.*",
34 "phpdocumentor/phpdocumentor": "3.1.*"
35 },
36 "extra": {
37 "installer-paths": {
38 "vendor/{$vendor}/{$name}/": ["woocommerce/action-scheduler"]
39 }
40 }
41 }
1 # Welcome to the Ultimate Member Documentation
2
3 There are GitHub Pages documentation of [Ultimate Member](https://wordpress.org/plugins/ultimate-member/) plugin. Use the links below:
4
5 The generated documentation on actions and filters is [here](https://ultimatemember.github.io/ultimatemember/hooks).
6
7 The generated documentation on PHP namespaces, classes, properties, methods and functions is [here](https://ultimatemember.github.io/ultimatemember/phpdoc).
8
9 For more information about using Ultimate Member with WordPress, please see the [Ultimate Member Docs](https://docs.ultimatemember.com/).
10
11 To report an issue with Ultimate Member, please visit the [Support forum](https://wordpress.org/support/plugin/ultimate-member/).
1 /*
2 Ultimate Member dependencies
3 */
4
5 var gulp = require('gulp')
6 , uglify = require('gulp-uglify'),
7 sass = require('gulp-sass'),
8 rename = require('gulp-rename'),
9 cleanCSS = require( 'gulp-clean-css' );
10
11 // task
12 gulp.task( 'default', function ( done ) {
13 sass.compiler = require( 'node-sass' );
14
15 gulp.src(['assets/sass/*.sass']).pipe( sass().on( 'error', sass.logError ) ).pipe( gulp.dest( 'assets/css' ) );
16
17 gulp.src(['assets/js/*.js','!assets/js/*.min.js']) // path to your files
18 .pipe( uglify() )
19 .pipe( rename({ suffix: '.min' }) )
20 .pipe( gulp.dest( 'assets/js/' ) );
21
22 gulp.src(['assets/js/admin/*.js','!assets/js/admin/*.min.js']) // path to your files
23 .pipe( uglify() )
24 .pipe( rename({ suffix: '.min' }) )
25 .pipe( gulp.dest( 'assets/js/admin/' ) );
26 gulp.src(['assets/css/admin/*.css', '!assets/css/admin/*.min.css',])
27 .pipe( cleanCSS() )
28 .pipe( rename( { suffix: '.min' } ) )
29 .pipe( gulp.dest( 'assets/css/admin/' ) );
30
31 gulp.src(['assets/css/*.css', '!assets/css/*.min.css',])
32 .pipe( cleanCSS() )
33 .pipe( rename( { suffix: '.min' } ) )
34 .pipe( gulp.dest( 'assets/css/' ) );
35
36 // full CSS files
37 gulp.src(['assets/css/admin/*.sass'])
38 .pipe( sass().on( 'error', sass.logError ) )
39 .pipe( gulp.dest( 'assets/css/admin/' ) );
40 // min CSS files
41 gulp.src(['assets/css/admin/*.sass'])
42 .pipe( sass().on( 'error', sass.logError ) )
43 .pipe( cleanCSS() )
44 .pipe( rename( { suffix: '.min' } ) )
45 .pipe( gulp.dest( 'assets/css/admin/' ) );
46
47 // full CSS files
48 gulp.src(['assets/css/*.sass'])
49 .pipe( sass().on( 'error', sass.logError ) )
50 .pipe( gulp.dest( 'assets/css/' ) );
51 // min CSS files
52 gulp.src(['assets/css/*.sass'])
53 .pipe( sass().on( 'error', sass.logError ) )
54 .pipe( cleanCSS() )
55 .pipe( rename( { suffix: '.min' } ) )
56 .pipe( gulp.dest( 'assets/css/' ) );
57
58 gulp.src(['assets/libs/legacy/fonticons/*.css', '!assets/libs/legacy/fonticons/*.min.css',])
59 .pipe( cleanCSS() )
60 .pipe( rename( { suffix: '.min' } ) )
61 .pipe( gulp.dest( 'assets/libs/legacy/fonticons/' ) );
62
63 // Raty lib
64 gulp.src(['assets/libs/raty/*.css', '!assets/libs/raty/*.min.css',])
65 .pipe( cleanCSS() )
66 .pipe( rename( { suffix: '.min' } ) )
67 .pipe( gulp.dest( 'assets/libs/raty/' ) );
68 gulp.src(['assets/libs/raty/*.js', '!assets/libs/raty/*.min.js',])
69 .pipe( uglify() )
70 .pipe( rename({ suffix: '.min' }) )
71 .pipe( gulp.dest( 'assets/libs/raty/' ) );
72
73 // Tipsy lib
74 gulp.src(['assets/libs/tipsy/*.css', '!assets/libs/tipsy/*.min.css',])
75 .pipe( cleanCSS() )
76 .pipe( rename( { suffix: '.min' } ) )
77 .pipe( gulp.dest( 'assets/libs/tipsy/' ) );
78 gulp.src(['assets/libs/tipsy/*.js', '!assets/libs/tipsy/*.min.js',])
79 .pipe( uglify() )
80 .pipe( rename({ suffix: '.min' }) )
81 .pipe( gulp.dest( 'assets/libs/tipsy/' ) );
82
83 // Pickadate lib
84 gulp.src(['assets/libs/pickadate/*.css', '!assets/libs/pickadate/*.min.css',])
85 .pipe( cleanCSS() )
86 .pipe( rename( { suffix: '.min' } ) )
87 .pipe( gulp.dest( 'assets/libs/pickadate/' ) );
88 gulp.src(['assets/libs/pickadate/*.js', '!assets/libs/pickadate/*.min.js',])
89 .pipe( uglify() )
90 .pipe( rename({ suffix: '.min' }) )
91 .pipe( gulp.dest( 'assets/libs/pickadate/' ) );
92 gulp.src(['assets/libs/pickadate/translations/*.js', '!assets/libs/pickadate/translations/*.min.js',])
93 .pipe( uglify() )
94 .pipe( rename({ suffix: '.min' }) )
95 .pipe( gulp.dest( 'assets/libs/pickadate/translations/' ) );
96
97 done();
98 });
1 {
2 "opts": {
3 "destination": "docs/hooks",
4 "template": "node_modules/wp-hookdoc/template",
5 "recurse": true,
6 "readme": "./.github/hookdoc-tmpl/README.md"
7 },
8 "source": {
9 "include": [
10 "./"
11 ],
12 "exclude": [
13 "node_modules"
14 ],
15 "includePattern": ".+\\.(php)?$"
16 },
17 "plugins": [
18 "node_modules/wp-hookdoc/plugin",
19 "plugins/markdown"
20 ],
21 "templates": {
22 "default": {
23 "layoutFile": "./.github/hookdoc-tmpl/layout.tmpl",
24 "staticFiles": {
25 "include": [
26 "./.github/hookdoc-tmpl/static"
27 ]
28 }
29 }
30 }
31 }
1 <?php 1 <?php
2 namespace um\admin; 2 namespace um\admin;
3 3
4 use WP_Query;
5
4 if ( ! defined( 'ABSPATH' ) ) { 6 if ( ! defined( 'ABSPATH' ) ) {
5 exit; 7 exit;
6 } 8 }
...@@ -69,6 +71,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ...@@ -69,6 +71,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
69 add_action( 'um_admin_do_action__check_templates_version', array( &$this, 'check_templates_version' ) ); 71 add_action( 'um_admin_do_action__check_templates_version', array( &$this, 'check_templates_version' ) );
70 72
71 add_action( 'um_admin_do_action__install_core_pages', array( &$this, 'install_core_pages' ) ); 73 add_action( 'um_admin_do_action__install_core_pages', array( &$this, 'install_core_pages' ) );
74 add_action( 'um_admin_do_action__install_predefined_page', array( &$this, 'install_predefined_page' ) );
72 75
73 add_action( 'parent_file', array( &$this, 'parent_file' ), 9 ); 76 add_action( 'parent_file', array( &$this, 'parent_file' ), 9 );
74 add_filter( 'gettext', array( &$this, 'gettext' ), 10, 4 ); 77 add_filter( 'gettext', array( &$this, 'gettext' ), 10, 4 );
...@@ -1617,31 +1620,106 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ...@@ -1617,31 +1620,106 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
1617 public function install_core_pages() { 1620 public function install_core_pages() {
1618 UM()->setup()->install_default_pages(); 1621 UM()->setup()->install_default_pages();
1619 1622
1620 //check empty pages in settings 1623 // Auto dismiss 'wrong_pages' notice if it's visible
1621 $empty_pages = array(); 1624 $this->dismiss_wrong_pages();
1622 1625
1623 $pages = UM()->config()->permalinks; 1626 $url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
1624 if ( $pages && is_array( $pages ) ) { 1627 wp_safe_redirect( $url );
1625 foreach ( $pages as $slug => $page_id ) { 1628 exit;
1626 $page = get_post( $page_id ); 1629 }
1630
1631 /**
1632 * Install predefined page based on $_REQUEST['um_page_slug'] argument.
1633 */
1634 public function install_predefined_page() {
1635 if ( ! current_user_can( 'manage_options' ) ) {
1636 $url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
1637 wp_safe_redirect( $url );
1638 exit;
1639 }
1640
1641 $predefined_pages = array_keys( UM()->config()->get( 'predefined_pages' ) );
1642
1643 // phpcs:ignore WordPress.Security.NonceVerification -- early nonce verification based on `um_adm_action`
1644 $page_slug = array_key_exists( 'um_page_slug', $_REQUEST ) ? sanitize_key( $_REQUEST['um_page_slug'] ) : '';
1645
1646 if ( empty( $page_slug ) || ! in_array( $page_slug, $predefined_pages, true ) ) {
1647 $url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
1648 wp_safe_redirect( $url );
1649 exit;
1650 }
1651
1652 $post_ids = new WP_Query(
1653 array(
1654 'post_type' => 'page',
1655 'meta_query' => array(
1656 array(
1657 'key' => '_um_core',
1658 'value' => $page_slug,
1659 ),
1660 ),
1661 'posts_per_page' => -1,
1662 'fields' => 'ids',
1663 )
1664 );
1665
1666 $post_ids = $post_ids->get_posts();
1667
1668 if ( ! empty( $post_ids ) ) {
1669 foreach ( $post_ids as $post_id ) {
1670 delete_post_meta( $post_id, '_um_core' );
1671 }
1672 }
1673
1674 UM()->setup()->predefined_page( $page_slug );
1627 1675
1628 if ( ! isset( $page->ID ) && array_key_exists( $slug, UM()->config()->core_pages ) ) { 1676 // Auto dismiss 'wrong_pages' notice if it's visible
1677 $this->dismiss_wrong_pages();
1678
1679 $url = add_query_arg(
1680 array(
1681 'page' => 'um_options',
1682 'update' => 'um_settings_updated',
1683 ),
1684 admin_url( 'admin.php' )
1685 );
1686 wp_safe_redirect( $url );
1687 exit;
1688 }
1689
1690 /**
1691 * Dismiss 'wrong_pages' notice if it's visible.
1692 */
1693 public function dismiss_wrong_pages() {
1694 // Check empty pages in settings.
1695 $empty_pages = array();
1696
1697 $predefined_pages = array_keys( UM()->config()->get( 'predefined_pages' ) );
1698 foreach ( $predefined_pages as $slug ) {
1699 $page_id = um_get_predefined_page_id( $slug );
1700 if ( ! $page_id ) {
1629 $empty_pages[] = $slug; 1701 $empty_pages[] = $slug;
1702 continue;
1630 } 1703 }
1704
1705 $page = get_post( $page_id );
1706 if ( ! $page ) {
1707 $empty_pages[] = $slug;
1708 continue;
1631 } 1709 }
1632 } 1710 }
1633 1711
1634 //if there aren't empty pages - then hide pages notice 1712 // If there aren't empty pages - then hide pages notice
1635 if ( empty( $empty_pages ) ) { 1713 if ( empty( $empty_pages ) ) {
1636 $hidden_notices = get_option( 'um_hidden_admin_notices', array() ); 1714 $hidden_notices = get_option( 'um_hidden_admin_notices', array() );
1715 if ( ! is_array( $hidden_notices ) ) {
1716 $hidden_notices = array();
1717 }
1718
1637 $hidden_notices[] = 'wrong_pages'; 1719 $hidden_notices[] = 'wrong_pages';
1638 1720
1639 update_option( 'um_hidden_admin_notices', $hidden_notices ); 1721 update_option( 'um_hidden_admin_notices', $hidden_notices );
1640 } 1722 }
1641
1642 $url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) );
1643 wp_safe_redirect( $url );
1644 exit;
1645 } 1723 }
1646 1724
1647 /** 1725 /**
...@@ -1826,24 +1904,13 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ...@@ -1826,24 +1904,13 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
1826 * Manual check templates versions. 1904 * Manual check templates versions.
1827 */ 1905 */
1828 public function check_templates_version() { 1906 public function check_templates_version() {
1829 $templates = UM()->admin_settings()->get_override_templates( true ); 1907 UM()->common()->theme()->flush_transient_templates_data();
1830 $out_date = false;
1831
1832 foreach ( $templates as $template ) {
1833 if ( 0 === $template['status_code'] ) {
1834 $out_date = true;
1835 break;
1836 }
1837 }
1838
1839 if ( false === $out_date ) {
1840 delete_option( 'um_override_templates_outdated' );
1841 }
1842 1908
1843 $url = add_query_arg( 1909 $url = add_query_arg(
1844 array( 1910 array(
1845 'page' => 'um_options', 1911 'page' => 'um_options',
1846 'tab' => 'override_templates', 1912 'tab' => 'advanced',
1913 'section' => 'override_templates',
1847 ), 1914 ),
1848 admin_url( 'admin.php' ) 1915 admin_url( 'admin.php' )
1849 ); 1916 );
......
...@@ -352,7 +352,8 @@ final class Enqueue extends \um\common\Enqueue { ...@@ -352,7 +352,8 @@ final class Enqueue extends \um\common\Enqueue {
352 'successfully_redirect' => add_query_arg( 352 'successfully_redirect' => add_query_arg(
353 array( 353 array(
354 'page' => 'um_options', 354 'page' => 'um_options',
355 'tab' => 'misc', 355 'tab' => 'advanced',
356 'section' => 'features',
356 'msg' => 'updated', 357 'msg' => 'updated',
357 ), 358 ),
358 admin_url( 'admin.php' ) 359 admin_url( 'admin.php' )
...@@ -554,7 +555,7 @@ final class Enqueue extends \um\common\Enqueue { ...@@ -554,7 +555,7 @@ final class Enqueue extends \um\common\Enqueue {
554 wp_enqueue_style( 'um_admin_common' ); 555 wp_enqueue_style( 'um_admin_common' );
555 556
556 if ( self::$um_cpt_form_screen ) { 557 if ( self::$um_cpt_form_screen ) {
557 if ( defined( 'UM_LEGACY_BUILDER_OFF' ) && UM_LEGACY_BUILDER_OFF ) { 558 if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE && UM()->options()->get( 'enable_new_form_builder' ) ) {
558 // Do new assets. 559 // Do new assets.
559 } else { 560 } else {
560 $this->load_builder(); 561 $this->load_builder();
...@@ -583,10 +584,16 @@ final class Enqueue extends \um\common\Enqueue { ...@@ -583,10 +584,16 @@ final class Enqueue extends \um\common\Enqueue {
583 wp_enqueue_style( 'um_admin_roles' ); 584 wp_enqueue_style( 'um_admin_roles' );
584 } elseif ( 'ultimate-member_page_um_options' === $hook ) { 585 } elseif ( 'ultimate-member_page_um_options' === $hook ) {
585 // phpcs:ignore WordPress.Security.NonceVerification 586 // phpcs:ignore WordPress.Security.NonceVerification
586 if ( isset( $_GET['tab'] ) && 'secure' === $_GET['tab'] ) { 587 if ( isset( $_GET['tab'], $_GET['section'] ) && 'advanced' === $_GET['tab'] && 'security' === $_GET['section'] ) {
587 wp_register_script( 'um_admin_secure', $js_url . 'admin/secure' . $suffix . '.js', array( 'jquery', 'wp-i18n' ), UM_VERSION, true ); 588 wp_register_script( 'um_admin_security', $js_url . 'admin/security' . $suffix . '.js', array( 'jquery', 'wp-i18n' ), UM_VERSION, true );
588 wp_set_script_translations( 'um_admin_secure', 'ultimate-member' ); 589 wp_set_script_translations( 'um_admin_security', 'ultimate-member' );
589 wp_enqueue_script( 'um_admin_secure' ); 590 wp_enqueue_script( 'um_admin_security' );
591 }
592
593 // phpcs:ignore WordPress.Security.NonceVerification
594 if ( isset( $_GET['tab'] ) && 'appearance' === $_GET['tab'] && empty( $_GET['section'] ) ) {
595 // Init WP Media Uploader on the UM > Settings > Appearance > Profile screen.
596 wp_enqueue_media();
590 } 597 }
591 598
592 wp_register_style( 'um_admin_settings', $css_url . 'admin/settings' . $suffix . '.css', array(), UM_VERSION ); 599 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' ) ) { ...@@ -90,12 +90,6 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
90 */ 90 */
91 public function admin_init() { 91 public function admin_init() {
92 global $wpdb; 92 global $wpdb;
93 // Dismiss admin notice after the first visit to Secure settings page.
94 if ( isset( $_REQUEST['page'] ) && isset( $_REQUEST['tab'] ) &&
95 'um_options' === sanitize_key( $_REQUEST['page'] ) && 'secure' === sanitize_key( $_REQUEST['tab'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
96 UM()->admin()->notices()->dismiss( 'secure_settings' );
97 }
98
99 if ( isset( $_REQUEST['um_secure_expire_all_sessions'] ) && ! wp_doing_ajax() ) { 93 if ( isset( $_REQUEST['um_secure_expire_all_sessions'] ) && ! wp_doing_ajax() ) {
100 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-secure-expire-session-nonce' ) || ! current_user_can( 'manage_options' ) ) { 94 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-secure-expire-session-nonce' ) || ! current_user_can( 'manage_options' ) ) {
101 // This nonce is not valid or current logged-in user has no administrative rights. 95 // This nonce is not valid or current logged-in user has no administrative rights.
...@@ -239,13 +233,15 @@ if ( ! class_exists( 'um\admin\Secure' ) ) { ...@@ -239,13 +233,15 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
239 'id' => 'lock_register_forms', 233 'id' => 'lock_register_forms',
240 'type' => 'checkbox', 234 'type' => 'checkbox',
241 'label' => __( 'Lock All Register Forms', 'ultimate-member' ), 235 'label' => __( 'Lock All Register Forms', 'ultimate-member' ),
236 'checkbox_label' => __( 'Lock Forms', 'ultimate-member' ),
242 'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ), 237 'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ),
243 ), 238 ),
244 array( 239 array(
245 'id' => 'display_login_form_notice', 240 'id' => 'display_login_form_notice',
246 'type' => 'checkbox', 241 'type' => 'checkbox',
247 'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ), 242 'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ),
248 'description' => __( 'Enforces users to reset their passwords( one-time ) and prevent from entering old password.', 'ultimate-member' ), 243 'checkbox_label' => __( 'Enable Login form notice', 'ultimate-member' ),
244 'description' => __( 'Enforces users to reset their passwords (one-time) and prevent from entering old password.', 'ultimate-member' ),
249 ), 245 ),
250 ); 246 );
251 247
...@@ -267,13 +263,15 @@ if ( ! class_exists( 'um\admin\Secure' ) ) { ...@@ -267,13 +263,15 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
267 array( 263 array(
268 'id' => 'secure_ban_admins_accounts', 264 'id' => 'secure_ban_admins_accounts',
269 'type' => 'checkbox', 265 'type' => 'checkbox',
270 'label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ), 266 'label' => __( 'Administrative capabilities ban', 'ultimate-member' ),
267 'checkbox_label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ),
271 'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ), 268 'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ),
272 ), 269 ),
273 array( 270 array(
274 'id' => 'secure_notify_admins_banned_accounts', 271 'id' => 'secure_notify_admins_banned_accounts',
275 'type' => 'checkbox', 272 'type' => 'checkbox',
276 'label' => __( 'Notify Administrators', 'ultimate-member' ), 273 'label' => __( 'Notify Administrators', 'ultimate-member' ),
274 'checkbox_label' => __( 'Enable notification', 'ultimate-member' ),
277 'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ), 275 'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ),
278 'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ), 276 'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ),
279 ), 277 ),
...@@ -292,14 +290,21 @@ if ( ! class_exists( 'um\admin\Secure' ) ) { ...@@ -292,14 +290,21 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
292 'id' => 'secure_allowed_redirect_hosts', 290 'id' => 'secure_allowed_redirect_hosts',
293 'type' => 'textarea', 291 'type' => 'textarea',
294 'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ), 292 'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ),
295 'description' => __( 'Extend allowed hosts for frontend pages redirects', 'ultimate-member' ), 293 'description' => __( 'Extend allowed hosts for frontend pages redirects.', 'ultimate-member' ),
296 ), 294 ),
297 ) 295 )
298 ); 296 );
299 297
300 $settings['secure'] = array( 298 $settings['advanced']['sections'] = UM()->array_insert_before(
301 'title' => __( 'Secure', 'ultimate-member' ), 299 $settings['advanced']['sections'],
300 'developers',
301 array(
302 'security' => array(
303 'title' => __( 'Security', 'ultimate-member' ),
304 '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' ),
302 'fields' => $secure_fields, 305 'fields' => $secure_fields,
306 ),
307 )
303 ); 308 );
304 309
305 return $settings; 310 return $settings;
......
...@@ -13,10 +13,68 @@ if ( ! defined( 'ABSPATH' ) ) { ...@@ -13,10 +13,68 @@ if ( ! defined( 'ABSPATH' ) ) {
13 class Site_Health { 13 class Site_Health {
14 14
15 /** 15 /**
16 * String of a badge color.
17 * Options: blue, green, red, orange, purple and gray.
18 *
19 * @see https://make.wordpress.org/core/2019/04/25/site-health-check-in-5-2/
20 *
21 * @since 2.8.3
22 */
23 const BADGE_COLOR = 'blue';
24
25 /**
16 * Site_Health constructor. 26 * Site_Health constructor.
17 */ 27 */
18 public function __construct() { 28 public function __construct() {
19 add_filter( 'debug_information', array( $this, 'debug_information' ), 20 ); 29 add_filter( 'debug_information', array( $this, 'debug_information' ), 20 );
30 add_filter( 'site_status_tests', array( $this, 'register_site_status_tests' ) );
31 }
32
33 public function register_site_status_tests( $tests ) {
34 $custom_templates = UM()->common()->theme()->get_custom_templates_list();
35
36 if ( ! empty( $custom_templates ) ) {
37 $tests['direct']['um_override_templates'] = array(
38 'label' => esc_html__( 'Are the Ultimate Member templates out of date?', 'ultimate-member' ),
39 'test' => array( $this, 'override_templates_test' ),
40 );
41 }
42
43 return $tests;
44 }
45
46 public function override_templates_test() {
47 $result = array(
48 'label' => __( 'You have the most recent version of custom Ultimate Member templates', 'ultimate-member' ),
49 'status' => 'good',
50 'badge' => array(
51 'label' => UM_PLUGIN_NAME,
52 'color' => self::BADGE_COLOR,
53 ),
54 'description' => sprintf(
55 '<p>%s</p>',
56 __( 'Your custom Ultimate Member templates that are situated in the theme have the most recent version and are ready to use.', 'ultimate-member' )
57 ),
58 'actions' => '',
59 'test' => 'um_override_templates',
60 );
61
62 if ( UM()->common()->theme()->is_outdated_template_exist() ) {
63 $result['label'] = __( 'Your custom templates are out of date', 'ultimate-member' );
64 $result['status'] = 'critical';
65 $result['badge']['color'] = 'red';
66 $result['description'] = sprintf(
67 '<p>%s</p>',
68 __( 'Your custom Ultimate Member templates that are situated in the theme are out of date and may break the website\'s functionality.', 'ultimate-member' )
69 );
70 $result['actions'] = sprintf(
71 '<p><a href="%s">%s</a></p>',
72 admin_url( 'admin.php?page=um_options&tab=advanced&section=override_templates' ),
73 esc_html__( 'Check status and update', 'ultimate-member' )
74 );
75 }
76
77 return $result;
20 } 78 }
21 79
22 private function get_roles() { 80 private function get_roles() {
...@@ -290,7 +348,7 @@ class Site_Health { ...@@ -290,7 +348,7 @@ class Site_Health {
290 } 348 }
291 349
292 $account_settings['um-account_email'] = array( 350 $account_settings['um-account_email'] = array(
293 'label' => __( 'Allow users to change e-mail', 'ultimate-member' ), 351 'label' => __( 'Allow users to change email', 'ultimate-member' ),
294 'value' => UM()->options()->get( 'account_email' ) ? $labels['yes'] : $labels['no'], 352 'value' => UM()->options()->get( 'account_email' ) ? $labels['yes'] : $labels['no'],
295 ); 353 );
296 354
...@@ -485,7 +543,7 @@ class Site_Health { ...@@ -485,7 +543,7 @@ class Site_Health {
485 // Email settings 543 // Email settings
486 $email_settings = array( 544 $email_settings = array(
487 'um-admin_email' => array( 545 'um-admin_email' => array(
488 'label' => __( 'Admin E-mail Address', 'ultimate-member' ), 546 'label' => __( 'Admin Email Address', 'ultimate-member' ),
489 'value' => UM()->options()->get( 'admin_email' ), 547 'value' => UM()->options()->get( 'admin_email' ),
490 ), 548 ),
491 'um-mail_from' => array( 549 'um-mail_from' => array(
...@@ -497,7 +555,7 @@ class Site_Health { ...@@ -497,7 +555,7 @@ class Site_Health {
497 'value' => UM()->options()->get( 'mail_from_addr' ), 555 'value' => UM()->options()->get( 'mail_from_addr' ),
498 ), 556 ),
499 'um-email_html' => array( 557 'um-email_html' => array(
500 'label' => __( 'Use HTML for E-mails?', 'ultimate-member' ), 558 'label' => __( 'Use HTML for Emails?', 'ultimate-member' ),
501 'value' => UM()->options()->get( 'email_html' ) ? $labels['yes'] : $labels['no'], 559 'value' => UM()->options()->get( 'email_html' ) ? $labels['yes'] : $labels['no'],
502 ), 560 ),
503 ); 561 );
...@@ -1362,7 +1420,7 @@ class Site_Health { ...@@ -1362,7 +1420,7 @@ class Site_Health {
1362 $info[ 'ultimate-member-' . $key ]['fields'], 1420 $info[ 'ultimate-member-' . $key ]['fields'],
1363 array( 1421 array(
1364 'um-url_email_activate' => array( 1422 'um-url_email_activate' => array(
1365 'label' => __( 'URL redirect after e-mail activation', 'ultimate-member' ), 1423 'label' => __( 'URL redirect after email activation', 'ultimate-member' ),
1366 'value' => $rolemeta['_um_url_email_activate'], 1424 'value' => $rolemeta['_um_url_email_activate'],
1367 ), 1425 ),
1368 ) 1426 )
...@@ -1788,7 +1846,7 @@ class Site_Health { ...@@ -1788,7 +1846,7 @@ class Site_Health {
1788 'first_name' => __( 'First Name', 'ultimate-member' ), 1846 'first_name' => __( 'First Name', 'ultimate-member' ),
1789 'last_name' => __( 'Last Name', 'ultimate-member' ), 1847 'last_name' => __( 'Last Name', 'ultimate-member' ),
1790 'nickname' => __( 'Nickname', 'ultimate-member' ), 1848 'nickname' => __( 'Nickname', 'ultimate-member' ),
1791 'secondary_user_email' => __( 'Secondary E-mail Address', 'ultimate-member' ), 1849 'secondary_user_email' => __( 'Secondary Email Address', 'ultimate-member' ),
1792 'description' => __( 'Biography', 'ultimate-member' ), 1850 'description' => __( 'Biography', 'ultimate-member' ),
1793 'phone_number' => __( 'Phone Number', 'ultimate-member' ), 1851 'phone_number' => __( 'Phone Number', 'ultimate-member' ),
1794 'mobile_number' => __( 'Mobile Number', 'ultimate-member' ), 1852 'mobile_number' => __( 'Mobile Number', 'ultimate-member' ),
......
1 <?php 1 <?php
2 namespace um\admin\core; 2 namespace um\admin\core;
3 3
4 // Exit if accessed directly. 4 if ( ! defined( 'ABSPATH' ) ) {
5 if ( ! defined( 'ABSPATH' ) ) exit; 5 exit;
6 }
6 7
7 if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) { 8 if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) {
8 9
9
10 /** 10 /**
11 * Class Admin_Forms_Settings 11 * Class Admin_Forms_Settings
12 * @package um\admin\core 12 * @package um\admin\core
...@@ -17,41 +17,42 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) { ...@@ -17,41 +17,42 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) {
17 * Admin_Forms constructor. 17 * Admin_Forms constructor.
18 * @param bool $form_data 18 * @param bool $form_data
19 */ 19 */
20 function __construct( $form_data = false ) { 20 public function __construct( $form_data = false ) {
21
22 parent::__construct( $form_data ); 21 parent::__construct( $form_data );
23
24 } 22 }
25 23
26
27 /** 24 /**
28 * Get field value 25 * Get field value.
29 * 26 *
30 * @param array $field_data 27 * @param array $field_data
31 * @param string $i 28 * @param string $i
29 *
32 * @return string|array 30 * @return string|array
33 */ 31 */
34 function get_field_value( $field_data, $i = '' ) { 32 public function get_field_value( $field_data, $i = '' ) {
35 $default = isset( $field_data['default' . $i] ) ? $field_data['default' . $i] : UM()->options()->get_default( $field_data['id' . $i] ); 33 $default_key = 'default' . $i;
36 34 $value_key = 'value' . $i;
37 if ( $field_data['type'] == 'checkbox' || $field_data['type'] == 'multi_checkbox' ) { 35 $id_key = 'id' . $i;
38 if ( isset( $field_data['value' . $i] ) ) { 36
39 return $field_data['value' . $i]; 37 $default = isset( $field_data[ $default_key ] ) ? $field_data[ $default_key ] : UM()->options()->get_default( $field_data[ $id_key ] );
40 } else { 38
41 $value = UM()->options()->get( $field_data['id' . $i] ); 39 if ( in_array( $field_data['type'], array( 'checkbox', 'multi_checkbox' ), true ) ) {
40 if ( isset( $field_data[ $value_key ] ) ) {
41 return $field_data[ $value_key ];
42 }
43
44 $value = UM()->options()->get( $field_data[ $id_key ] );
42 $value = is_string( $value ) ? stripslashes( $value ) : $value; 45 $value = is_string( $value ) ? stripslashes( $value ) : $value;
43 return '' !== $value ? $value : $default; 46 return '' !== $value ? $value : $default;
44 } 47 }
45 } else { 48
46 if ( isset( $field_data['value' . $i] ) ) { 49 if ( isset( $field_data[ $value_key ] ) ) {
47 return $field_data['value'. $i]; 50 return $field_data[ $value_key ];
48 } else { 51 }
49 $value = UM()->options()->get( $field_data['id' . $i] ); 52
53 $value = UM()->options()->get( $field_data[ $id_key ] );
50 $value = is_string( $value ) ? stripslashes( $value ) : $value; 54 $value = is_string( $value ) ? stripslashes( $value ) : $value;
51 return isset( $value ) ? $value : $default; 55 return isset( $value ) ? $value : $default;
52 } 56 }
53 } 57 }
54 }
55
56 }
57 } 58 }
......
...@@ -52,7 +52,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -52,7 +52,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
52 * @param bool $echo 52 * @param bool $echo
53 * @return string 53 * @return string
54 */ 54 */
55 function render_form( $echo = true ) { 55 public function render_form( $echo = true ) {
56 56
57 if ( empty( $this->form_data['fields'] ) ) { 57 if ( empty( $this->form_data['fields'] ) ) {
58 return ''; 58 return '';
...@@ -64,7 +64,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -64,7 +64,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
64 ob_start(); 64 ob_start();
65 65
66 foreach ( $this->form_data['fields'] as $field_data ) { 66 foreach ( $this->form_data['fields'] as $field_data ) {
67 if ( isset( $field_data['type'] ) && 'hidden' == $field_data['type'] ) { 67 if ( isset( $field_data['type'] ) && 'hidden' === $field_data['type'] ) {
68 echo $this->render_form_row( $field_data ); 68 echo $this->render_form_row( $field_data );
69 } 69 }
70 } 70 }
...@@ -97,19 +97,18 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -97,19 +97,18 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
97 } 97 }
98 } 98 }
99 99
100
101 /** 100 /**
102 * @param array $data 101 * @param array $data
103 * 102 *
104 * @return string 103 * @return string
105 */ 104 */
106 function render_form_row( $data ) { 105 public function render_form_row( $data ) {
107 106
108 if ( empty( $data['type'] ) ) { 107 if ( empty( $data['type'] ) ) {
109 return ''; 108 return '';
110 } 109 }
111 110
112 if ( !empty( $data['value'] ) && $data['type'] != 'email_template' ) { 111 if ( ! empty( $data['value'] ) && $data['type'] != 'email_template' ) {
113 $data['value'] = wp_unslash( $data['value'] ); 112 $data['value'] = wp_unslash( $data['value'] );
114 113
115 /*for multi_text*/ 114 /*for multi_text*/
...@@ -169,8 +168,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -169,8 +168,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
169 168
170 } 169 }
171 170
172 if ( ! empty( $data['description'] ) ) 171 if ( ! empty( $data['description'] ) ) {
173 $html .= '<p class="description">' . $data['description'] . '</p>'; 172 $html .= '<p class="description">' . $data['description'] . '</p>';
173 }
174 174
175 $html .= '</div>'; 175 $html .= '</div>';
176 176
...@@ -190,8 +190,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -190,8 +190,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
190 190
191 } 191 }
192 192
193 if ( ! empty( $data['description'] ) ) 193 if ( ! empty( $data['description'] ) ) {
194 $html .= '<p class="description">' . $data['description'] . '</p>'; 194 $html .= '<p class="description">' . $data['description'] . '</p>';
195 }
195 196
196 $html .= '</div>'; 197 $html .= '</div>';
197 198
...@@ -209,8 +210,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -209,8 +210,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
209 210
210 } 211 }
211 212
212 if ( ! empty( $data['description'] ) ) 213 if ( ! empty( $data['description'] ) ) {
213 $html .= '<p class="description">' . $data['description'] . '</p>'; 214 $html .= '<p class="description">' . $data['description'] . '</p>';
215 }
214 216
215 $html .= '</div>'; 217 $html .= '</div>';
216 218
...@@ -233,8 +235,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -233,8 +235,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
233 235
234 } 236 }
235 237
236 if ( ! empty( $data['description'] ) ) 238 if ( ! empty( $data['description'] ) ) {
237 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; 239 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
240 }
238 241
239 $html .= '</td></tr>'; 242 $html .= '</td></tr>';
240 243
...@@ -255,8 +258,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -255,8 +258,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
255 258
256 } 259 }
257 260
258 if ( ! empty( $data['description'] ) ) 261 if ( ! empty( $data['description'] ) ) {
259 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; 262 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
263 }
260 264
261 $html .= '</td></tr>'; 265 $html .= '</td></tr>';
262 266
...@@ -276,15 +280,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -276,15 +280,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
276 280
277 } 281 }
278 282
279 if ( ! empty( $data['description'] ) ) 283 if ( ! empty( $data['description'] ) ) {
280 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; 284 $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>';
285 }
281 286
282 $html .= '</td></tr>'; 287 $html .= '</td></tr>';
283
284 } 288 }
285 } 289 }
286 } 290 }
287
288 } else { 291 } else {
289 $html .= $this->render_hidden( $data ); 292 $html .= $this->render_hidden( $data );
290 } 293 }
...@@ -927,10 +930,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -927,10 +930,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
927 * 930 *
928 * @return bool|string 931 * @return bool|string
929 */ 932 */
930 function render_checkbox( $field_data ) { 933 public function render_checkbox( $field_data ) {
931 934
932 if ( empty( $field_data['id'] ) ) 935 if ( empty( $field_data['id'] ) ) {
933 return false; 936 return false;
937 }
934 938
935 $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; 939 $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id'];
936 $id_attr = ' id="' . esc_attr( $id ) . '" '; 940 $id_attr = ' id="' . esc_attr( $id ) . '" ';
...@@ -941,7 +945,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -941,7 +945,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
941 $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; 945 $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" ';
942 946
943 $data = array( 947 $data = array(
944 'field_id' => $field_data['id'] 948 'field_id' => $field_data['id'],
945 ); 949 );
946 950
947 if ( ! empty( $field_data['data'] ) ) { 951 if ( ! empty( $field_data['data'] ) ) {
...@@ -959,20 +963,22 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -959,20 +963,22 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
959 963
960 $value = $this->get_field_value( $field_data ); 964 $value = $this->get_field_value( $field_data );
961 965
962 $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" /> 966 $checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : '';
963 <input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" />";
964
965 967
966 return $html; 968 $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 ) . " />";
969 if ( '' !== $checkbox_label ) {
970 $field_html = "<label>$field_html $checkbox_label</label>";
971 }
972 $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}";
973 return apply_filters( 'um_admin_render_checkbox_field_html', $html, $field_data );
967 } 974 }
968
969 975
970 /** 976 /**
971 * @param $field_data 977 * @param $field_data
972 * 978 *
973 * @return bool|string 979 * @return bool|string
974 */ 980 */
975 function render_same_page_update( $field_data ) { 981 public function render_same_page_update( $field_data ) {
976 982
977 if ( empty( $field_data['id'] ) ) { 983 if ( empty( $field_data['id'] ) ) {
978 return false; 984 return false;
...@@ -987,7 +993,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -987,7 +993,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
987 $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; 993 $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" ';
988 994
989 $data = array( 995 $data = array(
990 'field_id' => $field_data['id'] 996 'field_id' => $field_data['id'],
991 ); 997 );
992 998
993 if ( ! empty( $field_data['data'] ) ) { 999 if ( ! empty( $field_data['data'] ) ) {
...@@ -1009,8 +1015,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -1009,8 +1015,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
1009 1015
1010 $value = $this->get_field_value( $field_data ); 1016 $value = $this->get_field_value( $field_data );
1011 1017
1012 $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" /> 1018 $checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : '';
1013 <input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" />"; 1019
1020 $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 ) . " />";
1021 if ( '' !== $checkbox_label ) {
1022 $field_html = "<label>$field_html $checkbox_label</label>";
1023 }
1024 $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}";
1014 1025
1015 if ( ! empty( $field_data['upgrade_cb'] ) ) { 1026 if ( ! empty( $field_data['upgrade_cb'] ) ) {
1016 $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' ) . '"/> 1027 $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' ) ) { ...@@ -1020,7 +1031,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
1020 return $html; 1031 return $html;
1021 } 1032 }
1022 1033
1023
1024 /** 1034 /**
1025 * @param $field_data 1035 * @param $field_data
1026 * 1036 *
...@@ -1083,6 +1093,79 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -1083,6 +1093,79 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
1083 return $html; 1093 return $html;
1084 } 1094 }
1085 1095
1096 /**
1097 * @param $field_data
1098 *
1099 * @since 2.8.3
1100 *
1101 * @return bool|string
1102 */
1103 public function render_page_select( $field_data ) {
1104 if ( empty( $field_data['id'] ) ) {
1105 return false;
1106 }
1107
1108 $multiple = ! empty( $field_data['multi'] ) ? 'multiple' : '';
1109
1110 $id = ( ! empty( $this->form_data['prefix_id'] ) ? sanitize_title( $this->form_data['prefix_id'] ) : '' ) . '_' . $field_data['id'];
1111 $id_attr = ' id="' . esc_attr( $id ) . '" ';
1112
1113 $class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' ';
1114 $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field';
1115 $class_attr = ' class="um-forms-field um-pages-select2 ' . esc_attr( $class ) . '" ';
1116
1117 $data = array(
1118 'field_id' => $field_data['id'],
1119 );
1120
1121 if ( ! empty( $field_data['placeholder'] ) ) {
1122 $data['placeholder'] = $field_data['placeholder'];
1123 }
1124
1125 $data_attr = '';
1126 foreach ( $data as $key => $value ) {
1127 $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" ';
1128 }
1129
1130 $name = $field_data['id'];
1131 $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name;
1132 $hidden_name_attr = ' name="' . $name . '" ';
1133 $name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' );
1134 $name_attr = ' name="' . $name . '" ';
1135
1136 $value = $this->get_field_value( $field_data );
1137
1138 $options = '<option value="">' . esc_html( $data['placeholder'] ) . '</option>';
1139 if ( ! empty( $field_data['options'] ) ) {
1140 foreach ( $field_data['options'] as $key => $option ) {
1141 if ( ! empty( $field_data['multi'] ) ) {
1142
1143 if ( ! is_array( $value ) || empty( $value ) ) {
1144 $value = array();
1145 }
1146
1147 $options .= '<option value="' . $key . '" ' . selected( in_array( $key, $value ), true, false ) . '>' . esc_html( $option ) . '</option>';
1148 } else {
1149 $options .= '<option value="' . $key . '" ' . selected( (string)$key == $value, true, false ) . '>' . esc_html( $option ) . '</option>';
1150 }
1151 }
1152 }
1153
1154 $hidden = '';
1155 if ( ! empty( $multiple ) ) {
1156 $hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />";
1157 }
1158
1159 $button = '';
1160 $slug = str_replace( 'core_', '', $field_data['id'] );
1161 if ( ! um_get_predefined_page_id( $slug ) || 'publish' !== get_post_status( um_get_predefined_page_id( $slug ) ) ) {
1162 $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>';
1163 }
1164
1165 $html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr>$options</select>$button";
1166
1167 return $html;
1168 }
1086 1169
1087 /** 1170 /**
1088 * @param $field_data 1171 * @param $field_data
...@@ -1739,7 +1822,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -1739,7 +1822,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
1739 return $html; 1822 return $html;
1740 } 1823 }
1741 1824
1742
1743 /** 1825 /**
1744 * Get field value 1826 * Get field value
1745 * 1827 *
...@@ -1770,5 +1852,24 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { ...@@ -1770,5 +1852,24 @@ if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) {
1770 1852
1771 return $value; 1853 return $value;
1772 } 1854 }
1855
1856 public function render_external_link( $data ) {
1857 $defaults = array(
1858 'url' => '',
1859 'html' => '',
1860 );
1861 $data = wp_parse_args( $data, $defaults );
1862 if ( empty( $data['url'] ) || empty( $data['html'] ) ) {
1863 return '';
1864 }
1865 ob_start();
1866 ?>
1867 <a target="_blank" href="<?php echo esc_url( $data['url'] ); ?>">
1868 <?php echo esc_html( $data['html'] ); ?>
1869 <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>
1870 </a>
1871 <?php
1872 return ob_get_clean();
1873 }
1773 } 1874 }
1774 } 1875 }
......
...@@ -16,18 +16,16 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { ...@@ -16,18 +16,16 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
16 */ 16 */
17 class Admin_Menu { 17 class Admin_Menu {
18 18
19
20 /** 19 /**
21 * @var string 20 * @var string
22 */ 21 */
23 var $pagehook; 22 var $pagehook;
24 var $slug = 'ultimatemember'; 23 var $slug = 'ultimatemember';
25 24
26
27 /** 25 /**
28 * Admin_Menu constructor. 26 * Admin_Menu constructor.
29 */ 27 */
30 function __construct() { 28 public function __construct() {
31 add_action( 'admin_menu', array( &$this, 'primary_admin_menu' ), 0 ); 29 add_action( 'admin_menu', array( &$this, 'primary_admin_menu' ), 0 );
32 add_action( 'admin_menu', array( &$this, 'secondary_menu_items' ), 1000 ); 30 add_action( 'admin_menu', array( &$this, 'secondary_menu_items' ), 1000 );
33 add_action( 'admin_menu', array( &$this, 'extension_menu' ), 9999 ); 31 add_action( 'admin_menu', array( &$this, 'extension_menu' ), 9999 );
...@@ -35,8 +33,46 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { ...@@ -35,8 +33,46 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
35 add_action( 'admin_head', array( $this, 'menu_order_count' ) ); 33 add_action( 'admin_head', array( $this, 'menu_order_count' ) );
36 34
37 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1000 ); 35 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1000 );
36
37 add_action( 'load-ultimate-member_page_um_options', array( &$this, 'maybe_settings_redirect' ) );
38 } 38 }
39 39
40 /**
41 * Trigger redirect on the Settings screen if there is a wrong tab or section.
42 *
43 * @since 2.8.2
44 */
45 public function maybe_settings_redirect() {
46 $current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] );
47 $current_subtab = empty( $_GET['section'] ) ? '' : sanitize_key( $_GET['section'] );
48
49 $settings_struct = UM()->admin_settings()->settings_structure[ $current_tab ];
50
51 // Remove not option hidden fields.
52 if ( ! empty( $settings_struct['fields'] ) ) {
53 foreach ( $settings_struct['fields'] as $field_key => $field_options ) {
54 if ( isset( $field_options['is_option'] ) && false === $field_options['is_option'] ) {
55 unset( $settings_struct['fields'][ $field_key ] );
56 }
57 }
58 }
59
60 if ( empty( $settings_struct['fields'] ) && empty( $settings_struct['sections'] ) && empty( $settings_struct['form_sections'] ) ) {
61 wp_safe_redirect( add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) ) );
62 exit;
63 }
64
65 if ( ! empty( $settings_struct['sections'] ) ) {
66 if ( empty( $settings_struct['sections'][ $current_subtab ] ) ) {
67 $args = array( 'page' => 'um_options' );
68 if ( ! empty( $current_tab ) ) {
69 $args['tab'] = $current_tab;
70 }
71 wp_safe_redirect( add_query_arg( $args, admin_url( 'admin.php' ) ) );
72 exit;
73 }
74 }
75 }
40 76
41 /** 77 /**
42 * Change the admin footer text on UM admin pages 78 * Change the admin footer text on UM admin pages
...@@ -143,8 +179,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { ...@@ -143,8 +179,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
143 /** 179 /**
144 * Setup admin menu 180 * Setup admin menu
145 */ 181 */
146 function primary_admin_menu() { 182 public function primary_admin_menu() {
147 $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'); 183 $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' );
148 184
149 add_action( 'load-' . $this->pagehook, array( &$this, 'on_load_page' ) ); 185 add_action( 'load-' . $this->pagehook, array( &$this, 'on_load_page' ) );
150 186
...@@ -155,7 +191,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { ...@@ -155,7 +191,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) {
155 /** 191 /**
156 * Secondary admin menu (after settings) 192 * Secondary admin menu (after settings)
157 */ 193 */
158 function secondary_menu_items() { 194 public function secondary_menu_items() {
195 add_submenu_page( $this->slug, __( 'Settings', 'ultimate-member' ), __( 'Settings', 'ultimate-member' ), 'manage_options', 'um_options', array( UM()->admin_settings(), 'settings_page' ) );
196
159 add_submenu_page( $this->slug, __( 'Forms', 'ultimate-member' ), __( 'Forms', 'ultimate-member' ), 'manage_options', 'edit.php?post_type=um_form', '' ); 197 add_submenu_page( $this->slug, __( 'Forms', 'ultimate-member' ), __( 'Forms', 'ultimate-member' ), 'manage_options', 'edit.php?post_type=um_form', '' );
160 198
161 add_submenu_page( $this->slug, __( 'User Roles', 'ultimate-member' ), __( 'User Roles', 'ultimate-member' ), 'manage_options', 'um_roles', array( &$this, 'um_roles_pages' ) ); 199 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' ) ) { ...@@ -1021,7 +1021,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
1021 public function add_metabox_form() { 1021 public function add_metabox_form() {
1022 add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( $this, 'custom_submitdiv' ), 'um_form', 'side', 'high' ); 1022 add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( $this, 'custom_submitdiv' ), 'um_form', 'side', 'high' );
1023 1023
1024 if ( defined( 'UM_LEGACY_BUILDER_OFF' ) && UM_LEGACY_BUILDER_OFF ) { 1024 if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE && UM()->options()->get( 'enable_new_form_builder' ) ) {
1025 // Do new metabox. 1025 // Do new metabox.
1026 } else { 1026 } else {
1027 add_meta_box( 'um-admin-form-mode', __( 'Select Form Type', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'normal', 'default' ); 1027 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' ) ) { ...@@ -1267,7 +1267,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
1267 } 1267 }
1268 1268
1269 // Set post meta for legacy support in the future. 1269 // Set post meta for legacy support in the future.
1270 add_post_meta( $post_id, 'um_form_version', UM_VERSION ); 1270 add_post_meta( $post_id, 'um_form_version', UM_VERSION, true );
1271 1271
1272 if ( empty( $_POST['post_title'] ) ) { 1272 if ( empty( $_POST['post_title'] ) ) {
1273 $where = array( 'ID' => $post_id ); 1273 $where = array( 'ID' => $post_id );
...@@ -1494,7 +1494,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { ...@@ -1494,7 +1494,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
1494 break; 1494 break;
1495 1495
1496 case '_validate': 1496 case '_validate':
1497 if ( array_key_exists( 'mode', $form_data ) && 'login' === $form_data['mode'] && in_array( $field_args['metakey'], array( 'username', 'user_login', 'user_email' ), true ) ) { 1497 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 ) ) {
1498 return; 1498 return;
1499 } 1499 }
1500 ?> 1500 ?>
......
...@@ -31,8 +31,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -31,8 +31,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
31 31
32 add_action( 'wp_ajax_um_dismiss_notice', array( &$this, 'dismiss_notice' ) ); 32 add_action( 'wp_ajax_um_dismiss_notice', array( &$this, 'dismiss_notice' ) );
33 add_action( 'admin_init', array( &$this, 'force_dismiss_notice' ) ); 33 add_action( 'admin_init', array( &$this, 'force_dismiss_notice' ) );
34
35 add_action( 'current_screen', array( &$this, 'create_list_for_screen' ) );
36 } 34 }
37 35
38 /** 36 /**
...@@ -51,8 +49,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -51,8 +49,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
51 49
52 $this->extensions_page(); 50 $this->extensions_page();
53 51
54 $this->template_version();
55
56 $this->child_theme_required(); 52 $this->child_theme_required();
57 53
58 // Removed for now to avoid the bad reviews. 54 // Removed for now to avoid the bad reviews.
...@@ -82,13 +78,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -82,13 +78,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
82 do_action( 'um_admin_create_notices' ); 78 do_action( 'um_admin_create_notices' );
83 } 79 }
84 80
85 public function create_list_for_screen() {
86 if ( UM()->admin()->screen()->is_own_screen() ) {
87 $this->secure_settings();
88 }
89 }
90
91
92 /** 81 /**
93 * @return array 82 * @return array
94 */ 83 */
...@@ -587,8 +576,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -587,8 +576,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
587 } 576 }
588 } 577 }
589 578
590 579 public function check_wrong_licenses() {
591 function check_wrong_licenses() {
592 $invalid_license = 0; 580 $invalid_license = 0;
593 $arr_inactive_license_keys = array(); 581 $arr_inactive_license_keys = array();
594 582
...@@ -599,10 +587,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -599,10 +587,11 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
599 foreach ( UM()->admin_settings()->settings_structure['licenses']['fields'] as $field_data ) { 587 foreach ( UM()->admin_settings()->settings_structure['licenses']['fields'] as $field_data ) {
600 $license = get_option( "{$field_data['id']}_edd_answer" ); 588 $license = get_option( "{$field_data['id']}_edd_answer" );
601 589
602 if ( ( is_object( $license ) && 'valid' == $license->license ) || 'valid' == $license ) 590 if ( ( is_object( $license ) && isset( $license->license ) && 'valid' === $license->license ) || 'valid' === $license ) {
603 continue; 591 continue;
592 }
604 593
605 if ( ( is_object( $license ) && 'inactive' == $license->license ) || 'inactive' == $license ) { 594 if ( ( is_object( $license ) && isset( $license->license ) && 'inactive' === $license->license ) || 'inactive' === $license ) {
606 $arr_inactive_license_keys[] = $license->item_name; 595 $arr_inactive_license_keys[] = $license->item_name;
607 } 596 }
608 597
...@@ -614,7 +603,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -614,7 +603,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
614 'license_key', 603 'license_key',
615 array( 604 array(
616 'class' => 'error', 605 'class' => 'error',
617 // translators: %1$s is a inactive license number; %2$s is a plugin name; %3$s is a store link. 606 // translators: %1$s is an inactive license number; %2$s is a plugin name; %3$s is a store link.
618 '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>', 607 '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>',
619 ), 608 ),
620 3 609 3
...@@ -622,12 +611,20 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -622,12 +611,20 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
622 } 611 }
623 612
624 if ( $invalid_license ) { 613 if ( $invalid_license ) {
614 $licenses_page_url = add_query_arg(
615 array(
616 'page' => 'um_options',
617 'tab' => 'licenses',
618 ),
619 admin_url( 'admin.php' )
620 );
621
625 $this->add_notice( 622 $this->add_notice(
626 'license_key', 623 'license_key',
627 array( 624 array(
628 'class' => 'error', 625 'class' => 'error',
629 // translators: %1$s is a invalid license; %2$s is a plugin name; %3$s is a license link. 626 // translators: %1$s is an invalid license; %2$s is a plugin name; %3$s is a license link.
630 '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>', 627 '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>',
631 ), 628 ),
632 3 629 3
633 ); 630 );
...@@ -776,36 +773,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -776,36 +773,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
776 } 773 }
777 774
778 /** 775 /**
779 * Check Templates Versions notice
780 */
781 public function template_version() {
782 if ( true === (bool) get_option( 'um_override_templates_outdated' ) ) {
783 $link = admin_url( 'admin.php?page=um_options&tab=override_templates' );
784 ob_start();
785 ?>
786
787 <p>
788 <?php
789 // translators: %s override templates page link.
790 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' ) );
791 ?>
792 </p>
793
794 <?php
795 $message = ob_get_clean();
796 UM()->admin()->notices()->add_notice(
797 'um_override_templates_notice',
798 array(
799 'class' => 'error',
800 'message' => $message,
801 'dismissible' => false,
802 ),
803 10
804 );
805 }
806 }
807
808 /**
809 * Check if there isn't installed child-theme. Child theme is required for safely saved customizations. 776 * Check if there isn't installed child-theme. Child theme is required for safely saved customizations.
810 */ 777 */
811 public function child_theme_required() { 778 public function child_theme_required() {
...@@ -820,7 +787,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -820,7 +787,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
820 <p> 787 <p>
821 <?php 788 <?php
822 // translators: %s child-theme article link. 789 // translators: %s child-theme article link.
823 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' ) ); 790 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' ) );
824 ?> 791 ?>
825 </p> 792 </p>
826 793
...@@ -838,39 +805,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -838,39 +805,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
838 } 805 }
839 } 806 }
840 807
841 /**
842 * First time installed Secure settings.
843 */
844 public function secure_settings() {
845 ob_start();
846 ?>
847 <p>
848 <strong><?php esc_html_e( 'Important Update', 'ultimate-member' ); ?></strong><br/>
849 <?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' ); ?>
850 </p>
851 <p>
852 <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>
853 <a class="button" target="_blank" href="https://docs.ultimatemember.com/article/1869-security-feature"><?php esc_html_e( 'Read the documentation', 'ultimate-member' ); ?></a>
854 </p>
855 <?php
856 $message = ob_get_clean();
857 $this->add_notice(
858 'secure_settings',
859 array(
860 'class' => 'warning',
861 'message' => $message,
862 'dismissible' => true,
863 ),
864 1
865 );
866 }
867
868 public function common_secure() { 808 public function common_secure() {
869 if ( UM()->options()->get( 'lock_register_forms' ) ) { 809 if ( UM()->options()->get( 'lock_register_forms' ) ) {
870 ob_start(); 810 ob_start();
871 ?> 811 ?>
872 <p> 812 <p>
873 <?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' ); ?> 813 <?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' ); ?>
874 </p> 814 </p>
875 <?php 815 <?php
876 $message = ob_get_clean(); 816 $message = ob_get_clean();
...@@ -889,7 +829,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -889,7 +829,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
889 ob_start(); 829 ob_start();
890 ?> 830 ?>
891 <p> 831 <p>
892 <?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' ); ?> 832 <?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' ); ?>
893 </p> 833 </p>
894 <?php 834 <?php
895 $message = ob_get_clean(); 835 $message = ob_get_clean();
...@@ -908,7 +848,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ...@@ -908,7 +848,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
908 ob_start(); 848 ob_start();
909 ?> 849 ?>
910 <p> 850 <p>
911 <?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' ); ?> 851 <?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' ); ?>
912 </p> 852 </p>
913 <?php 853 <?php
914 $message = ob_get_clean(); 854 $message = ob_get_clean();
......
...@@ -102,10 +102,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) { ...@@ -102,10 +102,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
102 $dest = realpath( $um_dir ); 102 $dest = realpath( $um_dir );
103 if ( $src && $dest ) { 103 if ( $src && $dest ) {
104 self::recurse_copy( $src, $dest ); 104 self::recurse_copy( $src, $dest );
105 error_log( "UM Log. Theme '" . $theme->get( 'template' ) . "' templates restored." ); 105 error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates restored." );
106 UM()->files()->remove_dir( $src ); 106 UM()->files()->remove_dir( $src );
107 } else { 107 } else {
108 error_log( "UM Error. Can not restore theme templates." ); 108 error_log( 'UM Error. Can not restore theme templates.' );
109 } 109 }
110 110
111 delete_option( 'theme_version ' . $theme->get( 'Name' ) ); 111 delete_option( 'theme_version ' . $theme->get( 'Name' ) );
...@@ -144,9 +144,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) { ...@@ -144,9 +144,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) {
144 $dest = realpath( $temp_dir ); 144 $dest = realpath( $temp_dir );
145 if ( $src && $dest ) { 145 if ( $src && $dest ) {
146 self::recurse_copy( $src, $dest ); 146 self::recurse_copy( $src, $dest );
147 error_log( "UM Log. Theme '" . $theme->get( 'template' ) . "' templates saved." ); 147 error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates saved." );
148 } else { 148 } else {
149 error_log( "UM Error. Can not save theme templates." ); 149 error_log( 'UM Error. Can not save theme templates.' );
150 } 150 }
151 151
152 update_option( 'theme_version ' . $theme->get( 'Name' ), $theme->get( 'Version' ) ); 152 update_option( 'theme_version ' . $theme->get( 'Name' ), $theme->get( 'Version' ) );
......
...@@ -247,7 +247,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) { ...@@ -247,7 +247,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
247 'label' => __( 'Put as Pending Review', 'ultimate-member' ) 247 'label' => __( 'Put as Pending Review', 'ultimate-member' )
248 ), 248 ),
249 'um_resend_activation' => array( 249 'um_resend_activation' => array(
250 'label' => __( 'Resend Activation E-mail', 'ultimate-member' ) 250 'label' => __( 'Resend Activation Email', 'ultimate-member' )
251 ), 251 ),
252 'um_deactivate' => array( 252 'um_deactivate' => array(
253 'label' => __( 'Deactivate', 'ultimate-member' ) 253 'label' => __( 'Deactivate', 'ultimate-member' )
...@@ -407,7 +407,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) { ...@@ -407,7 +407,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Users' ) ) {
407 $status = array( 407 $status = array(
408 'approved' => __( 'Approved', 'ultimate-member' ), 408 'approved' => __( 'Approved', 'ultimate-member' ),
409 'awaiting_admin_review' => __( 'Pending review', 'ultimate-member' ), 409 'awaiting_admin_review' => __( 'Pending review', 'ultimate-member' ),
410 'awaiting_email_confirmation' => __( 'Waiting e-mail confirmation', 'ultimate-member' ), 410 'awaiting_email_confirmation' => __( 'Waiting email confirmation', 'ultimate-member' ),
411 'inactive' => __( 'Inactive', 'ultimate-member' ), 411 'inactive' => __( 'Inactive', 'ultimate-member' ),
412 'rejected' => __( 'Rejected', 'ultimate-member' ), 412 'rejected' => __( 'Rejected', 'ultimate-member' ),
413 ); 413 );
......
...@@ -99,6 +99,15 @@ class UM_Emails_List_Table extends WP_List_Table { ...@@ -99,6 +99,15 @@ class UM_Emails_List_Table extends WP_List_Table {
99 $this->_column_headers = array( $columns, $hidden, $sortable ); 99 $this->_column_headers = array( $columns, $hidden, $sortable );
100 } 100 }
101 101
102 /**
103 * Generates the table navigation above or below the table
104 *
105 * @since 3.1.0
106 * @param string $which
107 */
108 protected function display_tablenav( $which ) {
109 // Stop displaying tablenav.
110 }
102 111
103 /** 112 /**
104 * @param object $item 113 * @param object $item
...@@ -222,11 +231,13 @@ class UM_Emails_List_Table extends WP_List_Table { ...@@ -222,11 +231,13 @@ class UM_Emails_List_Table extends WP_List_Table {
222 $active = UM()->options()->get( $item['key'] . '_on' ); 231 $active = UM()->options()->get( $item['key'] . '_on' );
223 232
224 $icon = ! empty( $active ) ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt'; 233 $icon = ! empty( $active ) ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt';
225 $link = add_query_arg( array( 'email' => $item['key'] ) ); 234 $icon_title = ! empty( $active ) ? __( 'Enabled', 'ultimate-member' ) : __( 'Disabled', 'ultimate-member' );
226 $text = '<span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span><a href="' . esc_url( $link ) . '"><strong>' . $item['title'] . '</strong></a>'; 235
236 $link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) );
237 $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>';
227 238
228 if ( ! empty( $item['description'] ) ) { 239 if ( ! empty( $item['description'] ) ) {
229 $text .= ' <span class="um_tooltip dashicons dashicons-editor-help" title="' . esc_attr__( $item['description'], 'ultimate-member' ) . '"></span>'; 240 $text .= ' <span class="um_tooltip dashicons dashicons-editor-help" title="' . esc_attr( $item['description'] ) . '"></span>';
230 } 241 }
231 242
232 return $text; 243 return $text;
...@@ -239,11 +250,11 @@ class UM_Emails_List_Table extends WP_List_Table { ...@@ -239,11 +250,11 @@ class UM_Emails_List_Table extends WP_List_Table {
239 * @return string 250 * @return string
240 */ 251 */
241 function column_recipients( $item ) { 252 function column_recipients( $item ) {
242 if ( $item['recipient'] == 'admin' ) { 253 if ( 'admin' === $item['recipient'] ) {
243 return UM()->options()->get( 'admin_email' ); 254 return UM()->options()->get( 'admin_email' );
244 } else {
245 return __( 'Member', 'ultimate-member' );
246 } 255 }
256
257 return __( 'Member', 'ultimate-member' );
247 } 258 }
248 259
249 260
...@@ -253,7 +264,8 @@ class UM_Emails_List_Table extends WP_List_Table { ...@@ -253,7 +264,8 @@ class UM_Emails_List_Table extends WP_List_Table {
253 * @return string 264 * @return string
254 */ 265 */
255 function column_configure( $item ) { 266 function column_configure( $item ) {
256 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>'; 267 $edit_link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) );
268 return '<a class="button um-email-configure" href="' . esc_url( $edit_link ) . '" title="' . esc_attr__( 'Manage', 'ultimate-member' ) . '">' . esc_html__( 'Manage', 'ultimate-member' ) . '</a>';
257 } 269 }
258 270
259 271
...@@ -278,10 +290,10 @@ class UM_Emails_List_Table extends WP_List_Table { ...@@ -278,10 +290,10 @@ class UM_Emails_List_Table extends WP_List_Table {
278 $ListTable = new UM_Emails_List_Table( array( 290 $ListTable = new UM_Emails_List_Table( array(
279 'singular' => __( 'Email Notification', 'ultimate-member' ), 291 'singular' => __( 'Email Notification', 'ultimate-member' ),
280 'plural' => __( 'Email Notifications', 'ultimate-member' ), 292 'plural' => __( 'Email Notifications', 'ultimate-member' ),
281 'ajax' => false 293 'ajax' => false,
282 )); 294 ));
283 295
284 $per_page = 20; 296 $per_page = 999;
285 $paged = $ListTable->get_pagenum(); 297 $paged = $ListTable->get_pagenum();
286 298
287 /** 299 /**
...@@ -317,18 +329,21 @@ $emails = UM()->config()->email_notifications; ...@@ -317,18 +329,21 @@ $emails = UM()->config()->email_notifications;
317 329
318 $ListTable->prepare_items(); 330 $ListTable->prepare_items();
319 $ListTable->items = array_slice( $emails, ( $paged - 1 ) * $per_page, $per_page ); 331 $ListTable->items = array_slice( $emails, ( $paged - 1 ) * $per_page, $per_page );
320 $ListTable->wpc_set_pagination_args( array( 'total_items' => count( $emails ), 'per_page' => $per_page ) ); ?> 332 $ListTable->wpc_set_pagination_args( array( 'total_items' => count( $emails ), 'per_page' => $per_page ) );
321 333 ?>
322 <p class="description" style="margin: 20px 0 0 0;"> 334
323 <?php 335 <h2 class="title"><?php esc_html_e( 'Email notifications', 'ultimate-member' ); ?></h2>
324 // translators: %s: doc link. 336 <p>
325 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' ) ); 337 <?php esc_html_e( 'Email notifications sent from Ultimate Member are listed below. Click on an email to configure it.', 'ultimate-member' ); ?>
326 ?> 338 <br />
339 <?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' ); ?>
340 <?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' ) ); ?>
327 </p> 341 </p>
328 342 <div class="clear"></div>
329 <form action="" method="get" name="um-settings-emails" id="um-settings-emails"> 343 <form action="" method="get" name="um-settings-emails" id="um-settings-emails">
330 <input type="hidden" name="page" value="um_options" /> 344 <input type="hidden" name="page" value="um_options" />
331 <input type="hidden" name="tab" value="email" /> 345 <input type="hidden" name="tab" value="email" />
332 346
333 <?php $ListTable->display(); ?> 347 <?php $ListTable->display(); ?>
334 </form> 348 </form>
349 <div class="clear"></div>
......
...@@ -58,8 +58,7 @@ class UM_Versions_List_Table extends WP_List_Table { ...@@ -58,8 +58,7 @@ class UM_Versions_List_Table extends WP_List_Table {
58 $sortable = $this->get_sortable_columns(); 58 $sortable = $this->get_sortable_columns();
59 $this->_column_headers = array( $columns, array(), $sortable ); 59 $this->_column_headers = array( $columns, array(), $sortable );
60 60
61 $templates = get_option( 'um_template_statuses', array() ); 61 $templates = UM()->common()->theme()->build_templates_data();
62 $templates = is_array( $templates ) ? $templates : array();
63 62
64 @uasort( 63 @uasort(
65 $templates, 64 $templates,
...@@ -163,6 +162,16 @@ class UM_Versions_List_Table extends WP_List_Table { ...@@ -163,6 +162,16 @@ class UM_Versions_List_Table extends WP_List_Table {
163 $icon = 1 === $item['status_code'] ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt'; 162 $icon = 1 === $item['status_code'] ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt';
164 return $item['status'] . ' <span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span>'; 163 return $item['status'] . ' <span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span>';
165 } 164 }
165
166 /**
167 * Generates the table navigation above or below the table
168 *
169 * @since 3.1.0
170 * @param string $which
171 */
172 protected function display_tablenav( $which ) {
173 // Stop displaying tablenav.
174 }
166 } 175 }
167 176
168 $list_table = new UM_Versions_List_Table( 177 $list_table = new UM_Versions_List_Table(
...@@ -210,6 +219,7 @@ $list_table->prepare_items(); ...@@ -210,6 +219,7 @@ $list_table->prepare_items();
210 219
211 <form action="" method="get" name="um-settings-template-versions" id="um-settings-template-versions"> 220 <form action="" method="get" name="um-settings-template-versions" id="um-settings-template-versions">
212 <input type="hidden" name="page" value="um_options" /> 221 <input type="hidden" name="page" value="um_options" />
213 <input type="hidden" name="tab" value="override_templates" /> 222 <input type="hidden" name="tab" value="advanced" />
223 <input type="hidden" name="section" value="override_templates" />
214 <?php $list_table->display(); ?> 224 <?php $list_table->display(); ?>
215 </form> 225 </form>
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
70 </td> 70 </td>
71 <td class="last t"> 71 <td class="last t">
72 <a href="<?php echo esc_url( admin_url( 'users.php?um_status=awaiting_email_confirmation' ) ); ?>" class="warning"> 72 <a href="<?php echo esc_url( admin_url( 'users.php?um_status=awaiting_email_confirmation' ) ); ?>" class="warning">
73 <?php _e( 'Awaiting E-mail Confirmation', 'ultimate-member' ); ?> 73 <?php _e( 'Awaiting Email Confirmation', 'ultimate-member' ); ?>
74 </a> 74 </a>
75 </td> 75 </td>
76 </tr> 76 </tr>
......
...@@ -166,12 +166,12 @@ $premium['profile-tabs'] = array( ...@@ -166,12 +166,12 @@ $premium['profile-tabs'] = array(
166 'desc' => 'Add custom tabs to profiles', 166 'desc' => 'Add custom tabs to profiles',
167 ); 167 );
168 168
169 //$premium['stripe'] = array( 169 $premium['stripe'] = array(
170 // 'url' => 'https://ultimatemember.com/extensions/stripe/', 170 'url' => 'https://ultimatemember.com/extensions/stripe/',
171 // 'img' => 'stripe.png', 171 'img' => 'stripe.png',
172 // 'name' => 'Stripe', 172 'name' => 'Stripe',
173 // 'desc' => 'Sell paid memberships to access your website via Stripe subscriptions', 173 'desc' => 'Sell paid memberships to access your website via Stripe subscriptions',
174 //); 174 );
175 175
176 $free['jobboardwp'] = array( 176 $free['jobboardwp'] = array(
177 'url' => 'https://wordpress.org/plugins/um-jobboardwp', 177 'url' => 'https://wordpress.org/plugins/um-jobboardwp',
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
43 'id' => '_um_can_delete_everyone', 43 'id' => '_um_can_delete_everyone',
44 'type' => 'checkbox', 44 'type' => 'checkbox',
45 'label' => __( 'Can delete other member accounts?', 'ultimate-member' ), 45 'label' => __( 'Can delete other member accounts?', 'ultimate-member' ),
46 'tooltip' => __( 'Allow this role to edit accounts of other members', 'ultimate-member' ), 46 'tooltip' => __( 'Allow this role to delete other user accounts.', 'ultimate-member' ),
47 'value' => ! empty( $role['_um_can_delete_everyone'] ) ? $role['_um_can_delete_everyone'] : 0, 47 'value' => ! empty( $role['_um_can_delete_everyone'] ) ? $role['_um_can_delete_everyone'] : 0,
48 ), 48 ),
49 array( 49 array(
......
1 <?php if ( ! defined( 'ABSPATH' ) ) { 1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
2 exit; 3 exit;
3 } 4 }
4 5
5 $role = $object['data']; ?> 6 $role = $object['data'];
7 ?>
6 8
7 <div class="um-admin-metabox"> 9 <div class="um-admin-metabox">
8 <?php 10 <?php
9 UM()->admin_forms( 11 $form = UM()->admin_forms(
10 array( 12 array(
11 'class' => 'um-role-publish um-top-label', 13 'class' => 'um-role-publish um-top-label',
12 'prefix_id' => 'role', 14 'prefix_id' => 'role',
...@@ -20,7 +22,8 @@ $role = $object['data']; ?> ...@@ -20,7 +22,8 @@ $role = $object['data']; ?>
20 ), 22 ),
21 ), 23 ),
22 ) 24 )
23 )->render_form(); 25 );
26 $form->render_form();
24 ?> 27 ?>
25 </div> 28 </div>
26 29
...@@ -31,3 +34,10 @@ $role = $object['data']; ?> ...@@ -31,3 +34,10 @@ $role = $object['data']; ?>
31 <div class="clear"></div> 34 <div class="clear"></div>
32 </div> 35 </div>
33 </div> 36 </div>
37 <?php
38 echo $form->render_external_link(
39 array(
40 'html' => __( 'Learn more about role priorities', 'ultimate-member' ),
41 'url' => 'https://docs.ultimatemember.com/article/1494-how-to-set-role-priority-for-user-roles',
42 )
43 );
......
...@@ -76,8 +76,8 @@ ...@@ -76,8 +76,8 @@
76 array( 76 array(
77 'id' => '_um_url_email_activate', 77 'id' => '_um_url_email_activate',
78 'type' => 'text', 78 'type' => 'text',
79 'label' => __( 'URL redirect after e-mail activation', 'ultimate-member' ), 79 'label' => __( 'URL redirect after email activation', 'ultimate-member' ),
80 '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' ), 80 'tooltip' => __( 'If you want users to go to a specific page other than login page after email activation, enter the URL here.', 'ultimate-member' ),
81 'value' => ! empty( $role['_um_url_email_activate'] ) ? __( $role['_um_url_email_activate'], 'ultimate-member' ) : '', 81 'value' => ! empty( $role['_um_url_email_activate'] ) ? __( $role['_um_url_email_activate'], 'ultimate-member' ) : '',
82 'conditional' => array( '_um_status', '=', 'checkmail' ), 82 'conditional' => array( '_um_status', '=', 'checkmail' ),
83 ), 83 ),
......
...@@ -20,10 +20,23 @@ if ( ! class_exists( 'um\ajax\Init' ) ) { ...@@ -20,10 +20,23 @@ if ( ! class_exists( 'um\ajax\Init' ) ) {
20 * @used-by \UM::includes() 20 * @used-by \UM::includes()
21 */ 21 */
22 public function includes() { 22 public function includes() {
23 $this->pages();
23 $this->secure(); 24 $this->secure();
24 } 25 }
25 26
26 /** 27 /**
28 * @since 2.8.3
29 *
30 * @return Pages
31 */
32 public function pages() {
33 if ( empty( UM()->classes['um\ajax\pages'] ) ) {
34 UM()->classes['um\ajax\pages'] = new Pages();
35 }
36 return UM()->classes['um\ajax\pages'];
37 }
38
39 /**
27 * @since 2.6.8 40 * @since 2.6.8
28 * 41 *
29 * @return Secure 42 * @return Secure
......
1 <?php
2 namespace um\ajax;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Class Pages
10 *
11 * @package um\ajax
12 */
13 class Pages {
14
15 /**
16 * Pages constructor.
17 */
18 public function __construct() {
19 add_action( 'wp_ajax_um_get_pages_list', array( $this, 'get_pages_list' ) );
20 }
21
22 /**
23 * AJAX callback for getting the pages list
24 */
25 public function get_pages_list() {
26 UM()->admin()->check_ajax_nonce();
27
28 // we will pass post IDs and titles to this array
29 $return = array();
30
31 $pre_result = apply_filters( 'um_admin_settings_get_pages_list', false );
32
33 if ( false === $pre_result ) {
34 $query_args = array(
35 'post_type' => 'page',
36 'post_status' => 'publish', // if you don't want drafts to be returned
37 'ignore_sticky_posts' => 1,
38 'posts_per_page' => 10, // how much to show at once
39 'paged' => absint( $_GET['page'] ),
40 'orderby' => 'title',
41 'order' => 'asc',
42 );
43
44 if ( ! empty( $_GET['search'] ) ) {
45 $query_args['s'] = sanitize_text_field( $_GET['search'] ); // the search query
46 }
47
48 $search_results = new \WP_Query( $query_args );
49
50 if ( $search_results->have_posts() ) {
51 while ( $search_results->have_posts() ) {
52 $search_results->the_post();
53
54 // shorten the title a little
55 $title = ( mb_strlen( $search_results->post->post_title ) > 50 ) ? mb_substr( $search_results->post->post_title, 0, 49 ) . '...' : $search_results->post->post_title;
56 $title = sprintf( __( '%s (ID: %s)', 'ultimate-member' ), $title, $search_results->post->ID );
57 $return[] = array( $search_results->post->ID, $title ); // array( Post ID, Post Title )
58 }
59 }
60
61 $return['total_count'] = $search_results->found_posts;
62 } else {
63 // got already calculated posts array from 3rd-party integrations (e.g. WPML, Polylang)
64 $return = $pre_result;
65 }
66
67 wp_send_json( $return );
68 }
69 }
...@@ -282,10 +282,10 @@ class Secure { ...@@ -282,10 +282,10 @@ class Secure {
282 282
283 $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>'; 283 $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>';
284 if ( $suspicious_accounts_count > 0 ) { 284 if ( $suspicious_accounts_count > 0 ) {
285 $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' ) ); 285 $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' ) );
286 $content .= $br . esc_html__( '1. Please temporarily lock all your active Register forms.', 'ultimate-member' ); 286 $content .= $br . esc_html__( '1. Please temporarily lock all your active Register forms.', 'ultimate-member' );
287 $content .= ' <a href="' . esc_attr( $lock_register_forms_url ) . '" target="_blank">' . esc_html__( 'Click here to lock them now.', 'ultimate-member' ) . '</a>'; 287 $content .= ' <a href="' . esc_attr( $lock_register_forms_url ) . '" target="_blank">' . esc_html__( 'Click here to lock them now.', 'ultimate-member' ) . '</a>';
288 $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' ); 288 $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' );
289 $content .= $br . $br; 289 $content .= $br . $br;
290 $suspicious_accounts_url = admin_url( 'users.php?um_status=inactive' ); 290 $suspicious_accounts_url = admin_url( 'users.php?um_status=inactive' );
291 291
......
...@@ -228,7 +228,8 @@ if ( ! class_exists( 'UM' ) ) { ...@@ -228,7 +228,8 @@ if ( ! class_exists( 'UM' ) ) {
228 // init widgets 228 // init widgets
229 add_action( 'widgets_init', array( &$this, 'widgets_init' ) ); 229 add_action( 'widgets_init', array( &$this, 'widgets_init' ) );
230 230
231 //include short non class functions 231 // Include short non-class functions
232 require_once 'um-core-functions.php';
232 require_once 'um-short-functions.php'; 233 require_once 'um-short-functions.php';
233 require_once 'um-deprecated-functions.php'; 234 require_once 'um-deprecated-functions.php';
234 } 235 }
...@@ -585,8 +586,6 @@ if ( ! class_exists( 'UM' ) ) { ...@@ -585,8 +586,6 @@ if ( ! class_exists( 'UM' ) ) {
585 $this->theme_updater(); 586 $this->theme_updater();
586 } elseif ( $this->is_request( 'frontend' ) ) { 587 } elseif ( $this->is_request( 'frontend' ) ) {
587 $this->frontend()->includes(); 588 $this->frontend()->includes();
588 $this->account();
589 $this->password();
590 $this->login(); 589 $this->login();
591 $this->register(); 590 $this->register();
592 $this->user_posts(); 591 $this->user_posts();
...@@ -594,6 +593,8 @@ if ( ! class_exists( 'UM' ) ) { ...@@ -594,6 +593,8 @@ if ( ! class_exists( 'UM' ) ) {
594 } 593 }
595 594
596 //common includes 595 //common includes
596 $this->account();
597 $this->password();
597 $this->rewrite(); 598 $this->rewrite();
598 $this->mail(); 599 $this->mail();
599 $this->rest_api(); 600 $this->rest_api();
......
...@@ -24,6 +24,7 @@ if ( ! class_exists( 'um\common\Init' ) ) { ...@@ -24,6 +24,7 @@ if ( ! class_exists( 'um\common\Init' ) ) {
24 $this->screen(); 24 $this->screen();
25 $this->secure()->hooks(); 25 $this->secure()->hooks();
26 $this->site_health(); 26 $this->site_health();
27 $this->theme()->hooks();
27 } 28 }
28 29
29 /** 30 /**
...@@ -73,5 +74,17 @@ if ( ! class_exists( 'um\common\Init' ) ) { ...@@ -73,5 +74,17 @@ if ( ! class_exists( 'um\common\Init' ) ) {
73 } 74 }
74 return UM()->classes['um\common\site_health']; 75 return UM()->classes['um\common\site_health'];
75 } 76 }
77
78 /**
79 * @since 2.8.3
80 *
81 * @return Theme
82 */
83 public function theme() {
84 if ( empty( UM()->classes['um\common\theme'] ) ) {
85 UM()->classes['um\common\theme'] = new Theme();
86 }
87 return UM()->classes['um\common\theme'];
88 }
76 } 89 }
77 } 90 }
......
...@@ -18,7 +18,7 @@ if ( ! class_exists( 'um\common\Screen' ) ) { ...@@ -18,7 +18,7 @@ if ( ! class_exists( 'um\common\Screen' ) ) {
18 * Screen constructor. 18 * Screen constructor.
19 */ 19 */
20 public function __construct() { 20 public function __construct() {
21 add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000, 1 ); 21 add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000 );
22 } 22 }
23 23
24 /** 24 /**
......
1 <?php
2 namespace um\common;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Class Theme
10 *
11 * @package um\common
12 */
13 class Theme {
14
15 public function hooks() {
16 add_action( 'after_switch_theme', array( &$this, 'flush_transient_templates_data' ) );
17 }
18
19 /**
20 * Find outdated UM templates and notify Administrator.
21 *
22 */
23 public function flush_transient_templates_data() {
24 // Flush transient with the custom templates list.
25 delete_transient( 'um_custom_templates_list' );
26 }
27
28 /**
29 * Scan the template files.
30 *
31 * @param string $template_path Path to the template directory.
32 * @return array
33 */
34 public static function scan_template_files( $template_path ) {
35 $files = @scandir( $template_path ); // @codingStandardsIgnoreLine.
36 $result = array();
37
38 if ( ! empty( $files ) ) {
39
40 foreach ( $files as $value ) {
41
42 if ( ! in_array( $value, array( '.', '..' ), true ) ) {
43
44 if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
45 $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
46 foreach ( $sub_files as $sub_file ) {
47 $result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
48 }
49 } else {
50 $result[] = $value;
51 }
52 }
53 }
54 }
55 return $result;
56 }
57
58 public static function get_all_templates() {
59 $scan_files['um'] = self::scan_template_files( UM_PATH . '/templates/' );
60 /**
61 * Filters an array of the template files for scanning versions.
62 *
63 * @since 2.6.1
64 * @hook um_override_templates_scan_files
65 *
66 * @param {array} $scan_files Template files for scanning versions.
67 *
68 * @return {array} Template files for scanning versions.
69 */
70 return apply_filters( 'um_override_templates_scan_files', $scan_files );
71 }
72
73 /**
74 * @param $file string
75 *
76 * @return string
77 */
78 public static function get_file_version( $file ) {
79 // Avoid notices if file does not exist.
80 if ( ! file_exists( $file ) ) {
81 return '';
82 }
83
84 // We don't need to write to the file, so just open for reading.
85 $fp = fopen( $file, 'r' ); // @codingStandardsIgnoreLine.
86
87 // Pull only the first 8kiB of the file in.
88 $file_data = fread( $fp, 8192 ); // @codingStandardsIgnoreLine.
89
90 // PHP will close a file handle, but we are good citizens.
91 fclose( $fp ); // @codingStandardsIgnoreLine.
92
93 // Make sure we catch CR-only line endings.
94 $file_data = str_replace( "\r", "\n", $file_data );
95 $version = '';
96
97 if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) {
98 $version = _cleanup_header_comment( $match[1] );
99 }
100
101 return $version;
102 }
103
104 public function get_custom_templates_list() {
105 $files_in_theme = array();
106 $scan_files = self::get_all_templates();
107 foreach ( $scan_files as $key => $files ) {
108 foreach ( $files as $file ) {
109 if ( false === strpos( $file, 'email/' ) ) {
110 /**
111 * Filters an array of the template files for scanning versions based on $key.
112 *
113 * Note: $key - means um or extension key.
114 *
115 * @since 2.6.1
116 * @hook um_override_templates_get_template_path__{$key}
117 *
118 * @param {array} $located Template file paths for scanning versions.
119 * @param {string} $file Template file name.
120 *
121 * @return {array} Template file paths for scanning versions.
122 */
123 $located = apply_filters( "um_override_templates_get_template_path__{$key}", array(), $file );
124
125 $exceptions = array(
126 'members-grid.php',
127 'members-header.php',
128 'members-list.php',
129 'members-pagination.php',
130 'searchform.php',
131 'login-to-view.php',
132 'profile/comments.php',
133 'profile/comments-single.php',
134 'profile/posts.php',
135 'profile/posts-single.php',
136 'modal/um_upload_single.php',
137 'modal/um_view_photo.php',
138 );
139
140 $theme_file = false;
141 if ( ! empty( $located ) ) {
142 $theme_file = $located['theme'];
143 } elseif ( in_array( $file, $exceptions, true ) && file_exists( get_stylesheet_directory() . '/ultimate-member/' . $file ) ) {
144 $theme_file = get_stylesheet_directory() . '/ultimate-member/' . $file;
145 } elseif ( file_exists( get_stylesheet_directory() . '/ultimate-member/templates/' . $file ) ) {
146 $theme_file = get_stylesheet_directory() . '/ultimate-member/templates/' . $file;
147 }
148
149 if ( ! empty( $theme_file ) ) {
150 if ( ! empty( $located ) ) {
151 $core_path = $located['core'];
152 } else {
153 $core_path = UM_PATH . 'templates/' . $file;
154 }
155
156 $files_in_theme[] = array(
157 'core' => $core_path,
158 'theme' => $theme_file,
159 );
160 }
161 }
162 }
163 }
164
165 return $files_in_theme;
166 }
167
168 public function is_outdated_template_exist() {
169 $outdated_exists = false;
170 $templates = $this->get_custom_templates_list();
171 foreach ( $templates as $files ) {
172 if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) {
173 continue;
174 }
175
176 $core_path = $files['core'];
177 $theme_file = $files['theme'];
178
179 $core_version = self::get_file_version( $core_path );
180 $theme_version = self::get_file_version( $theme_file );
181
182 if ( '' === $theme_version || version_compare( $theme_version, $core_version, '<' ) ) {
183 $outdated_exists = true;
184 break;
185 }
186 }
187
188 return $outdated_exists;
189 }
190
191 public function build_templates_data() {
192 $templates_data = array();
193
194 // Get from cache if isn't empty and request isn't force.
195 $transient = get_transient( 'um_custom_templates_list' );
196 if ( false !== $transient && array_key_exists( 'data', $transient ) ) {
197 return $transient['data'];
198 }
199
200 $templates = $this->get_custom_templates_list();
201 foreach ( $templates as $files ) {
202 if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) {
203 continue;
204 }
205
206 $core_path = $files['core'];
207 $theme_file = $files['theme'];
208
209 $core_version = self::get_file_version( $core_path );
210 $theme_version = self::get_file_version( $theme_file );
211
212 $status = esc_html__( 'Theme version up to date', 'ultimate-member' );
213 $status_code = 1;
214
215 if ( '' === $theme_version ) {
216 $status = esc_html__( 'Theme version is empty', 'ultimate-member' );
217 $status_code = 0;
218 } elseif ( version_compare( $theme_version, $core_version, '<' ) ) {
219 $status = esc_html__( 'Theme version is out of date', 'ultimate-member' );
220 $status_code = 0;
221 }
222
223 $templates_data[] = array(
224 'core_version' => $core_version,
225 'theme_version' => $theme_version,
226 'core_file' => stristr( $core_path, 'wp-content' ),
227 'theme_file' => stristr( $theme_file, 'wp-content' ),
228 'status' => $status,
229 'status_code' => $status_code,
230 );
231 }
232
233 // Cache results via transient setting.
234 $transient = array(
235 'data' => $templates_data,
236 'time' => time(),
237 );
238 set_transient( 'um_custom_templates_list', $transient, 5 * MINUTE_IN_SECONDS );
239
240 return $templates_data;
241 }
242 }
...@@ -273,7 +273,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -273,7 +273,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
273 ), 273 ),
274 274
275 'tel' => array( 275 'tel' => array(
276 'name' => __( 'Telephone Box', 'ultimate-member' ), 276 'name' => __( 'Telephone', 'ultimate-member' ),
277 'col1' => array('_title','_metakey','_help','_default','_min_chars','_visibility'), 277 'col1' => array('_title','_metakey','_help','_default','_min_chars','_visibility'),
278 'col2' => array('_label','_placeholder','_public','_roles','_validate','_custom_validate','_max_chars'), 278 'col2' => array('_label','_placeholder','_public','_roles','_validate','_custom_validate','_max_chars'),
279 'col3' => array('_required','_editable','_icon'), 279 'col3' => array('_required','_editable','_icon'),
...@@ -782,10 +782,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -782,10 +782,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
782 ), 782 ),
783 783
784 'username' => array( 784 'username' => array(
785 'title' => __('Username or E-mail','ultimate-member'), 785 'title' => __('Username or Email','ultimate-member'),
786 'metakey' => 'username', 786 'metakey' => 'username',
787 'type' => 'text', 787 'type' => 'text',
788 'label' => __('Username or E-mail','ultimate-member'), 788 'label' => __('Username or Email','ultimate-member'),
789 'required' => 1, 789 'required' => 1,
790 'public' => 1, 790 'public' => 1,
791 'editable' => false, 791 'editable' => false,
...@@ -871,10 +871,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -871,10 +871,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
871 ), 871 ),
872 872
873 'user_email' => array( 873 'user_email' => array(
874 'title' => __('E-mail Address','ultimate-member'), 874 'title' => __('Email Address','ultimate-member'),
875 'metakey' => 'user_email', 875 'metakey' => 'user_email',
876 'type' => 'text', 876 'type' => 'text',
877 'label' => __('E-mail Address','ultimate-member'), 877 'label' => __('Email Address','ultimate-member'),
878 'required' => 0, 878 'required' => 0,
879 'public' => 1, 879 'public' => 1,
880 'validate' => 'unique_email', 880 'validate' => 'unique_email',
...@@ -882,10 +882,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -882,10 +882,10 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
882 ), 882 ),
883 883
884 'secondary_user_email' => array( 884 'secondary_user_email' => array(
885 'title' => __('Secondary E-mail Address','ultimate-member'), 885 'title' => __('Secondary Email Address','ultimate-member'),
886 'metakey' => 'secondary_user_email', 886 'metakey' => 'secondary_user_email',
887 'type' => 'text', 887 'type' => 'text',
888 'label' => __('Secondary E-mail Address','ultimate-member'), 888 'label' => __('Secondary Email Address','ultimate-member'),
889 'required' => 0, 889 'required' => 0,
890 'public' => 1, 890 'public' => 1,
891 'editable' => true, 891 'editable' => true,
...@@ -1271,7 +1271,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -1271,7 +1271,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
1271 ), 1271 ),
1272 1272
1273 'username_b' => array( 1273 'username_b' => array(
1274 'title' => __('Username or E-mail','ultimate-member'), 1274 'title' => __('Username or Email','ultimate-member'),
1275 'metakey' => 'username_b', 1275 'metakey' => 'username_b',
1276 'type' => 'text', 1276 'type' => 'text',
1277 'placeholder' => __('Enter your username or email','ultimate-member'), 1277 'placeholder' => __('Enter your username or email','ultimate-member'),
...@@ -1558,11 +1558,11 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { ...@@ -1558,11 +1558,11 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
1558 $array['skype'] = __('Skype ID','ultimate-member'); 1558 $array['skype'] = __('Skype ID','ultimate-member');
1559 $array['soundcloud'] = __( 'SoundCloud Profile', 'ultimate-member' ); 1559 $array['soundcloud'] = __( 'SoundCloud Profile', 'ultimate-member' );
1560 $array['twitter_url'] = __( 'X (formerly Twitter) URL', 'ultimate-member' ); 1560 $array['twitter_url'] = __( 'X (formerly Twitter) URL', 'ultimate-member' );
1561 $array['is_email'] = __('E-mail( Not Unique )','ultimate-member'); 1561 $array['is_email'] = __('Email( Not Unique )','ultimate-member');
1562 $array['unique_email'] = __('Unique E-mail','ultimate-member'); 1562 $array['unique_email'] = __('Unique Email','ultimate-member');
1563 $array['unique_value'] = __('Unique Metakey value','ultimate-member'); 1563 $array['unique_value'] = __('Unique Metakey value','ultimate-member');
1564 $array['unique_username'] = __('Unique Username','ultimate-member'); 1564 $array['unique_username'] = __('Unique Username','ultimate-member');
1565 $array['unique_username_or_email'] = __('Unique Username/E-mail','ultimate-member'); 1565 $array['unique_username_or_email'] = __('Unique Username/Email','ultimate-member');
1566 $array['url'] = __('Website URL','ultimate-member'); 1566 $array['url'] = __('Website URL','ultimate-member');
1567 $array['youtube_url'] = __('YouTube Profile','ultimate-member'); 1567 $array['youtube_url'] = __('YouTube Profile','ultimate-member');
1568 $array['youtube_video'] = __('YouTube Video','ultimate-member'); 1568 $array['youtube_video'] = __('YouTube Video','ultimate-member');
......
...@@ -623,7 +623,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) { ...@@ -623,7 +623,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
623 * @return string 623 * @return string
624 */ 624 */
625 public function show_error( $key ) { 625 public function show_error( $key ) {
626 return UM()->form()->errors[ $key ]; 626 if ( empty( UM()->form()->errors ) ) {
627 return '';
628 }
629 return array_key_exists( $key, UM()->form()->errors ) ? UM()->form()->errors[ $key ] : '';
627 } 630 }
628 631
629 /** 632 /**
...@@ -634,7 +637,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) { ...@@ -634,7 +637,10 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
634 * @return string 637 * @return string
635 */ 638 */
636 public function show_notice( $key ) { 639 public function show_notice( $key ) {
637 return UM()->form()->notices[ $key ]; 640 if ( empty( UM()->form()->notices ) ) {
641 return '';
642 }
643 return array_key_exists( $key, UM()->form()->notices ) ? UM()->form()->notices[ $key ] : '';
638 } 644 }
639 645
640 /** 646 /**
......
...@@ -305,7 +305,7 @@ if ( ! class_exists( 'um\core\Mail' ) ) { ...@@ -305,7 +305,7 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
305 * } 305 * }
306 * add_filter( 'um_email_template_body_attrs', 'my_email_template_body_attrs', 10, 3 ); 306 * add_filter( 'um_email_template_body_attrs', 'my_email_template_body_attrs', 10, 3 );
307 */ 307 */
308 $body_attrs = apply_filters( 'um_email_template_body_attrs', 'style="background: #f2f2f2;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;"', $slug, $args ); 308 $body_attrs = apply_filters( 'um_email_template_body_attrs', 'style="background: #fff;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;"', $slug, $args );
309 ?> 309 ?>
310 310
311 <body <?php echo $body_attrs; ?>> 311 <body <?php echo $body_attrs; ?>>
...@@ -351,8 +351,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) { ...@@ -351,8 +351,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
351 */ 351 */
352 $message = apply_filters( 'um_email_send_message_content', $message, $slug, $args ); 352 $message = apply_filters( 'um_email_send_message_content', $message, $slug, $args );
353 353
354 add_filter( 'um_template_tags_patterns_hook', array( &$this, 'add_placeholder' ) ); 354 // add_filter( 'um_template_tags_patterns_hook', array( &$this, 'add_placeholder' ) );
355 add_filter( 'um_template_tags_replaces_hook', array( &$this, 'add_replace_placeholder' ) ); 355 // add_filter( 'um_template_tags_replaces_hook', array( &$this, 'add_replace_placeholder' ) );
356 356
357 // Convert tags in email template. 357 // Convert tags in email template.
358 return um_convert_tags( $message, $args ); 358 return um_convert_tags( $message, $args );
...@@ -421,8 +421,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) { ...@@ -421,8 +421,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
421 $mail_from_addr = UM()->options()->get( 'mail_from_addr' ) ? UM()->options()->get( 'mail_from_addr' ) : get_bloginfo( 'admin_email' ); 421 $mail_from_addr = UM()->options()->get( 'mail_from_addr' ) ? UM()->options()->get( 'mail_from_addr' ) : get_bloginfo( 'admin_email' );
422 $this->headers = 'From: ' . stripslashes( $mail_from ) . ' <' . $mail_from_addr . '>' . "\r\n"; 422 $this->headers = 'From: ' . stripslashes( $mail_from ) . ' <' . $mail_from_addr . '>' . "\r\n";
423 423
424 add_filter( 'um_template_tags_patterns_hook', array( UM()->mail(), 'add_placeholder' ) ); 424 add_filter( 'um_template_tags_patterns_hook', array( $this, 'add_placeholder' ) );
425 add_filter( 'um_template_tags_replaces_hook', array( UM()->mail(), 'add_replace_placeholder' ) ); 425 add_filter( 'um_template_tags_replaces_hook', array( $this, 'add_replace_placeholder' ) );
426 426
427 /** 427 /**
428 * Filters email notification subject. 428 * Filters email notification subject.
...@@ -623,6 +623,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) { ...@@ -623,6 +623,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
623 $placeholders[] = '{login_url}'; 623 $placeholders[] = '{login_url}';
624 $placeholders[] = '{password}'; 624 $placeholders[] = '{password}';
625 $placeholders[] = '{account_activation_link}'; 625 $placeholders[] = '{account_activation_link}';
626 $placeholders[] = '{action_url}';
627 $placeholders[] = '{action_title}';
626 return $placeholders; 628 return $placeholders;
627 } 629 }
628 630
...@@ -641,6 +643,16 @@ if ( ! class_exists( 'um\core\Mail' ) ) { ...@@ -641,6 +643,16 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
641 $replace_placeholders[] = um_get_core_page( 'login' ); 643 $replace_placeholders[] = um_get_core_page( 'login' );
642 $replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' ); 644 $replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' );
643 $replace_placeholders[] = um_user( 'account_activation_link' ); 645 $replace_placeholders[] = um_user( 'account_activation_link' );
646
647 $set_password_required = get_user_meta( um_user( 'ID' ), 'um_set_password_required', true );
648 if ( empty( $set_password_required ) || 'pending' === um_user( 'status' ) ) {
649 $replace_placeholders[] = um_get_core_page( 'login' );
650 $replace_placeholders[] = esc_html__( 'Login to our site', 'ultimate-member' );
651 } else {
652 $replace_placeholders[] = um_user( 'password_reset_link' );
653 $replace_placeholders[] = esc_html__( 'Set your password', 'ultimate-member' );
654 }
655
644 return $replace_placeholders; 656 return $replace_placeholders;
645 } 657 }
646 } 658 }
......
...@@ -58,7 +58,11 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -58,7 +58,11 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
58 58
59 var $filter_types = array(); 59 var $filter_types = array();
60 60
61 61 /**
62 * Fields used for searching from wp_users table.
63 *
64 * @var string[]
65 */
62 var $core_search_fields = array( 66 var $core_search_fields = array(
63 'user_login', 67 'user_login',
64 'user_url', 68 'user_url',
...@@ -67,6 +71,19 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -67,6 +71,19 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
67 'user_nicename', 71 'user_nicename',
68 ); 72 );
69 73
74 /**
75 * Fields used for sorting from wp_users table.
76 *
77 * @var string[]
78 */
79 var $core_users_fields = array(
80 'user_login',
81 'user_url',
82 'display_name',
83 'user_email',
84 'user_nicename',
85 'user_registered',
86 );
70 87
71 /** 88 /**
72 * @var 89 * @var
...@@ -408,7 +425,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -408,7 +425,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
408 'first_name' => __( 'First Name', 'ultimate-member' ), 425 'first_name' => __( 'First Name', 'ultimate-member' ),
409 'last_name' => __( 'Last Name', 'ultimate-member' ), 426 'last_name' => __( 'Last Name', 'ultimate-member' ),
410 'nickname' => __( 'Nickname', 'ultimate-member' ), 427 'nickname' => __( 'Nickname', 'ultimate-member' ),
411 'secondary_user_email' => __( 'Secondary E-mail Address', 'ultimate-member' ), 428 'secondary_user_email' => __( 'Secondary Email Address', 'ultimate-member' ),
412 'description' => __( 'Biography', 'ultimate-member' ), 429 'description' => __( 'Biography', 'ultimate-member' ),
413 'phone_number' => __( 'Phone Number', 'ultimate-member' ), 430 'phone_number' => __( 'Phone Number', 'ultimate-member' ),
414 'mobile_number' => __( 'Mobile Number', 'ultimate-member' ), 431 'mobile_number' => __( 'Mobile Number', 'ultimate-member' ),
...@@ -1314,17 +1331,17 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -1314,17 +1331,17 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
1314 $this->query_args['paged'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; 1331 $this->query_args['paged'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
1315 } 1332 }
1316 1333
1317
1318 /** 1334 /**
1319 * Add sorting attributes for \WP_Users_Query 1335 * Add sorting attributes for \WP_Users_Query
1320 * 1336 *
1321 * @param array $directory_data Member Directory options 1337 * @param array $directory_data Member Directory options
1322 */ 1338 */
1323 function sorting_query( $directory_data ) { 1339 public function sorting_query( $directory_data ) {
1324 // sort members by 1340 // sort members by
1325 $this->query_args['order'] = 'ASC'; 1341 $this->query_args['order'] = 'ASC';
1342
1326 $sortby = ! empty( $_POST['sorting'] ) ? sanitize_text_field( $_POST['sorting'] ) : $directory_data['sortby']; 1343 $sortby = ! empty( $_POST['sorting'] ) ? sanitize_text_field( $_POST['sorting'] ) : $directory_data['sortby'];
1327 $sortby = ( $sortby == 'other' ) ? $directory_data['sortby_custom'] : $sortby; 1344 $sortby = ( 'other' === $sortby ) ? $directory_data['sortby_custom'] : $sortby;
1328 1345
1329 $custom_sort = array(); 1346 $custom_sort = array();
1330 if ( ! empty( $directory_data['sorting_fields'] ) ) { 1347 if ( ! empty( $directory_data['sorting_fields'] ) ) {
...@@ -1384,7 +1401,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -1384,7 +1401,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
1384 $this->query_args['order'] = 'ASC'; 1401 $this->query_args['order'] = 'ASC';
1385 } 1402 }
1386 1403
1387 } elseif ( in_array( $sortby, array( 'last_name', 'first_name', 'nickname' ) ) ) { 1404 } elseif ( in_array( $sortby, array( 'last_name', 'first_name', 'nickname' ), true ) ) {
1388 1405
1389 $this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $sortby . '_c' => array( 1406 $this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $sortby . '_c' => array(
1390 'key' => $sortby, 1407 'key' => $sortby,
...@@ -1426,7 +1443,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -1426,7 +1443,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
1426 $this->query_args['orderby'] = array( 'last_name_c' => 'ASC', 'first_name_c' => 'ASC' ); 1443 $this->query_args['orderby'] = array( 'last_name_c' => 'ASC', 'first_name_c' => 'ASC' );
1427 unset( $this->query_args['order'] ); 1444 unset( $this->query_args['order'] );
1428 1445
1429 } elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys ) ) { 1446 } elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys, true ) ) {
1430 1447
1431 $order = 'DESC'; 1448 $order = 'DESC';
1432 if ( strstr( $sortby, '_desc' ) ) { 1449 if ( strstr( $sortby, '_desc' ) ) {
...@@ -1458,18 +1475,23 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -1458,18 +1475,23 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
1458 ) 1475 )
1459 ); 1476 );
1460 1477
1461 $this->query_args['orderby'] = array( $sortby . '_ns' => $order, 'user_registered' => 'DESC' ); 1478 $this->query_args['orderby'] = array(
1479 $sortby . '_ns' => $order,
1480 'user_registered' => 'DESC',
1481 );
1462 unset( $this->query_args['order'] ); 1482 unset( $this->query_args['order'] );
1463 1483
1464 } elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby == $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort ) ) { 1484 } elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby === $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort, true ) ) {
1465 $custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC'; 1485 $custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC';
1466 1486
1467 $meta_query = new \WP_Meta_Query(); 1487 $meta_query = new \WP_Meta_Query();
1468 $custom_sort_type = ! empty( $directory_data['sortby_custom_type'] ) ? $meta_query->get_cast_for_type( $directory_data['sortby_custom_type'] ) : 'CHAR'; 1488 $custom_sort_type = ! empty( $directory_data['sortby_custom_type'] ) ? $meta_query->get_cast_for_type( $directory_data['sortby_custom_type'] ) : 'CHAR';
1489
1469 if ( ! empty( $directory_data['sorting_fields'] ) ) { 1490 if ( ! empty( $directory_data['sorting_fields'] ) ) {
1470 // phpcs:ignore WordPress.Security.NonceVerification -- already verified here 1491 // phpcs:ignore WordPress.Security.NonceVerification -- already verified here
1471 $sorting = sanitize_text_field( $_POST['sorting'] ); 1492 $sorting = sanitize_text_field( $_POST['sorting'] );
1472 $sorting_fields = maybe_serialize( $directory_data['sorting_fields'] ); 1493 $sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
1494
1473 if ( ! empty( $sorting_fields ) && is_array( $sorting_fields ) ) { 1495 if ( ! empty( $sorting_fields ) && is_array( $sorting_fields ) ) {
1474 foreach ( $sorting_fields as $field ) { 1496 foreach ( $sorting_fields as $field ) {
1475 if ( isset( $field[ $sorting ] ) ) { 1497 if ( isset( $field[ $sorting ] ) ) {
...@@ -2371,7 +2393,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2371,7 +2393,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2371 2393
2372 if ( UM()->roles()->um_current_user_can( 'edit', $user_id ) ) { 2394 if ( UM()->roles()->um_current_user_can( 'edit', $user_id ) ) {
2373 $actions['um-editprofile'] = array( 2395 $actions['um-editprofile'] = array(
2374 'title' => __( 'Edit Profile', 'ultimate-member' ), 2396 'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
2375 'url' => um_edit_profile_url(), 2397 'url' => um_edit_profile_url(),
2376 ); 2398 );
2377 } 2399 }
...@@ -2403,8 +2425,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2403,8 +2425,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2403 $url = add_query_arg( array( 'um_action' => $id, 'uid' => $user_id ), um_get_core_page( 'user' ) ); 2425 $url = add_query_arg( array( 'um_action' => $id, 'uid' => $user_id ), um_get_core_page( 'user' ) );
2404 2426
2405 $actions[ $id ] = array( 2427 $actions[ $id ] = array(
2406 'title' => $arr['label'], 2428 'title' => esc_html( $arr['label'] ),
2407 'url' => $url, 2429 'url' => esc_url( $url ),
2408 ); 2430 );
2409 } 2431 }
2410 } 2432 }
...@@ -2415,25 +2437,24 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2415,25 +2437,24 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2415 2437
2416 if ( empty( UM()->user()->cannot_edit ) ) { 2438 if ( empty( UM()->user()->cannot_edit ) ) {
2417 $actions['um-editprofile'] = array( 2439 $actions['um-editprofile'] = array(
2418 'title' => __( 'Edit Profile', 'ultimate-member' ), 2440 'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
2419 'url' => um_edit_profile_url(), 2441 'url' => um_edit_profile_url(),
2420 ); 2442 );
2421 } 2443 }
2422 2444
2423 $actions['um-myaccount'] = array( 2445 $actions['um-myaccount'] = array(
2424 'title' => __( 'My Account', 'ultimate-member' ), 2446 'title' => esc_html__( 'My Account', 'ultimate-member' ),
2425 'url' => um_get_core_page( 'account' ), 2447 'url' => um_get_core_page( 'account' ),
2426 ); 2448 );
2427 2449
2428 $actions['um-logout'] = array( 2450 $actions['um-logout'] = array(
2429 'title' => __( 'Logout', 'ultimate-member' ), 2451 'title' => esc_html__( 'Logout', 'ultimate-member' ),
2430 'url' => um_get_core_page( 'logout' ), 2452 'url' => um_get_core_page( 'logout' ),
2431 ); 2453 );
2432 2454
2433 $actions = apply_filters( 'um_member_directory_my_user_card_actions', $actions, $user_id ); 2455 $actions = apply_filters( 'um_member_directory_my_user_card_actions', $actions, $user_id );
2434 } 2456 }
2435 2457
2436
2437 return $actions; 2458 return $actions;
2438 } 2459 }
2439 2460
...@@ -2464,21 +2485,21 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2464,21 +2485,21 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2464 $hook_after_user_name = ob_get_clean(); 2485 $hook_after_user_name = ob_get_clean();
2465 2486
2466 $data_array = array( 2487 $data_array = array(
2467 'card_anchor' => substr( md5( $user_id ), 10, 5 ), 2488 'card_anchor' => esc_html( substr( md5( $user_id ), 10, 5 ) ),
2468 'id' => $user_id, 2489 'id' => absint( $user_id ),
2469 'role' => um_user( 'role' ), 2490 'role' => esc_html( um_user( 'role' ) ),
2470 'account_status' => um_user( 'account_status' ), 2491 'account_status' => esc_html( um_user( 'account_status' ) ),
2471 'account_status_name' => um_user( 'account_status_name' ), 2492 'account_status_name' => esc_html( um_user( 'account_status_name' ) ),
2472 'cover_photo' => um_user( 'cover_photo', $this->cover_size ), 2493 'cover_photo' => wp_kses( um_user( 'cover_photo', $this->cover_size ), UM()->get_allowed_html( 'templates' ) ),
2473 'display_name' => um_user( 'display_name' ), 2494 'display_name' => esc_html( um_user( 'display_name' ) ),
2474 'profile_url' => um_user_profile_url(), 2495 'profile_url' => esc_url( um_user_profile_url() ),
2475 'can_edit' => $can_edit, 2496 'can_edit' => (bool) $can_edit,
2476 'edit_profile_url' => um_edit_profile_url(), 2497 'edit_profile_url' => esc_url( um_edit_profile_url() ),
2477 'avatar' => get_avatar( $user_id, $this->avatar_size ), 2498 'avatar' => wp_kses( get_avatar( $user_id, $this->avatar_size ), UM()->get_allowed_html( 'templates' ) ),
2478 'display_name_html' => um_user( 'display_name', 'html' ), 2499 'display_name_html' => wp_kses( um_user( 'display_name', 'html' ), UM()->get_allowed_html( 'templates' ) ),
2479 'dropdown_actions' => $dropdown_actions, 2500 'dropdown_actions' => $dropdown_actions,
2480 'hook_just_after_name' => preg_replace( '/^\s+/im', '', $hook_just_after_name ), 2501 'hook_just_after_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_just_after_name ), UM()->get_allowed_html( 'templates' ) ),
2481 'hook_after_user_name' => preg_replace( '/^\s+/im', '', $hook_after_user_name ), 2502 'hook_after_user_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_after_user_name ), UM()->get_allowed_html( 'templates' ) ),
2482 ); 2503 );
2483 2504
2484 if ( ! empty( $directory_data['show_tagline'] ) ) { 2505 if ( ! empty( $directory_data['show_tagline'] ) ) {
...@@ -2498,7 +2519,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2498,7 +2519,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2498 continue; 2519 continue;
2499 } 2520 }
2500 2521
2501 $data_array[ $key ] = $value; 2522 $data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
2502 } 2523 }
2503 } 2524 }
2504 } 2525 }
...@@ -2529,8 +2550,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2529,8 +2550,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2529 ) ); 2550 ) );
2530 } 2551 }
2531 2552
2532 $data_array[ "label_{$key}" ] = __( $label, 'ultimate-member' ); 2553 $data_array[ "label_{$key}" ] = esc_html__( $label, 'ultimate-member' );
2533 $data_array[ $key ] = $value; 2554 $data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
2534 } 2555 }
2535 } 2556 }
2536 } 2557 }
...@@ -2540,7 +2561,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2540,7 +2561,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2540 UM()->fields()->show_social_urls(); 2561 UM()->fields()->show_social_urls();
2541 $social_urls = ob_get_clean(); 2562 $social_urls = ob_get_clean();
2542 2563
2543 $data_array['social_urls'] = $social_urls; 2564 $data_array['social_urls'] = wp_kses( $social_urls, UM()->get_allowed_html( 'templates' ) );
2544 } 2565 }
2545 } 2566 }
2546 2567
...@@ -2632,11 +2653,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ...@@ -2632,11 +2653,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
2632 'fields' => 'ids', 2653 'fields' => 'ids',
2633 'number' => 0, 2654 'number' => 0,
2634 'meta_query' => array( 2655 'meta_query' => array(
2635 'relation' => 'AND' 2656 'relation' => 'AND',
2636 ), 2657 ),
2637 ); 2658 );
2638 2659
2639
2640 // handle different restrictions 2660 // handle different restrictions
2641 $this->restriction_options(); 2661 $this->restriction_options();
2642 2662
......
1 <?php 1 <?php
2 namespace um\core; 2 namespace um\core;
3 3
4 // Exit if accessed directly 4 if ( ! defined( 'ABSPATH' ) ) {
5 if ( ! defined( 'ABSPATH' ) ) exit; 5 exit;
6 }
6 7
7 if ( ! class_exists( 'um\core\Options' ) ) { 8 if ( ! class_exists( 'um\core\Options' ) ) {
8 9
...@@ -125,6 +126,18 @@ if ( ! class_exists( 'um\core\Options' ) ) { ...@@ -125,6 +126,18 @@ if ( ! class_exists( 'um\core\Options' ) ) {
125 return $settings_defaults[ $option_id ]; 126 return $settings_defaults[ $option_id ];
126 } 127 }
127 128
129 /**
130 * Get predefined page option key
131 *
132 * @since 2.8.3
133 *
134 * @param string $slug
135 *
136 * @return string
137 */
138 public function get_predefined_page_option_key( $slug ) {
139 return apply_filters( 'um_predefined_page_option_key', "core_{$slug}" );
140 }
128 141
129 /** 142 /**
130 * Get core page ID 143 * Get core page ID
......
...@@ -38,20 +38,25 @@ if ( ! class_exists( 'um\core\Password' ) ) { ...@@ -38,20 +38,25 @@ if ( ! class_exists( 'um\core\Password' ) ) {
38 * 38 *
39 * @return bool|string 39 * @return bool|string
40 */ 40 */
41 function reset_url() { 41 public function reset_url() {
42 static $reset_key = null;
43
42 $user_id = um_user( 'ID' ); 44 $user_id = um_user( 'ID' );
43 45
44 delete_option( "um_cache_userdata_{$user_id}" ); 46 delete_option( "um_cache_userdata_{$user_id}" );
45 47
46 //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 48 // 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.
49 // 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.
47 $user_data = get_userdata( $user_id ); 50 $user_data = get_userdata( $user_id );
48 $key = UM()->user()->maybe_generate_password_reset_key( $user_data ); 51 if ( empty( $reset_key ) ) {
52 $reset_key = UM()->user()->maybe_generate_password_reset_key( $user_data );
53 }
49 54
50 // this link looks like WordPress native link e.g. wp-login.php?action=rp&key={hash}&login={user_login} 55 // this link looks like WordPress native link e.g. wp-login.php?action=rp&key={hash}&login={user_login}
51 $url = add_query_arg( 56 $url = add_query_arg(
52 array( 57 array(
53 'act' => 'reset_password', 58 'act' => 'reset_password',
54 'hash' => $key, 59 'hash' => $reset_key,
55 'login' => $user_data->user_login, 60 'login' => $user_data->user_login,
56 ), 61 ),
57 um_get_core_page( 'password-reset' ) 62 um_get_core_page( 'password-reset' )
...@@ -155,6 +160,7 @@ if ( ! class_exists( 'um\core\Password' ) ) { ...@@ -155,6 +160,7 @@ if ( ! class_exists( 'um\core\Password' ) ) {
155 160
156 if ( false !== $this->change_password ) { 161 if ( false !== $this->change_password ) {
157 // then COOKIE are valid then get data from them and populate hidden fields for the password reset form 162 // then COOKIE are valid then get data from them and populate hidden fields for the password reset form
163 $args['rp_mode'] = 'pw_change';
158 $args['template'] = 'password-change'; 164 $args['template'] = 'password-change';
159 $args['rp_key'] = ''; 165 $args['rp_key'] = '';
160 $rp_cookie = 'wp-resetpass-' . COOKIEHASH; 166 $rp_cookie = 'wp-resetpass-' . COOKIEHASH;
...@@ -163,6 +169,14 @@ if ( ! class_exists( 'um\core\Password' ) ) { ...@@ -163,6 +169,14 @@ if ( ! class_exists( 'um\core\Password' ) ) {
163 169
164 $args['login'] = $rp_login; 170 $args['login'] = $rp_login;
165 $args['rp_key'] = $rp_key; 171 $args['rp_key'] = $rp_key;
172
173 $rp_user_obj = get_user_by( 'login', $rp_login );
174 if ( false !== $rp_user_obj ) {
175 $set_password_required = get_user_meta( $rp_user_obj->ID, 'um_set_password_required', true );
176 if ( ! empty( $set_password_required ) ) {
177 $args['rp_mode'] = 'pw_set';
178 }
179 }
166 } 180 }
167 } 181 }
168 182
...@@ -481,6 +495,7 @@ if ( ! class_exists( 'um\core\Password' ) ) { ...@@ -481,6 +495,7 @@ if ( ! class_exists( 'um\core\Password' ) ) {
481 495
482 if ( isset( $args['user_password'] ) && empty( $args['user_password'] ) ) { 496 if ( isset( $args['user_password'] ) && empty( $args['user_password'] ) ) {
483 UM()->form()->add_error( 'user_password', __( 'You must enter a new password', 'ultimate-member' ) ); 497 UM()->form()->add_error( 'user_password', __( 'You must enter a new password', 'ultimate-member' ) );
498 return;
484 } 499 }
485 500
486 if ( isset( $args['user_password'] ) ) { 501 if ( isset( $args['user_password'] ) ) {
...@@ -599,6 +614,11 @@ if ( ! class_exists( 'um\core\Password' ) ) { ...@@ -599,6 +614,11 @@ if ( ! class_exists( 'um\core\Password' ) ) {
599 } 614 }
600 $this->setcookie( $rp_cookie, false ); 615 $this->setcookie( $rp_cookie, false );
601 616
617 $set_password_required = get_user_meta( $user->ID, 'um_set_password_required', true );
618 if ( ! empty( $set_password_required ) ) {
619 delete_user_meta( $user->ID, 'um_set_password_required' );
620 }
621
602 /** 622 /**
603 * UM hook 623 * UM hook
604 * 624 *
......
...@@ -125,8 +125,14 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) { ...@@ -125,8 +125,14 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
125 wp_die( __( 'This activation link is expired.', 'ultimate-member' ) ); 125 wp_die( __( 'This activation link is expired.', 'ultimate-member' ) );
126 } 126 }
127 127
128 $redirect = um_get_core_page( 'login', 'account_active' );
129 $set_password_required = get_user_meta( $user_id, 'um_set_password_required', true );
130
128 um_fetch_user( $user_id ); 131 um_fetch_user( $user_id );
129 UM()->user()->approve(); 132 UM()->user()->approve();
133 if ( ! empty( $set_password_required ) ) {
134 $redirect = um_user( 'password_reset_link' );
135 }
130 um_reset_user(); 136 um_reset_user();
131 137
132 $user_role = UM()->roles()->get_priority_user_role( $user_id ); 138 $user_role = UM()->roles()->get_priority_user_role( $user_id );
...@@ -167,7 +173,9 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) { ...@@ -167,7 +173,9 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
167 */ 173 */
168 do_action( 'um_after_email_confirmation', $user_id ); 174 do_action( 'um_after_email_confirmation', $user_id );
169 175
170 $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" 176 if ( empty( $set_password_required ) ) {
177 $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"
178 }
171 $redirect = apply_filters( 'um_after_email_confirmation_redirect', $redirect, $user_id, $login ); 179 $redirect = apply_filters( 'um_after_email_confirmation_redirect', $redirect, $user_id, $login );
172 180
173 exit( wp_redirect( $redirect ) ); 181 exit( wp_redirect( $redirect ) );
......
...@@ -162,6 +162,13 @@ if ( ! class_exists( 'um\core\Rewrite' ) ) { ...@@ -162,6 +162,13 @@ if ( ! class_exists( 'um\core\Rewrite' ) ) {
162 if ( empty( $custom_meta ) ) { 162 if ( empty( $custom_meta ) ) {
163 // Set default permalink base if custom meta is empty. 163 // Set default permalink base if custom meta is empty.
164 $permalink_base = 'user_login'; 164 $permalink_base = 'user_login';
165 } else {
166 // Ignore username slug if custom meta slug exists.
167 $user_id = username_exists( um_queried_user() );
168 $custom_permalink = get_user_meta( $user_id, 'um_user_profile_url_slug_' . $permalink_base, true );
169 if ( ! empty( $custom_permalink ) && um_queried_user() !== $custom_permalink ) {
170 return false;
171 }
165 } 172 }
166 } 173 }
167 174
......
...@@ -191,6 +191,56 @@ KEY meta_value_indx (um_value(191)) ...@@ -191,6 +191,56 @@ KEY meta_value_indx (um_value(191))
191 $content = '[ultimatemember form_id="' . $setup_shortcodes[ $slug ] . '"]'; 191 $content = '[ultimatemember form_id="' . $setup_shortcodes[ $slug ] . '"]';
192 } 192 }
193 193
194 /** This filter is documented in includes/core/class-setup.php */
195 $content = apply_filters( 'um_setup_predefined_page_content', $content, $slug );
196
197 $user_page = array(
198 'post_title' => $array['title'],
199 'post_content' => $content,
200 'post_name' => $slug,
201 'post_type' => 'page',
202 'post_status' => 'publish',
203 'post_author' => get_current_user_id(),
204 'comment_status' => 'closed',
205 );
206
207 $post_id = wp_insert_post( $user_page );
208 update_post_meta( $post_id, '_um_core', $slug );
209
210 $core_pages[ $slug ] = $post_id;
211 }
212
213 $options = get_option( 'um_options', array() );
214
215 foreach ( $core_pages as $slug => $page_id ) {
216 $key = UM()->options()->get_core_page_id( $slug );
217 $options[ $key ] = $page_id;
218 }
219
220 update_option( 'um_options', $options );
221
222 // reset rewrite rules after first install of core pages
223 UM()->rewrite()->reset_rules();
224 }
225
226 public function predefined_page( $slug, $with_rewrite = true ) {
227 $page_exists = UM()->query()->find_post_id( 'page', '_um_core', $slug );
228 if ( $page_exists ) {
229 return;
230 }
231
232 $predefined_pages = UM()->config()->get( 'predefined_pages' );
233 if ( empty( $predefined_pages ) || ! array_key_exists( $slug, $predefined_pages ) ) {
234 return;
235 }
236
237 $data = $predefined_pages[ $slug ];
238
239 if ( empty( $data['title'] ) ) {
240 return;
241 }
242
243 $content = ! empty( $data['content'] ) ? $data['content'] : '';
194 /** 244 /**
195 * Filters Ultimate Member predefined pages content when set up the predefined page. 245 * Filters Ultimate Member predefined pages content when set up the predefined page.
196 * 246 *
...@@ -215,7 +265,7 @@ KEY meta_value_indx (um_value(191)) ...@@ -215,7 +265,7 @@ KEY meta_value_indx (um_value(191))
215 $content = apply_filters( 'um_setup_predefined_page_content', $content, $slug ); 265 $content = apply_filters( 'um_setup_predefined_page_content', $content, $slug );
216 266
217 $user_page = array( 267 $user_page = array(
218 'post_title' => $array['title'], 268 'post_title' => $data['title'],
219 'post_content' => $content, 269 'post_content' => $content,
220 'post_name' => $slug, 270 'post_name' => $slug,
221 'post_type' => 'page', 271 'post_type' => 'page',
...@@ -225,23 +275,19 @@ KEY meta_value_indx (um_value(191)) ...@@ -225,23 +275,19 @@ KEY meta_value_indx (um_value(191))
225 ); 275 );
226 276
227 $post_id = wp_insert_post( $user_page ); 277 $post_id = wp_insert_post( $user_page );
228 update_post_meta( $post_id, '_um_core', $slug ); 278 if ( empty( $post_id ) || is_wp_error( $post_id ) ) {
229 279 return;
230 $core_pages[ $slug ] = $post_id;
231 } 280 }
232 281
233 $options = get_option( 'um_options', array() ); 282 update_post_meta( $post_id, '_um_core', $slug );
234
235 foreach ( $core_pages as $slug => $page_id ) {
236 $key = UM()->options()->get_core_page_id( $slug );
237 $options[ $key ] = $page_id;
238 }
239 283
240 update_option( 'um_options', $options ); 284 UM()->options()->update( UM()->options()->get_predefined_page_option_key( $slug ), $post_id );
241 285
242 // reset rewrite rules after first install of core pages 286 if ( $with_rewrite ) {
287 // Reset rewrite rules after page creation and option upgrade.
243 UM()->rewrite()->reset_rules(); 288 UM()->rewrite()->reset_rules();
244 } 289 }
290 }
245 291
246 /** 292 /**
247 * Set default UM settings. 293 * Set default UM settings.
......
...@@ -74,6 +74,8 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) { ...@@ -74,6 +74,8 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
74 add_shortcode( 'um_show_content', array( &$this, 'um_shortcode_show_content_for_role' ) ); 74 add_shortcode( 'um_show_content', array( &$this, 'um_shortcode_show_content_for_role' ) );
75 add_shortcode( 'ultimatemember_searchform', array( &$this, 'ultimatemember_searchform' ) ); 75 add_shortcode( 'ultimatemember_searchform', array( &$this, 'ultimatemember_searchform' ) );
76 76
77 add_shortcode( 'um_author_profile_link', array( &$this, 'author_profile_link' ) );
78
77 add_filter( 'body_class', array( &$this, 'body_class' ), 0 ); 79 add_filter( 'body_class', array( &$this, 'body_class' ), 0 );
78 80
79 add_filter( 'um_shortcode_args_filter', array( &$this, 'display_logout_form' ), 99 ); 81 add_filter( 'um_shortcode_args_filter', array( &$this, 'display_logout_form' ), 99 );
...@@ -458,6 +460,63 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) { ...@@ -458,6 +460,63 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
458 return $output; 460 return $output;
459 } 461 }
460 462
463 /**
464 * Display post author's link to UM User Profile.
465 *
466 * @since 2.8.2
467 *
468 * Example 1: [um_author_profile_link] current post author User Profile URL
469 * Example 2: [um_author_profile_link title="User profile" user_id="29"]
470 * Example 3: [um_author_profile_link title="User profile" user_id="29"]Visit Author Profile[/um_author_profile_link]
471 * Example 4: [um_author_profile_link raw="1"] for result like http://localhost:8000/user/janedoe/
472 *
473 * @param array $attr {
474 * Attributes of the shortcode.
475 *
476 * @type string $class A link class.
477 * @type string $title A link text.
478 * @type int $user_id User ID. Author ID if empty.
479 * @type bool $raw Get raw URL or link layout. `false` by default.
480 * }
481 * @param string $content
482 * @return string Profile link HTML or profile link URL if the link text is empty.
483 */
484 public function author_profile_link( $attr = array(), $content = '' ) {
485 $default_user_id = 0;
486 if ( is_singular() ) {
487 $default_user_id = get_post()->post_author;
488 } elseif ( is_author() ) {
489 $default_user_id = get_the_author_meta( 'ID' );
490 }
491
492 $defaults_atts = array(
493 'class' => 'um-link um-profile-link',
494 'title' => __( 'Go to profile', 'ultimate-member' ),
495 'user_id' => $default_user_id,
496 'raw' => false,
497 );
498
499 $atts = shortcode_atts( $defaults_atts, $attr, 'um_author_profile_link' );
500
501 if ( empty( $atts['user_id'] ) ) {
502 return '';
503 }
504
505 $user_id = absint( $atts['user_id'] );
506 $url = um_user_profile_url( $user_id );
507 if ( empty( $url ) ) {
508 return '';
509 }
510
511 if ( ! empty( $atts['raw'] ) ) {
512 return $url;
513 }
514
515 $title = ! empty( $atts['title'] ) ? $atts['title'] : __( 'Go to profile', 'ultimate-member' );
516 $link_html = empty( $content ) ? $title : $content;
517
518 return '<a class="' . esc_attr( $atts['class'] ) . '" href="' . esc_url( $url ) . '" title="' . esc_attr( $title ) . '">' . wp_kses_post( $link_html ) . '</a>';
519 }
461 520
462 /** 521 /**
463 * @param array $args 522 * @param array $args
......
...@@ -972,7 +972,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -972,7 +972,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
972 * @param string $image_path 972 * @param string $image_path
973 * @param string $src 973 * @param string $src
974 * @param string $key 974 * @param string $key
975 * @param integer $user_id 975 * @param int $user_id
976 * @param string $coord 976 * @param string $coord
977 * @param array $crop 977 * @param array $crop
978 * 978 *
...@@ -982,14 +982,15 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -982,14 +982,15 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
982 */ 982 */
983 public function profile_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) { 983 public function profile_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) {
984 $sizes = UM()->options()->get( 'photo_thumb_sizes' ); 984 $sizes = UM()->options()->get( 'photo_thumb_sizes' );
985
986 $quality = UM()->options()->get( 'image_compression' ); 985 $quality = UM()->options()->get( 'image_compression' );
987 986
988 $image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor 987 $image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor
989 988
990 $temp_image_path = $image_path; 989 $temp_image_path = $image_path;
991 //refresh image_path to make temporary image permanently after upload 990
992 $image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . pathinfo( $image_path, PATHINFO_EXTENSION ); 991 // Refresh image_path to make temporary image permanently after upload
992 $photo_ext = pathinfo( $image_path, PATHINFO_EXTENSION );
993 $image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . $photo_ext;
993 994
994 if ( ! is_wp_error( $image ) ) { 995 if ( ! is_wp_error( $image ) ) {
995 $src_x = $crop[0]; 996 $src_x = $crop[0];
...@@ -1004,12 +1005,16 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1004,12 +1005,16 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1004 $image->resize( $max_w, $src_h ); 1005 $image->resize( $max_w, $src_h );
1005 } 1006 }
1006 1007
1007 $image->save( $image_path ); 1008 $save_result = $image->save( $image_path );
1009
1010 if ( is_wp_error( $save_result ) ) {
1011 // translators: %s is the file src.
1012 wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
1013 }
1008 1014
1009 $image->set_quality( $quality ); 1015 $image->set_quality( $quality );
1010 1016
1011 $sizes_array = array(); 1017 $sizes_array = array();
1012
1013 foreach ( $sizes as $size ) { 1018 foreach ( $sizes as $size ) {
1014 $sizes_array[] = array( 'width' => $size ); 1019 $sizes_array[] = array( 'width' => $size );
1015 } 1020 }
...@@ -1020,27 +1025,28 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1020,27 +1025,28 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1020 1025
1021 unlink( $temp_image_path ); 1026 unlink( $temp_image_path );
1022 1027
1023 $src = str_replace( '/' . $key . '_temp.', '/' . $key . '.', $src ); 1028 $basename = $key . '_temp.' . $photo_ext;
1029 $src = str_replace( '/' . $basename, '/' . $save_result['file'], $src );
1024 1030
1025 $response['image']['source_url'] = $src; 1031 $response['image']['source_url'] = $src;
1026 $response['image']['source_path'] = $image_path; 1032 $response['image']['source_path'] = $save_result['path'];
1027 $response['image']['filename'] = wp_basename( $image_path ); 1033 $response['image']['filename'] = $save_result['file'];
1028 1034
1029 update_user_meta( $this->user_id, $key, wp_basename( wp_basename( $image_path ) ) ); 1035 update_user_meta( $this->user_id, $key, $save_result['file'] );
1030 delete_user_meta( $this->user_id, "{$key}_metadata_temp" ); 1036 delete_user_meta( $this->user_id, "{$key}_metadata_temp" );
1031 } else { 1037 } else {
1032 wp_send_json_error( esc_js( __( "Unable to crop image file: {$src}", 'ultimate-member' ) ) ); 1038 // translators: %s is the file src.
1039 wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
1033 } 1040 }
1034 1041
1035 return $response; 1042 return $response;
1036 } 1043 }
1037 1044
1038
1039 /** 1045 /**
1040 * Cover photo image process 1046 * Cover photo image process
1041 * 1047 *
1042 * @param string $src 1048 * @param string $src
1043 * @param integer $user_id 1049 * @param int $user_id
1044 * @param string $coord 1050 * @param string $coord
1045 * @param array $crop 1051 * @param array $crop
1046 * @param array $response 1052 * @param array $response
...@@ -1050,20 +1056,18 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1050,20 +1056,18 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1050 * @return array 1056 * @return array
1051 */ 1057 */
1052 public function cover_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) { 1058 public function cover_photo( $response, $image_path, $src, $key, $user_id, $coord, $crop ) {
1053
1054 $sizes = UM()->options()->get( 'cover_thumb_sizes' ); 1059 $sizes = UM()->options()->get( 'cover_thumb_sizes' );
1055
1056 $quality = UM()->options()->get( 'image_compression' ); 1060 $quality = UM()->options()->get( 'image_compression' );
1057 1061
1058 $image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor 1062 $image = wp_get_image_editor( $image_path ); // Return an implementation that extends WP_Image_Editor
1059 1063
1060 $temp_image_path = $image_path; 1064 $temp_image_path = $image_path;
1061 1065
1062 //refresh image_path to make temporary image permanently after upload 1066 // Refresh image_path to make temporary image permanently after upload
1063 $image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . pathinfo( $image_path, PATHINFO_EXTENSION ); 1067 $photo_ext = pathinfo( $image_path, PATHINFO_EXTENSION );
1068 $image_path = pathinfo( $image_path, PATHINFO_DIRNAME ) . DIRECTORY_SEPARATOR . $key . '.' . $photo_ext;
1064 1069
1065 if ( ! is_wp_error( $image ) ) { 1070 if ( ! is_wp_error( $image ) ) {
1066
1067 $src_x = $crop[0]; 1071 $src_x = $crop[0];
1068 $src_y = $crop[1]; 1072 $src_y = $crop[1];
1069 $src_w = $crop[2]; 1073 $src_w = $crop[2];
...@@ -1076,7 +1080,12 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1076,7 +1080,12 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1076 $image->resize( $max_w, $src_h ); 1080 $image->resize( $max_w, $src_h );
1077 } 1081 }
1078 1082
1079 $image->save( $image_path ); 1083 $save_result = $image->save( $image_path );
1084
1085 if ( is_wp_error( $save_result ) ) {
1086 // translators: %s is the file src.
1087 wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
1088 }
1080 1089
1081 $image->set_quality( $quality ); 1090 $image->set_quality( $quality );
1082 1091
...@@ -1090,7 +1099,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1090,7 +1099,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1090 1099
1091 // change filenames of resized images 1100 // change filenames of resized images
1092 foreach ( $resize as $row ) { 1101 foreach ( $resize as $row ) {
1093 $new_filename = str_replace( "x{$row['height']}" , '', $row['file'] ); 1102 $new_filename = str_replace( "x{$row['height']}", '', $row['file'] );
1094 $old_filename = $row['file']; 1103 $old_filename = $row['file'];
1095 1104
1096 rename( dirname( $image_path ) . DIRECTORY_SEPARATOR . $old_filename, dirname( $image_path ) . DIRECTORY_SEPARATOR . $new_filename ); 1105 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' ) ) { ...@@ -1098,16 +1107,18 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1098 1107
1099 unlink( $temp_image_path ); 1108 unlink( $temp_image_path );
1100 1109
1101 $src = str_replace( '/' . $key . '_temp.', '/' . $key . '.', $src ); 1110 $basename = $key . '_temp.' . $photo_ext;
1111 $src = str_replace( '/' . $basename, '/' . $save_result['file'], $src );
1102 1112
1103 $response['image']['source_url'] = $src; 1113 $response['image']['source_url'] = $src;
1104 $response['image']['source_path'] = $image_path; 1114 $response['image']['source_path'] = $save_result['path'];
1105 $response['image']['filename'] = wp_basename( $image_path ); 1115 $response['image']['filename'] = $save_result['file'];
1106 1116
1107 update_user_meta( $this->user_id, $key, wp_basename( wp_basename( $image_path ) ) ); 1117 update_user_meta( $this->user_id, $key, $save_result['file'] );
1108 delete_user_meta( $this->user_id, "{$key}_metadata_temp" ); 1118 delete_user_meta( $this->user_id, "{$key}_metadata_temp" );
1109 } else { 1119 } else {
1110 wp_send_json_error( esc_js( __( "Unable to crop image file: {$src}", 'ultimate-member' ) ) ); 1120 // translators: %s is the file src.
1121 wp_send_json_error( sprintf( __( 'Unable to crop image file: %s', 'ultimate-member' ), $src ) );
1111 } 1122 }
1112 1123
1113 return $response; 1124 return $response;
...@@ -1203,7 +1214,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { ...@@ -1203,7 +1214,7 @@ if ( ! class_exists( 'um\core\Uploader' ) ) {
1203 1214
1204 $response = apply_filters( "um_upload_image_process__{$key}", $response, $image_path, $src, $key, $user_id, $coord, $crop ); 1215 $response = apply_filters( "um_upload_image_process__{$key}", $response, $image_path, $src, $key, $user_id, $coord, $crop );
1205 1216
1206 if ( ! in_array( $key, array( 'profile_photo', 'cover_photo' ) ) ) { 1217 if ( ! in_array( $key, array( 'profile_photo', 'cover_photo' ), true ) ) {
1207 $response = apply_filters( 'um_upload_stream_image_process', $response, $image_path, $src, $key, $user_id, $coord, $crop ); 1218 $response = apply_filters( 'um_upload_stream_image_process', $response, $image_path, $src, $key, $user_id, $coord, $crop );
1208 } 1219 }
1209 1220
......
...@@ -1301,7 +1301,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1301,7 +1301,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1301 } 1301 }
1302 1302
1303 if ( $this->usermeta['account_status'][0] == 'awaiting_email_confirmation' ) { 1303 if ( $this->usermeta['account_status'][0] == 'awaiting_email_confirmation' ) {
1304 $this->usermeta['account_status_name'][0] = __( 'Awaiting E-mail Confirmation', 'ultimate-member' ); 1304 $this->usermeta['account_status_name'][0] = __( 'Awaiting Email Confirmation', 'ultimate-member' );
1305 } 1305 }
1306 1306
1307 if ( $this->usermeta['account_status'][0] == 'awaiting_admin_review' ) { 1307 if ( $this->usermeta['account_status'][0] == 'awaiting_admin_review' ) {
...@@ -1607,7 +1607,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1607,7 +1607,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1607 1607
1608 $expiry_time = UM()->options()->get( 'activation_link_expiry_time' ); 1608 $expiry_time = UM()->options()->get( 'activation_link_expiry_time' );
1609 if ( ! empty( $expiry_time ) && is_numeric( $expiry_time ) ) { 1609 if ( ! empty( $expiry_time ) && is_numeric( $expiry_time ) ) {
1610 $this->profile['account_secret_hash_expiry'] = time() + $expiry_time; 1610 $this->profile['account_secret_hash_expiry'] = time() + $expiry_time * DAY_IN_SECONDS;
1611 $this->update_usermeta_info( 'account_secret_hash_expiry' ); 1611 $this->update_usermeta_info( 'account_secret_hash_expiry' );
1612 } 1612 }
1613 1613
...@@ -1676,7 +1676,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1676,7 +1676,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1676 1676
1677 1677
1678 /** 1678 /**
1679 * This method approves a user membership and sends them an optional welcome/approval e-mail. 1679 * This method approves a user membership and sends them an optional welcome/approval email.
1680 * 1680 *
1681 * @usage <?php UM()->user()->approve(); ?> 1681 * @usage <?php UM()->user()->approve(); ?>
1682 * 1682 *
...@@ -1690,7 +1690,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1690,7 +1690,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1690 ?> 1690 ?>
1691 * 1691 *
1692 */ 1692 */
1693 function approve( $repeat = true ) { 1693 public function approve( $repeat = true ) {
1694 $user_id = um_user( 'ID' ); 1694 $user_id = um_user( 'ID' );
1695 1695
1696 if ( ! $repeat ) { 1696 if ( ! $repeat ) {
...@@ -1702,7 +1702,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1702,7 +1702,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1702 1702
1703 delete_option( "um_cache_userdata_{$user_id}" ); 1703 delete_option( "um_cache_userdata_{$user_id}" );
1704 1704
1705 if ( um_user( 'account_status' ) == 'awaiting_admin_review' ) { 1705 if ( 'awaiting_admin_review' === um_user( 'account_status' ) ) {
1706 $userdata = get_userdata( $user_id ); 1706 $userdata = get_userdata( $user_id );
1707 1707
1708 $this->maybe_generate_password_reset_key( $userdata ); 1708 $this->maybe_generate_password_reset_key( $userdata );
...@@ -1758,7 +1758,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1758,7 +1758,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1758 1758
1759 1759
1760 /** 1760 /**
1761 * This method puts a user under manual review by administrator and sends them an optional e-mail. 1761 * This method puts a user under manual review by administrator and sends them an optional email.
1762 * 1762 *
1763 * @usage <?php UM()->user()->pending(); ?> 1763 * @usage <?php UM()->user()->pending(); ?>
1764 * 1764 *
...@@ -1784,7 +1784,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1784,7 +1784,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1784 1784
1785 1785
1786 /** 1786 /**
1787 * This method rejects a user membership and sends them an optional e-mail. 1787 * This method rejects a user membership and sends them an optional email.
1788 * 1788 *
1789 * @usage <?php UM()->user()->reject(); ?> 1789 * @usage <?php UM()->user()->reject(); ?>
1790 * 1790 *
...@@ -1811,7 +1811,7 @@ if ( ! class_exists( 'um\core\User' ) ) { ...@@ -1811,7 +1811,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
1811 1811
1812 1812
1813 /** 1813 /**
1814 * This method deactivates a user membership and sends them an optional e-mail. 1814 * This method deactivates a user membership and sends them an optional email.
1815 * 1815 *
1816 * @usage <?php UM()->user()->deactivate(); ?> 1816 * @usage <?php UM()->user()->deactivate(); ?>
1817 * 1817 *
......
...@@ -157,15 +157,15 @@ function um_submit_account_errors_hook( $args ) { ...@@ -157,15 +157,15 @@ function um_submit_account_errors_hook( $args ) {
157 if ( isset( $args['user_email'] ) ) { 157 if ( isset( $args['user_email'] ) ) {
158 158
159 if ( strlen( trim( $args['user_email'] ) ) === 0 ) { 159 if ( strlen( trim( $args['user_email'] ) ) === 0 ) {
160 UM()->form()->add_error( 'user_email', __( 'You must provide your e-mail', 'ultimate-member' ) ); 160 UM()->form()->add_error( 'user_email', __( 'You must provide your email', 'ultimate-member' ) );
161 } 161 }
162 162
163 if ( ! is_email( $args['user_email'] ) ) { 163 if ( ! is_email( $args['user_email'] ) ) {
164 UM()->form()->add_error( 'user_email', __( 'Please provide a valid e-mail', 'ultimate-member' ) ); 164 UM()->form()->add_error( 'user_email', __( 'Please provide a valid email', 'ultimate-member' ) );
165 } 165 }
166 166
167 if ( email_exists( $args['user_email'] ) && email_exists( $args['user_email'] ) !== get_current_user_id() ) { 167 if ( email_exists( $args['user_email'] ) && email_exists( $args['user_email'] ) !== get_current_user_id() ) {
168 UM()->form()->add_error( 'user_email', __( 'Please provide a valid e-mail', 'ultimate-member' ) ); 168 UM()->form()->add_error( 'user_email', __( 'Please provide a valid email', 'ultimate-member' ) );
169 } 169 }
170 } 170 }
171 171
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.