PDA

View Full Version : Add/Change posting data


ndoktoruser
09-24-2015, 11:25 AM
Hello, everyone!

I am currently working on a similar functionality of anonymous posting (https://vborg.vbsupport.ru/showthread.php?t=177694&highlight=anonymous), adapted to vBulletin 5.

I have added a check box to flag that the user will post anonymously.
Now, I need to change the code which gets the data submitted by the form and saves it in the DB.
So, how do I change the data submitted by the user when he/she posts in a topic?
I don't want to change the code of the vBulletin classes. Maybe there is a way of simply add/change the content of the $data array which saves the data in the node table.

I also need to perform a second insertion (this time, to another table, to add the anonymous information).
Does anyone have any hint of what to do or know any plugin that does something similar using vB 5?

Note: as soon as the plugin is complete, I intend to post it on the forum to get feedback and share it with other people who need the same feature.

-------------------

Edit to add code related to the plugin:

1) Download the product_anonymous.xml file attached to this post;
2) Install the product: go to "Products & Hooks" -> "Manage Products" -> "Add/Import Product" and install the .xml file;
3) Create a new template: Go to "Style & Themes" -> "Style Manager" -> pick "Add New Tamplate" for "Default vB5 Style"
3.1) For this new template, set "anonymous_cb" as the title and following code:
<vb:if condition="$page['hasCheckbox'] == true">

<div class="b-content-entry-panel__content b-content-entry-panel__content--smiley h-clearfix">
<label class="js-collapse__link h-align-middle text-bold b-link js-link" for="checkbox_anonymous">Post as anonymous</label>
<input type="checkbox" id="checkbox_anonymous" name="anonymous_post" value="1">
</div>

</vb:if>


As result, a check box to post anonymously will appear (the function must be implemented).

https://vborg.vbsupport.ru/attachment.php?attachmentid=153386&stc=1&d=1443180429

Replicant
09-25-2015, 01:17 AM
Sounds like an interesting project. I'm by far no expert but here's my initial thoughts on the subject.
Changing the data array in the ckeditor submission probably won't work. Until the submission takes place, there is no nodeid to associate your anonymous user data to. Take a look at /js/ckeditor-rollup-519.js. This is where the post submission occurs.
A script will be needed for the additional anonymous info submission via a frontend controller.
I'm thinking you will need to capture the response data to get the nodeid of the new post,
then use that data to insert the node info in your new anonymous table.
Then you will need to add conditionals in the display_contenttype_threadview_header template (I believe) to check your anonymous info table for the current nodeid.
You will also need to create an API extension to get the data from the anonymous table (probably cache it) so you can call that function from the templates.

ndoktoruser
09-25-2015, 09:29 AM
Thanks for the hint, Replicant!

However, maybe I didn't explain very well what I want to do.
I do not want to change the content submitted by the form (/js/ckeditor-rollup-519.js). Is this the best option?

I imagined the following:
1) receive the content submitted by the form;
(probably some API extension would do it, with no changes to the JS)
2) validate whether the check box for anonymous post was checked or not;
3) if so, change the data which will be saved for the post (in the table node);
3.1) the current API saves the "userid" and "authorname" in the table "node", so I would set values for an anonymous post (0, "Guest");
3.2) at the same time, I would store the real "userid", "authorname" and "nodeid" in a new table created by the plugin (this information might be important for moderation).

I believe that this would be the simplest way, because I wouldn't change any existing code.
And when the topic is displayed, the current API would fetch the correct "anonymous" id and user from the table node.

PS: I changed the initial post to add the code for the hook.
PS2: the feature would have the same functionality as if we allow "non registered users" post in the community, but only for "registered users". And would add the log in the new table. So, technically vB already does that, I just don't know where.

Replicant
09-28-2015, 01:14 AM
Looks like you have a start. Any progress on the function?

ndoktoruser
09-28-2015, 06:59 AM
No real progress so far.

I will start changing the code and check what happens (when I get understand enough, I undo the changes and extend the classes in a proper way).
I suppose the function vB_Api_Content::add (in core/vb/api/content.php) is responsible for creating the new node. Then I have to find the proper way pass the right values to the parameter data.

Unfortunately I have no experience with vB.

--------------- Added 1443451334 at 1443451334 ---------------

Does anyone know any plugin for vBulletin 5 that changes or adds something to the default data which is posted by the forum users?

Replicant
09-28-2015, 01:45 PM
I'm still thinking the js method is the way to go. The form is submitted via ajax to the createcontent controller. If you can submit the form to your own controller function instead, forward the form data to the correct function for posting, catch the jsonResponse, and do your insert to your custom table at that point.

After looking at it a little closer, changing the data in the node table is going to cause issues with statistics, editing by post owner and also issues with attachments and images. There are more tables involved in the posts than just the node table that are attached to the userid. I would suggest staying away from changing the node table data and look at changing the output at template time.

