Assigning post-specific roles to users in WordPress - wordpress

I am designing a plugin that need to assign users to a particular post (of a custom type).
For instance, I have a custom post type: ClassifiedFile
For posts of that type, I will need somewhere in the interface to assign users to it, each having different capabilities. In that case, that could be:
Reviewers assigned to a particular classified file can read it and mark it as approved
Readers assigned to a particular classified file can only read it
Or course, readers and reviewers do not have access to other classified files than the ones they are allowed to see.
Managers who can assign Reviewers and Readers to classified files
PluginAdmin who can assign Managers to classified files
Ideally, the solution should lend to efficient requests of the type:
I want to list all classified files a user can read (be it as reviewer or as reader).
So far :
I have stored a few particular properties in the meta data of the post (such as the approval status).
I have created custom capabilities : "plugin-admin", "manage-file-users", "approve-file" and "read-file"
I provide two custom roles for that : File Group Manager ("plugin-admin"), File Group Manager ("manage-users") , File Reviewer ("approve-file", "read-file") and File Reader ("read-file")
I must say I am struggling to find a nice way to address the listing and storing of priviledges per classified file. Ideally I'd like to avoid having to create a separate DB table but if that is the way to do it then I'll do that.

Assigning roles was not much a problem, the question was more a matter of where and how to store the information.
I have decided to do that:
I define groups (which are in fact WP_Role objects) which are common to all ClassifiedFile
For each ClassifiedFile, I store a meta value which is an array of strings containing the role and id of a user. For instance: [ reviewer|50|, reader|123|, reader|13| ]
I can then query all ClassifiedFile of a particular user using the criteria:
'meta_query' => array( array(
'key' => 'users',
'value' => '|' . $user_id . '|',
'compare' => 'LIKE'
))
Or using a group:
'meta_query' => array( array(
'key' => 'users',
'value' => $group . '|' . $user_id . '|',
'compare' => '='
))

Related

Meta_key and meta_value - Wordpress

As the question asks, I'm trying to understand one thing, as this is a popular of the fields within the table, but I can't understand their usefulness.
global $wpdb;
$wpdb->insert(
$wpdb->postmeta,
array(
'post_id' => '1',
'meta_key' => 'address',
'meta_value' => '1428 Elm St.'
),
array(
'%d',
'%s',
'%s'
)
);
One thing is the post-table table?
What is the use of this table as in the previous case, for the seo?
in my searches on google, I saw that setting the correct tags, involves a better indexing by google, and for this there is a truly spectacular tool, which allows you to have access by entering the word of the topic we want to write like post and get all the queries, that people type more on google: (https://answerthepublic.com/)
but setting tags and populating the postmeta table are not the same thing?
What is the utility of populating with a code like the postmeta table before?
Its NOT for SEO. Its for custom fields. On WP by default for posts and pages you have wp-post table, that tables has following columns (https://i.imgur.com/NCBslgq.png) for expanding functionality and adding extra custom fields WP has other table wp-postmeta (meta_id, post_id, meta_key, meta_value). So if you want add address field to post or custom post, you attaching meta field to that post using add_post_meta() https://codex.wordpress.org/Function_Reference/add_post_meta

Saving user meta as single values or an array

I'm working on a plugin which is going to save about 10 custom user meta for certain users bound to the plugin. Among these metas we find: Address, zip, occupation, etc...
These metas will only be used by the plugin, and mostly (if not always) all of them will be fetched from the DB together to be shown in a table view in the admin.
So, I'm thinking about the best way to save these values.
I could do this:
add_user_meta( $user_id, 'address', 'kings street 45');
add_user_meta( $user_id, 'zip', '12345');
add_user_meta( $user_id, 'occupation', 'nurse');
... some more meta
Or would it be better to do this:
add_user_meta( $user_id, 'plugin_name_user_meta', array(
'address' => 'kings street 45'
'zip' => '12345'
'occupation' => 'nurse')
... some more meta
);
In WordPress I prefer to work with arrays because in helps keeping my data organized, so I would go the second way. Nevertheless, if you go the first way, prefix all the metas with a unique ID related to your plugin.
I disagree with the first answer and I would use your first suggestion.
Why? Because if you use add_user_meta for each field you have a seperate field in the database for each value. That means:
1) You can do meta and Wildcard Queries e.g. "Select all user with a ZIP starting with 11". This is impossible if you save an array especially as the array will be saved in serialized format.
Keep this possibility open! Some day you may want to do complicated queries on this data even if it is not the case currently.
Have a look at the WP Meta Query class and even better the WP User Query class:
https://codex.wordpress.org/Class_Reference/WP_Meta_Query
https://codex.wordpress.org/Class_Reference/WP_User_Query#Custom_Field_Parameters
2) You do not have a disadvantage in extensibility: As these fields are already saved in a meta table and not within fixed columns you can add and remove values dynamically.
However #Juan is right with the hint on prefixes: You definitly should prefix your meta_values in order to avoid collisions.

