Username only lowercase and numbers in WP multi? - wordpress

We are using wordpress in multi sub-domains at work.
So we have administrator for each domain who can create users for subscribing editing contributing.
The problem is, our company edit the rule that all logins/usernames have to be like this "first-name.family-name" ex "barack.obama"... :-)
But the administrator can not do it, only super admin can do it !
In sub-domain administrator mode, there is a message that says : "Only the lowercase letters a-z and numbers allowed".
So we want to make it possible to admin to create users with first-name.family-name, but we try to search how to change it in the code, without finding it.
If someone can help, thanks !

In multisite usernames are validated with wpmu_validate_user_signup, which you can find in /wp-includes/ms-functions.php#L462.
You can add a dot there, after the 0-9, which is not recommended, since you will then hate to update WordPress core.
if ( $user_name != $orig_username || preg_match( '/[^a-z0-9.]/', $user_name ) ) {
So, a better solution would be to create a plugin for it.
You could try to add the following in a php-file and add it to /wp-content/mu-plugins/
<?php
/*
Plugin Name: wpmu no username error
*/
function wpmu_no_username_error( $result ) {
$error_name = $result[ 'errors' ]->get_error_messages( 'user_name' );
if ( empty ( $error_name )
or false===$key=array_search( __( 'Only lowercase letters (a-z) and numbers are allowed.' ), $error_name)
) {
return $result;
}
// only remove the error we are disabling, leaving all others
unset ( $result[ 'errors' ]->errors[ 'user_name' ][$key] );
/**
* re-sequence errors in case a non sequential array matters
* e.g. if a core change put this message in element 0 then get_error_message() would not behave as expected)
*/
$result[ 'errors' ]->errors[ 'user_name' ] = array_values( $result[ 'errors' ]->errors[ 'user_name' ] );
return $result;
}
add_filter( 'wpmu_validate_user_signup', 'wpmu_no_username_error' );
I didn't try it though. This is based on "Changing the username character limit from four to less characters".
I hope this helps. At least it should get you close. GL with it!

Related

WP Rest API get post by slug with special characters (ex: !&')

I have posts with slugs with special characters. One of them is the following:
http://localhost/wp-json/wp/v2/posts?slug=my-post!
Unfortunately, WP REST API not showing the content since it has (!) within the slug.
Is there any solution you guys would recommend?
I have found the solution (at least for my case), not sure if it'll work for you but may indicate you the way to go. We need to tap into the function used to sanitize the slugs, as I said in my comment, by default is wp_parse_slug_list. Looking at the code the function that actually sanitizes the slug is sanitize_title.
Looking at the source code, wp_parse_slug_list calls sanitize_title with only one argument, which means that the context used is save. This means that, for posts that were already saved without being sanitized by this function, the slug won't match and the post will be inaccessible through the API. The solution is to change the sanitizing function slightly by adding a filter:
add_filter('rest_post_collection_params', function($query_params) {
$query_params['slug']['sanitize_callback'] = 'sanitize_rest_api_slug';
return $query_params;
}, 20, 1);
function sanitize_rest_api_slug( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value, '', 'query' );
}
return array_unique( $list );
}
The filter is actually being applied on the function get_collection_params() on the class-wp-rest-posts-controller class, but if you look at the source code, the filter has a variable depending on the post_type, so if you have another special kind of posts defined (besides post) you need to add/change a filter for that kind as well.
I hope this helps somebody else like me, even if it's too late for your issue.

WooCommerce Eway plugin not creating customer token for new customer