ndoktoruser
09-28-2015, 03:27 PM
I will take at the JS then.
I will be useful to set the "anonymous check" in the data array.

I found that, in the function vB_Api_Content_Text::add, I have access to the text and title of the post/topic. And changing the text or title worked. The data array also contains the userid and auhtorname, but it doesn't make any difference if I change it inside of this function. Somewhere else in the code, the session user is retrieved and saved.

Replicant
09-28-2015, 05:05 PM
The post data contains userid, username, secret, token and so forth. Some of that info is hashed to authenticate the post. That is why it needs to be submitted as the real user. That's why I am inclined to use the data as is and work it server side after the post is made. Here's a rough idea of what I'm thinking.

Post is clicked anonymous. That click changes the class on the reply button to call the custom controller using jquery.
The controller hands off the data to the createcontent controller and intercepts the jsonResponse.
The json Response has the nodeid of the new post. The controller then takes that nodeid and does an insert into the anonymous db table with userid and whatever else may be needed, then returns the jsonResponse to the browser to complete the post and reload the page.
In the content template, there would be a conditional that checks if the post nodeid =anonymous.nodeid, if it does, it replaces the post authorname with "Anonymous" else it just continues loading as usual.

There will need to be an api extension made to query the anonymous table. The whole process should only add one db query.

This is just a rough idea and may not work as I haven't tested any of it.

I do have a working api extension to query the database for the template conditional that I can share with you.

ndoktoruser
10-05-2015, 01:59 PM
Hello!

Sorry for the late reply, but I was very sick and didn't work on the feature.
Could you please share the template you told about?

Replicant
10-05-2015, 03:01 PM
I'll try to get that for you this week. I'm kind of slammed this week, so it may be this weekend before I have a chance to get to it.

ndoktoruser
10-07-2015, 02:14 PM
I am working on the possibility of saving with the actual userId, but I see a couple of problems:

The routine that fetches last poster / topic creator;
The count of posts made by the user;
The search of posts made by a user.


Now I see that all of those features would need to take the new table into account.

Replicant
10-17-2015, 11:54 PM
I am working on the possibility of saving with the actual userId, but I see a couple of problems:

The routine that fetches last poster / topic creator;
The count of posts made by the user;
The search of posts made by a user.


Now I see that all of those features would need to take the new table into account.


I've been thinking about this and maybe updating the node table with the anonymous user info is the way to go. Adding logic to the template to determine whether or not the post belongs to a specific user shouldn't be too difficult for editing purposes. There will also need to be an undo script added to the uninstall procedure to revert the changes made by the mod.

EDIT:Ya, after thinking about it, I don't like this idea. If something in the mod or uninstall script were to go awry, the anonymous posts would be irreversible, unowned and I still think it's a bad idea to modify the node table directly. Also the future vbulletin upgrade scripts are not going to take the changes into account and could cause issues there as well.

ndoktoruser
10-19-2015, 11:21 AM
If something in the mod or uninstall script were to go awry, the anonymous posts would be irreversible

If we start from the point that posts written anonymously would never have been written, once the users didn't have this feature, it would be OK having those posts as "guest user". Plus the fact that it would be inconvenient to the users initially having something personal or awkward posted as anonymous, then having their identities shown.

Once we, the moderators, have their identities saved in a special table to avoid eventual problems, I would be fine with that.

I still think it's a bad idea to modify the node table directly.

Yes. I don't know what issues those changes might cause, but I did a small test and couldn't detect any problem.


Also the future vbulletin upgrade scripts are not going to take the changes into account and could cause issues there as well.

I agree with you.
To perform any update, one would need to uninstall the plugin (and undo changes to the hook), then update vB and install the plugin adapted for the new version.
I foresee hard time testing the feature, but I don't see another way to avoid multiple hacks (for the post counter, for the topic creator, for the last poster in the topic, for the user information in the topic itself, for the search and maybe more).

So, we have two options: change the data vB stores in the table node or multiple hacks to override fetchUserInfo.

ndoktoruser
10-19-2015, 11:24 AM
Here it is a functional code to replace the user with "Guest".

Instead of userid (an integer), the table node will save 0.
Instead of username for authorname, the table node will save Guest.

I picked those values, because old posts as anonymous from my old system were migrated with those values.

PS: I tried to not change any existing logic, expect of the userid and authorname, to avoid a higher possibility of including bugs.


-------------------

Notes:

page.php manages whether the checkbox should be displayed or not. Currently, it always returns true. However, page.php is only called when there is a submission of the whole page.
That means for ajax calls (case 1: when the user clicks to edit the post; case 2: when the user posts something in a thread), the anonymous checkbox won't appear.