SQL Server to CSV to Wordpress - is it possible?

I have a custom made CMS system with a relatively small number (~1000) of articles inside my SQL Server database.
I want to migrate the whole site to Wordpress. Is it possible and if so, then how, to migrate the data (one table - Article) from SQL Server to a CSV file and then import it into Wordpress?
Thanks!
update:
The structure of table Article looks like this:
ID_Article - int (pk)
Title - nvarchar(max)
Summary - nvarchar(max)
Contents - nvarchar(max)
Date - datetime
ID_Author - int (fk)
Image - nvarchar(max)
Promoted - bit
Hidden - bit
There also categories done with an associative CategoryToArticle table. The only thing that needs to be moved is CONTENTS (optionally merged with Summary) DATE and TITLE (would be cool if it was merged with author's name "John Doe: My Article title."). It can be categorised as "Archive" or soemthing like that, image and other flags can be dropped completely.
You could use an automation software such as BlogSenseWP to import the CSV items in as new posts, but you would have limited control over the dating and tagging would have to be auto-regenerated using the Yahoo Tags API (included in the software's features). Categorization might be tricky as well, but there are keyword based auto-categorization filters that could help you get close.
Otherwise you would might want to investigate a custom PHP script that imports the CSV fields desired into variables, and then loops through them adding them to the wordpress database using wordpress functions.
Here is a custom way of adding a post to wordpress:
$permalink_name = sanitize_title_with_dashes( $title );
$post = array(
'post_author' => $author_id
'post_category' => $cat_id,
'post_content' => $description,
'post_date' => $date_placeholder,
'post_date_gmt' => $gmt_date,
'post_name' => $permalink_name,
'post_status' => 'publish',
'post_title' => $title,
'post_type' => 'post',
'tags_input' => "$tags",
'original_source'=> $link
);
$post_id = wp_insert_post( $post, $wp_error );
You would have to include the wp-config.php file at the top of this script to load the wordpress code environment.
The above is a crude summary. It would take a thorough understanding of PHP to fill in the ommited code and complete the concept script.
Use the SQLCMD command line tool. You can look at this question to see how to export data into a CSV.
It is possible. However, it heavily depends on the structure of your current table. If you have tags, categories, different post statuses (published, pending etc).
One possible way would be to write a script to read from your database, and drop the same data into the wordpress tables.
MSSQL -> CSV -> MySQL is also possible. You'll just have to read the CSV and dump the data into MySQL.
Maybe if you can give your table structure, we can give you a better way.
this might help you
first create a table in mysql DB
CREATE TABLE Genesis (
id INT(10),
title varchar(255),
description text,
date timestamp,
PRIMARY KEY (id)
);
then use some php code to updae wordpress data.
source -
http://web-design101.com/createawebsite/featured-articles/insert-wordpress-posts-through-mysql

order by custom field include even if empty - wordpress

I have a query for a page of posts.
It return results based on a custom post type, and custom field value. Now I've added the ability to order the results based on another custom field.
$loop = new WP_Query( array ( 'post_type' => 'new', 'orderby' => 'meta_value_num', 'meta_key' => 'over-length', 'meta_query' => array( array( 'key' => 'over-make', 'value' => 'Doral', 'compare' => 'LIKE') ) ) );
I've run into a bit of a problem. I'm ordering the results by a custom field called 'over-length' but it seems that if a post doesn't contain a value for 'over-length' it is excluded from the results.
I'm wondering how could I change my code so that it included post that don't have a value for orderby.
Also just thought of a workaround, but not sure how to do it. I'm using a plugin called "more fields" to create my custom fields. Would it be easier to check if the 'over-length' field is empty and set it to 0? if so how do I go about doing this.
Update
I've looked into the issue a bit further. It seems that if no value is given to 'over-length' the custom field is not added to wp_postmeta in the database. If I give a post a over-length value then go back and remove it it does in fact include the result in my query as the field still exist in the database. So how can I get this custom field to be entered into the database if it has a value or not?
About your last request - for a way to add a meta_key (custom field) on all posts even if it is left blank:
I often use the plugin Custom Fields Template for this kind of thing. It is similar to the one you are using (more fields) but it gives you many possibilities to play with the fields, and most importantly for this case, you can adjust hidden fields and default values. You can perhaps set a default=' ' (space) to have the field inserted if left blank. Or, with a bit more work, modify the plugin code to insert all the fields to DB without checking for empty the values. In the case of CustomFieldsTemplate it shouldn't be hard to do it.

Combining databases in Drupal

So here's the scenario:
I am building a series of event websites that need to be separate Drupal-6 installations on the same server. Each uses the same architecture but different URLs and themes.
What I'd like the sites to be able to share is content in 2 content types, teachers and sponsors. So that there would be one database with all the teachers and sponsors that each individual event site could then pull from by means of nodequeues.
So that new teacher nodes and sponsor nodes can be created and edited from within any of the Drupal installations.
It would also be convenient to share a user table as well, but not absolutely necessary.
Any ideas?
Does this help you?
The comments in settings.txt explain
how to use $db_prefix to share tables:
* To provide prefixes for specific tables, set $db_prefix as an array.
* The array's keys are the table names and the values are the prefixes.
* The 'default' element holds the prefix for any tables not specified
* elsewhere in the array. Example:
*
* $db_prefix = array(
* 'default' => 'main_',
* 'users' => 'shared_',
* 'sessions' => 'shared_',
* 'role' => 'shared_',
* 'authmap' => 'shared_',
* );
Another way, although I don't know if that would work, is to create one database per Drupal installation and create in each database a VIEW eg. install1_users, install2_users that refers to one shared table shared_users in a shared database. A carefully constructed view should be updatable just like a normal table.
Sounds like a job for the Domain Access project, a suite of modules that provide tools for running a group of affiliated sites from one Drupal installation and a single shared database. The module allows you to share users, content, and configurations across a number of sites. By default, these sites share all tables in your Drupal installation but the Domain Prefix module allows for selective, dynamic table prefixing for advanced users.
IMHO this is much better than rolling a custom solution which poses considerable complexity and risk of not being able to upgrade your site. See Share tables across instances (not recommended).
There are a couple of ways of doing this.
If it's okay to share a single database, you can use prefixing as follows:
$db_prefix = array(
'default' => 'main_',
'users' => 'shared_',
'sessions' => 'shared_',
'role' => 'shared_',
'authmap' => 'shared_',
);
However, keep in mind that there is a hard limit to the number of tables that a MySQL database can hold. According to this thread, it's 1792. If you suspect that you will reach this limit, you can use this hack/bug.
$db_prefix = array(
'default' => '',
'users' => 'maindb.',
'sessions' => 'maindb.',
'role' => 'maindb.',
'authmap' => 'maindb.',
);
where maindb is another shared database that contains the data that you need. This is not best practice, but it works in Drupal 6 (haven't tested in D7).

Resources