I have setup a fresh docker container with Wordpress 5.0.3 and the latest WC and WC Eway plugin (WooCommerce eWAY Gateway).
Created a store with some products, hooked up my Eway sandbox environment, enabled Save Cards (which would enable the token) and created an order.
After checking the post_meta in my DB for the order, I didn't see a _eway_token_customer_id field. While being logged in as a customer, I tried again and with the new order I still do not get a token.
The reason for this tests is that I got this strange behaviour in my real, new website, where the first order with a NEW customer, doesn't result in a token.
However, when I create a second order whilst being logged in, I do get a _eway_token_customer_id value within the order_meta.
It is imperative for me to get that token with the first order, because after that I will auto renew the product using the tokenp ayment option.
Debugging this issue is hell, and I find it very disconcerting that on my fresh WP installation I get no token at all.
Is there anyone that has a bright idea?
**update
After some digging around in the Eway Plugin, I found out that the first time I do an order, the function request_access_code() from the class WC_Gateway_EWAY is checking if there is a token in the database for this user.
The function body:
protected function request_access_code( $order ) {
$token_payment = $this->get_token_customer_id( $order );
if ( $token_payment && 'new' === $token_payment ) {
$result = json_decode( $this->get_api()->request_access_code( $order, 'TokenPayment', 'Recurring' ) );
} elseif ( 0 === $order->get_total() && 'shop_subscription' === ( version_compare( WC_VERSION, '3.0', '<' ) ? $order->order_type : $order->get_type() ) ) {
$result = json_decode( $this->get_api()->request_access_code( $order, 'CreateTokenCustomer', 'Recurring' ) );
} else {
$result = json_decode( $this->get_api()->request_access_code( $order ) );
}
if ( isset( $result->Errors ) && ! is_null( $result->Errors ) ) {
throw new Exception( $this->response_message_lookup( $result->Errors ) );
}
return $result;
}
The function handles three possible outcomes:
1) new customer: results in calling `$this->get_api()->request_access_code( $order, 'TokenPayment', 'Recurring' )` <-- this is the one we are after!
2) shop_subscription: calls `$this->get_api()->request_access_code( $order, 'CreateTokenCustomer', 'Recurring' )`
3) else..: calls `$this->get_api()->request_access_code( $order )`
What is happening during debugging, is that the $token_payment variable has the value of an empty string for a new customer, instead of new.
So I will attempt to fix this, either via a filter/action hook, or figure out why this is happening.
When I forced the function the always use the first if block, I got my token. :)
**Update 2:
I tested with an existing user account, created a new order.
When I look in the post_meta table:
Voila, the new value is present.
However, when I am not logged in and I create an account, the new value is not added and that is where it goes wrong.
A temp fix would be to use a hook and add the new value to the order so that when get_token_customer_id is called it retrieves a new value and not an empty string.
I think this is a bug, since this value should be added. It explains why the second transactions get the token but not the first.
If only Woocommerce Eway plugin had a git repo.... I could flag an issue or fork it.
***Solution without hack
Added this to my plugin (or functions.php if you like):
add_action( 'woocommerce_checkout_order_processed', function( $order_id, $posted_data, $order ) {
update_post_meta( $order_id, '_eway_token_customer_id', 'new' );
}, 10, 3);
This will add the new value when you checkout with a non-existent user.
The token was added nicely after adding my creditcard details.
The matter of the fact stays that the plugin still has a bug, which you can work around.

Wordpress Validate New Nicename/Slug

I have written a custom "Edit Account" script that allows a Wordpress user to update their Wordpress account. Everything is working great, except that I can't seem to find a way to update the user's nicename, which also doubles as the user's URL slug (via the get_author_posts_url function). This is causing issues because when a user changes their name, their slug still contains their original name - not the new one.
I know that the sanitize_title function will generate the new nicename, but I don't know how to verify that it is unique and modify it if it is not before entering it into the DB. I am wondering what built-in functions Wordpress has to handle this. I know I can write my own script to do this, but I would much rather use Wordpress functions. I couldn't find this anywhere in the WP documentation. Thanks!
Here is a function I have written to in lue of a built in function:
function new_user_slug($string){
//GENERATE NEW SLUG
$slug=sanitize_title($string);
//MAKE SURE SLUG IS UNIQUE
$result=mysql_query("SELECT * FROM wp_users WHERE user_nicename='$slug'");
if(mysql_num_rows($result)==0){
return $slug;
}else{
$counter=2;
$kill=0;
while($kill==0){
$mod_slug=$slug."-".$counter;
$result=mysql_query("SELECT * FROM wp_users WHERE user_nicename='$mod_slug'");
if(mysql_num_rows($result)==0){
$kill=1;
}else{
$counter++;
}
}
return $mod_slug;
}
}
This takes a string (the user's updated name) and converts it into the default slug. It then checks the slug against the database to see if it is unique. If it is, the slug is returned. If not, it enters an iteration loop that incrementally changes the slug until it is unique.
Try this:
wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent )
Source: https://codex.wordpress.org/Function_Reference/wp_unique_post_slug
Actually if you use wordpress user functions like wp_insert_user and wp_update_user Wordpress itselt handles duplicate user_nicename entries and adds -n suffix to them.
So your code would be something like this:
function new_nicename( $user_id, $nicename ) {
$nicename = sanitize_title( $nicename );
$user_id = wp_update_user( array( 'ID' => $user_id, 'user_nicename' => $nicename ) );
}

strpos() on title in a metabox in wordpress fails to find '-'

I was coding a simple metabox for wordpress and have a little issue when saving data.
The meta box is in my "create article"-page has two textfields. These are saved as post-meta, when the post is saved.
While saving I check if the fields were filled - if they are empty I take the post title and extract the data I need. The idea is to take everything that is before the first "-". If there is no minus sign, the whole title should be saved in my custom field. Now, this fails to find "-" in the title (alltough there is one) and returns the whole title every time:
function get_from_title($title) {
$pos = strpos($title, '-');
if ($pos) {
return trim(substr($title, $pos));
}
else {
$pos = strpos($title, '–'); //added this since two different signs could be used
if ($pos) {
return trim(substr($title, $pos));
}
else {
return $title;
}
}
}
the function that is calling get_from_title is getting the title via get_the_title( $post_id ) and this works without problems.
Is wordpress encoding the title somehow? Why can't strpos find the minus sign? What should I look for instead?
Thanks
I replied to the thread you started on this topic in the WordPress forums. You can find your answer there.
Alternatively, here's what I said. :)
Ah yes. This is a tricky one. So, why can't strpos find a hyphen in
the title when clearly we can see one? Because there isn't one. hehe.
What WordPress is doing here is converting your hyphen ( minus sign )
into an en-dash.
This will give you diddly-squat:
$pos = strpos( $title, '-' );
You want this:
$pos = strpos( $title, '–' );
Let me know how things turned out for you. :)