The case 2 (or simply the whole thing to show the checkbox) should be fixed.


-------------------

1) Installing the plugin:
1.1) Download the file product_anonymous.xml attached to this post;
1.2) Install the product: go to "Products & Hooks" -> "Manage Products" -> "Add/Import Product" and install the .xml file;
2) Copying the page.php file with the function to enable the checkbox:
2.1) Create the structure /anonymous/api/ inside of /core/packages/, so you will have /core/packages/anonymous/api/;
2.2) Download the file page.php attached to this post;
2.3) Copy it to the directory /core/packages/anonymous/api/;
3) Create a new template: Go to "Style & Themes" -> "Style Manager" , then pick "Add New Tamplate" for "Default vB5 Style"
3.1) For this new template, set "anonymous_cb" as the title. Then add the following code:
<vb:if condition="$page['hasCheckbox'] == true">

<div class="b-content-entry-panel__content b-content-entry-panel__content--smiley h-clearfix">
<label class="js-collapse__link h-align-middle text-bold b-link js-link" for="checkbox_anonymous">Post as anonymous</label>
<input type="checkbox" id="checkbox_anonymous" name="anonymous_post" value="1">
</div>

</vb:if>
4) Change the file /core/vb/library/content.php
4.1) Look for the if statement (line 242-258):
// *************************************
// * Fill some default data if missing *
// *************************************
if (empty($data['userid']))
{
$user = vB::getCurrentSession()->fetch_userinfo();
$data['authorname'] = $user['username'];
$userid = $data['userid'] = $user['userid'];
}
else
{
$userid = $data['userid'];
if (empty($data['authorname']))
{
$data['authorname'] = vB_Api::instanceInternal('user')->fetchUserName($userid);
}
}
4.2) Add the following right after the if statement:
if ($_POST['anonymous_post'] === "1") {
$data['authorname'] = "Guest";
$userid = $data['userid'] = 0;
}
4.3) Now, look for the if statement (initially on the line 456, now it went to the line 460):
if (empty($nodevals['userid']))
4.4) Replace it with:
$isPostAnonymous = $_POST['anonymous_post'] === "1" && $nodevals['userid'] === 0;
if (empty($nodevals['userid']) && !$isPostAnonymous)
5) Change the file /core/vb/library/content/text.php
5.1) Look for the if statement (line 492-506):
if (empty($data['userid']))
{
$user = vB::getCurrentSession()->fetch_userinfo();
$data['authorname'] = $user['username'];
$userid = $data['userid'] = $user['userid'];
}
else
{
$userid = $data['userid'];
if (empty($data['authorname']))
{
$data['authorname'] = vB_Api::instanceInternal('user')->fetchUserName($userid);
}
$user = vB_Api::instance('user')->fetchUserinfo($userid);
}
5.2) Add the following right after the if statement:
if ($_POST['anonymous_post'] === "1") {
$data['authorname'] = "Guest";
$userid = $data['userid'] = 0;
}

ndoktoruser
10-19-2015, 11:41 AM
There are two major issues in the code:

1) User information still not saved in the table anonymous_log.
I didn't find any example in vb5 of a plugin which saves info in a new table. Does anyone know one?

2) Condition to display the checkbox needs to be treated in a proper way.
I added the hook to "editor_additional_panels". So how can I know whether it is a new post, a new topic or edition of an existing post?

Replicant
10-20-2015, 03:00 AM
Create the following directory structure in your product directory

db/mysql

Create a file called querydefs.php in the mysql directory, adjust column names as needed


<?php if (!defined('VB_ENTRY')) die('Access denied.');
class Anonymous_dB_MYSQL_QueryDefs extends vB_dB_QueryDefs
{
protected $db_type = 'MYSQL';
protected $saveDbCacheErrorState = false;
protected $table_data = array(
'anonymous_log' => array('key' => array('logid' , 'userid' , 'parentid' , 'nodeid'))
);
protected $query_data = array();
}


This is the code to do the insert. You will need to set the variables appropriately. These variables worked in my test. I tested it in the createcontent.php frontend controller in the createNewNode() function.


$userinfo = vB_Api::instance('user')->fetchUserInfo();
vB::getDbAssertor()->insert('Replinonymous:anonymous_log', array(
'userid' => $userinfo['userid'],
'logid' => '',
'parentid' => $input['parentid'],
'nodeid' => $nodeId
));

That's pretty much it. Any table you want to write to that is not in the vb querydefs file, has to have an entry in your product query defs file for the api to work. You can also put named queries in the querydefs file and call them with assertQuery().

ndoktoruser
10-28-2015, 01:00 PM
Hello Replicant, sorry for the long time with no reply, but I've tried it and it works fine!
Thank you for the help!

Soon I will edit the initial post and add the last state of all files.