Easiest way to hide (some) WordPress plugins from users?

I'm using WordPress to make my users make their own website/blog. I have a set up that I'm cloning out to all the users with some special user-roles and standard plugins.
However, some of the plugins are not supposed to be changed or inactivated by the users.
Is their any way to select which plugins different user roles are allowed to use? Or a easy way to hide some plugins in the plugins-page but still have them working as normal?
Maybe there's some plugin that helps me to do this?
You could write a plugin that uses the "all_plugins" filter hook to remove from the array plugins that you don't want displaying for a certain user. Something like this:
$plugin_credentials = array(
'bob' => array(
'Hello Dolly' => 1
),
'jim' => array(
'Akismet' => 1,
'Hello Dolly' => 1,
),
'admin' => "**ALL**"
);
function plugin_permissions($plugins)
{
global $current_user, $plugin_credentials;
$username = $current_user->user_login;
if ($plugin_credentials[$username] == "**ALL**")
return $plugins;
$viewable_plugins = array();
foreach ($plugins as $plugin) {
if (isset($plugin_credentials[$username]) &&
isset($plugin_credentials[$username][$plugin['Name']]) &&
$plugin_credentials[$username][$plugin['Name']] == 1) {
array_push($viewable_plugins, $plugin);
}
}
return $viewable_plugins;
}
add_filter('all_plugins', 'plugin_permissions');
Managing the user permissions in the plugin itself is not ideal, but it is probably easiest. You can expand on that idea to create admin pages for managing the users and their viewable plugins in a database table somewhere.
Each plugin will usually specify their own role/permission, which you can see if you look at their add_submenu_page() or such function calls. You can create new roles for those plugins and replace the one specified by the author, but it will also break the changes if you upgrade the plugins.
You should stratify the users. Make sure that the Admin user(s) are trusted and know not to fiddle with what they don't understand. The others should be limited to their roles. Authors, editors, etc. For example, if they're just a part of the site to write articles, then they don't need to see the rest of it. Make them an author and be done with it.
This is part of client education. If its a smaller client with less stratified roles, then make them two accounts. Tell them "this is the account you administer the site with, you'll be using this rarely. And this is the account that you'll use most of the time to write and edit. You can do all of your daily tasks here and will most likely never need the administrator account". You won't always have luck with this approach, but its less time and effort invested in crap you shouldn't be wasting time on.
I've done a new version based on #spuriousdata Answer. This one uses the plugin slugs (file name minus the extension) to build the list of restrictions. This way is easier as we can unset the array using the first level $keys.
Configuration instructions in the code itself.
<?php
/**
* Plugin Name: Limit Plugins by User
* Plugin URI: http://stackoverflow.com/q/14340131/1287812
* Description: Show selected plugins for specific users.
* Based on the code by spuriousdata, http://stackoverflow.com/a/3713985.
* Author: brasofilo
* Author URI: http://wordpress.stackexchange.com/users/12615/brasofilo
* Version: 1.0
* License: GPLv2 or later
*/
add_filter( 'all_plugins', 'plugin_permissions_so_3707134' );
/**
* Filter the list of plugins according to user_login
*
* Usage: configure the variable $plugin_credentials, which holds a list of users and their plugins.
* To give full access, put a simple string "ALL"
* To grant only for some plugins, create an array with the Plugin Slug,
* which is the file name without extension (akismet.php, hello.php)
*
* #return array List of plugins
*/
function plugin_permissions_so_3707134( $plugins )
{
// Config
$plugin_credentials = array(
'admin' => "ALL",
'other-admin' => array(
'akismet',
),
'another-admin' => array(
'akismet',
'hello',
),
);
// Current user
global $current_user;
$username = $current_user->user_login;
// Super admin, return everything
if ( "ALL" == $plugin_credentials[ $username ] )
return $plugins;
// Filter the plugins of the user
foreach ( $plugins as $key => $value )
{
// Get the file name minus extension
$plugin_slug = basename( $key, '.php' );
// If not in the list of allowed plugins, remove from array
if( !in_array( $plugin_slug, $plugin_credentials[ $username ] ) )
unset( $plugins[ $key ] );
}
return $plugins;
}

Resources