You can save to the Attributes column whatever you like: simple values or arrays. So there is no need to create a string from out of the arrays. Therefore you don't need $userIDs = "[".implode(',', $userIDs)."]";
@MikeOlson said:
I understand that $sender->RequestArgs[0] is the discussionid
But you only have guessed that
Better would be to understand it and looking at Vanillas source code is very helpful here. You are inside of the discussionController...($sender) method. So $sender is a DiscussionController object. Look at the DiscussionController:
Why is that column name lower case? It really shouldn't be. What you see in there is a serialized string. It says it has an array with one element (I guess) and that the element is a string with 13 characters: DiscussionBan.
Something went wrong. Let me check my code and check if you have copied it the right way...
Oh no, the result of a:1:{s:13:"DiscussionBan";N;} is
array (
'DiscussionBan' => NULL,
);
So everything is correct except for the fact that $userIDs is null when you save it. There is a typo:
$userIDs = [];
foreach ($userArray as $name) {
$userModel = new UserModel();
$user = $userModel->getByUsername($name);
$userIDs[] = $user->UserID;
}
...
$discussionModel->saveToSerializedColumn(
'Attributes', // The column name
$sender->RequestArgs[0], // You should find out what this is
'DiscussionBan', // This serves as a internal key so that we can identify our d
$userIds
);
@R_J said:
You can save to the Attributes column whatever you like: simple values or arrays. So there is no need to create a string from out of the arrays. Therefore you don't need $userIDs = "[".implode(',', $userIDs)."]";
@MikeOlson said:
I understand that $sender->RequestArgs[0] is the discussionid
But you only have guessed that
Better would be to understand it and looking at Vanillas source code is very helpful here. You are inside of the discussionController...($sender) method. So $sender is a DiscussionController object. Look at the DiscussionController:
@R_J said:
Oh no, the result of a:1:{s:13:"DiscussionBan";N;} is
array (
'DiscussionBan' => NULL,
);
So everything is correct except for the fact that $userIDs is null when you save it. There is a typo:
$userIDs = [];
foreach ($userArray as $name) {
$userModel = new UserModel();
$user = $userModel->getByUsername($name);
$userIDs[] = $user->UserID;
}
...
$discussionModel->saveToSerializedColumn(
'Attributes', // The column name
$sender->RequestArgs[0], // You should find out what this is
'DiscussionBan', // This serves as a internal key so that we can identify our d
$userIds
);
The last $userIDs has a lower case "d".
Aha!!! I see it. I think that was the result of intellisense on my editor because at one point I had it with the lower case d and I must have hit return when it had that highlighted. I hate "intelli"sense
@MikeOlson said:
I went looking how to do that in the discussion model but I didn't see how to do that. (In fact I didn't see the save to serialized either)
@MikeOlson said:
INteresting on how to follow the controllers back.
This time you have to follow back the DiscussionModels ancestors
If I do print_r($DiscussionModel) I can see all the data for that row in the discussion table.
Shouldn't $discussionAttributes = $DiscussionModel->Attributes; pull out just the attributes field from that?
instead I was able to get the value of the attributes field by using a query:
$DiscussionID = $sender->RequestArgs[0];
$Attributes = Gdn::sql()
->select('Attributes')
->from('Discussion')
->where('DiscussionID',$DiscussionID)
->get(); // Now it's a dataset!
//print_r($Attributes);
foreach ($Attributes->resultArray() as $attribute) {
// Do something to each user with 1 comment.
print_r($attribute);
}
Not sure this is the best method to use and then I need to figure out how to loop through the data
The result of discussionModel->getID is a discussion object. That's what you are looking for. So you would need to use it like that $Discussion = $DiscussionModel->getID($DiscussionID);. Afterwards you have a Discussion object that you holds the information you need.
If you look at the contents of the $discussion with print_r you would find everything you need.
Here is my class...Where I do not know how to get at the attributes data. While I have done a lot of PHP scripting I am new to object oriented PHP coding.
<?php
// Define the plugin:
$PluginInfo['discussionBan'] = array(
'Name' => 'Discussion Ban',
'Description' => 'Grants moderators or permissioned users ability to ban users from specific discussions',
'Version' => '1.1',
'RequiredApplications' => array('Vanilla' => '>=2.3'),
'RequiredTheme' => false,
'RequiredPlugins' => false,
'HasLocale' => true,
'License' => 'GNU GPL2',
'Author' => "Mike Olson",
'AuthorUrl' => 'https://open.vanillaforums.com/profile/MikeOlson'
);
/**
* Class DiscussionBanPlugin
*
* @see http://docs.vanillaforums.com/developers/plugins
* @see http://docs.vanillaforums.com/developers/plugins/quickstart
*/
class DiscussionBanPlugin extends Gdn_Plugin {
public function base_discussionOptions_handler($sender, $args) {
// If user hasn't moderator permissions, we do not want to edit anything.
if (!Gdn::session()->checkPermission('Garden.Moderation.Manage')) {
return;
}
if (isset($args['DiscussionOptions'])) {
/*
$args['DiscussionOptions']['discussionBan'] = array(
'Label' => t('Ban Users From This Discussion'),
'Url' => 'discussion/discussionBan/'.$args['Discussion']->DiscussionID,
'Class' => 'Popup'
);
*/
$args['DiscussionOptions']['discussionBan'] = [
'Label' => t('Ban User from Discussion'),
'Url' => url('discussion/discussionban/'.$args['Discussion']->DiscussionID),
'Class' => 'Popup'
];
}
}
/**
* Add autocomplete.js to every page.
*
* @param GardenController $sender Instance of the calling class.
*
* @return void.
*/
public function base_render_before($sender) {
$sender->addJsFile('jquery.tokeninput.js');
}
/**
* Show ban user form and save results to discussion attributes.
*
* @param PluginController $sender Instance of the calling class
*
* @return void.
*/
public function discussionController_discussionBan_create($sender) {
$sender->permission('Garden.Moderation.Manage');
$sender->Form = new Gdn_Form();
$sender->setData('Title', t('Ban Users From This Discussion'));
if ($sender->Form->authenticatedPostBack() == false) {
// This will be run when the view is opened
//$sender->Form->setValue('UserNames', 'HelloWorld');
$DiscussionID = $sender->RequestArgs[0];
$DiscussionModel = new DiscussionModel();
$DiscussionModel->getID($DiscussionID);
$array = get_object_vars($DiscussionModel);
print_r($DiscussionModel->data->Attributes);
// ^^ I do not know how to get at the attributes array
print_r($array);
} else {
// This will only be run when the user pressed the button.
$userNames = $sender->Form->getFormValue('UserNames', false);
if ($userNames === false) {
return;
}
//print_r($userNames)."<br /><br />";
$userArray = explode(',', $userNames);
//print_r($userArray)."<br /><br />";
//print_r($sender->RequestArgs[0]);
$userIDs = [];
foreach ($userArray as $name) {
$userModel = new UserModel();
$user = $userModel->getByUsername($name);
$userIDs[] = $user->UserID;
}
//print_r($userIDs);
$userIDs = "[".implode(',', $userIDs)."]";
//print_r($userIDs);
$discussionModel = new DiscussionModel(); // Since we want to save to discussion table...
$discussionModel->saveToSerializedColumn(
'Attributes', // The column name
$sender->RequestArgs[0], // You should find out what this is
'DiscussionBan', // This serves as a internal key so that we can identify our d
$userIDs
);
$sender->informMessage(t("Your changes have been saved."));
}
$sender->render('discussionBan', '', 'plugins/discussionBan');
}
}
Here is my view...
<?php if (!defined('APPLICATION')) exit(); ?>
<h1><?php echo $this->data('Title') ?></h1>
<div class="FormWrapper DiscussionBan">
<?php
echo $this->Form->open();
echo $this->Form->errors();
?>
<ul>
<li>
<?php
echo $this->Form->label('Users to ban', 'UserNames');
echo wrap(
$this->Form->textBox('UserNames', array('class' => 'InputBox MultiComplete')),
'div',
array('class' => 'TextBoxWrapper')
);
?>
</li>
</ul>
<?php
echo $this->Form->close('Ban Users');
/*
$discussionModel = new DiscussionModel(); // Since we want to save to discussion table...
$discussionModel->saveToSerializedColumn(
'Attributes', // The column name
$sender->RequestArgs[0], // You should find out what this is
'DiscussionBan', // This serves as a internal key so that we can identify our d
[1,2,3,4,5]
);
*/
?>
</div>
<script>
jQuery(document).ready(function($) {
$.fn.userTokenInput = function() {
$(this).each(function() {
/// Author tag token input.
var $author = $(this);
var author = $author.val();
if (author && author.length) {
author = author.split(",");
for (i = 0; i < author.length; i++) {
author[i] = { id: i, name: author[i] };
}
} else {
author = [];
}
$author.tokenInput(gdn.url('/user/tagsearch'), {
hintText: gdn.definition("TagHint", "Start to type..."),
tokenValue: 'name',
searchingText: '', // search text gives flickery ux, don't like
searchDelay: 300,
minChars: 1,
zindex: 9999,
prePopulate: author,
animateDropdown: false
});
});
};
$('.MultiComplete').userTokenInput();
});
</script>
Alright, here is the plugin with a few changes:
1. added 'MobileFriendly' => true, to PluginInfo array so that your plugin would also be available on mobile browsers
2. I understood that you have a problem with the short array notation: only using [1,2,3] instead of array(1,2,3) isn't working for you. You should update your PHP version! I've deleted a comment block from base_discussionOptions_handler
3. Added docblock to base_discussionOptions_handler
4. Added some extra blank lines and removed trailing spaces here and there
5. New line 72 & 73: print discussion attributes
6. Commente the wrong $userIDs = "[".implode(',', $userIDs)."]";
<?php
// Define the plugin:
$PluginInfo['discussionBan'] = array(
'Name' => 'Discussion Ban',
'Description' => 'Grants moderators or permissioned users ability to ban users from specific discussions',
'Version' => '1.1',
'RequiredApplications' => array('Vanilla' => '>=2.3'),
'RequiredTheme' => false,
'RequiredPlugins' => false,
'MobileFriendly' => true,
'HasLocale' => true,
'License' => 'GNU GPL2',
'Author' => "Mike Olson",
'AuthorUrl' => 'https://open.vanillaforums.com/profile/MikeOlson'
);
/**
* Class DiscussionBanPlugin
*
* @see http://docs.vanillaforums.com/developers/plugins
* @see http://docs.vanillaforums.com/developers/plugins/quickstart
*/
class DiscussionBanPlugin extends Gdn_Plugin {
/**
* Add new entry to discussion options.
*
* @param GardenController $sender Instance of the calling class.
* @param mixed $args Event arguments.
*
* @return void.
*/
public function base_discussionOptions_handler($sender, $args) {
// If user hasn't moderator permissions, we do not want to edit anything.
if (!Gdn::session()->checkPermission('Garden.Moderation.Manage')) {
return;
}
if (isset($args['DiscussionOptions'])) {
$args['DiscussionOptions']['discussionBan'] = array(
'Label' => t('Ban User from Discussion'),
'Url' => 'discussion/discussionBan/'.$args['Discussion']->DiscussionID,
'Class' => 'Popup'
);
}
}
/**
* Add autocomplete.js to every page.
*
* @param GardenController $sender Instance of the calling class.
*
* @return void.
*/
public function base_render_before($sender) {
$sender->addJsFile('jquery.tokeninput.js');
}
/**
* Show ban user form and save results to discussion attributes.
*
* @param PluginController $sender Instance of the calling class
*
* @return void.
*/
public function discussionController_discussionBan_create($sender) {
$sender->permission('Garden.Moderation.Manage');
$sender->Form = new Gdn_Form();
$sender->setData('Title', t('Ban Users From This Discussion'));
if ($sender->Form->authenticatedPostBack() == false) {
// This will be run when the view is opened
//$sender->Form->setValue('UserNames', 'HelloWorld');
$DiscussionID = $sender->RequestArgs[0];
$DiscussionModel = new DiscussionModel();
$Discussion = $DiscussionModel->getID($DiscussionID);
print_r($Discussion->Attributes);
} else {
// This will only be run when the user pressed the button.
$userNames = $sender->Form->getFormValue('UserNames', false);
if ($userNames === false) {
return;
}
//print_r($userNames)."<br /><br />";
$userArray = explode(',', $userNames);
//print_r($userArray)."<br /><br />";
//print_r($sender->RequestArgs[0]);
$userIDs = [];
foreach ($userArray as $name) {
$userModel = new UserModel();
$user = $userModel->getByUsername($name);
$userIDs[] = $user->UserID;
}
//print_r($userIDs);
// wrong: $userIDs = "[".implode(',', $userIDs)."]";
//print_r($userIDs);
$discussionModel = new DiscussionModel(); // Since we want to save to discussion table...
$discussionModel->saveToSerializedColumn(
'Attributes', // The column name
$sender->RequestArgs[0], // Holds the discussion ID
'DiscussionBan', // Internal key
$userIDs
);
$sender->informMessage(t("Your changes have been saved."));
}
$sender->render('discussionBan', '', 'plugins/discussionBan');
}
}
I will give some explanation on that - give me some time...
Comments
Hmmm this is what was saved in the discussion table:
You can save to the Attributes column whatever you like: simple values or arrays. So there is no need to create a string from out of the arrays. Therefore you don't need
$userIDs = "[".implode(',', $userIDs)."]";
But you only have guessed that
Better would be to understand it and looking at Vanillas source code is very helpful here. You are inside of the discussionController...($sender) method. So $sender is a DiscussionController object. Look at the DiscussionController:
https://github.com/vanilla/vanilla/blob/release/2.3/applications/vanilla/controllers/class.discussioncontroller.php#L14
It doesn't have a RequestArgs property. But it extends the VanillaController, so we can take a look there:
https://github.com/vanilla/vanilla/blob/release/2.3/applications/vanilla/controllers/class.vanillacontroller.php#L14
No RequestArgs here. But this controller extends the "base" controller: Gdn_Controller (base, because every controller extends that one)
And here in the base controller you will find a clean explanation for "RequestArgs":
https://github.com/vanilla/vanilla/blob/release/2.3/library/core/class.controller.php#L88-L97
Why is that column name lower case? It really shouldn't be. What you see in there is a serialized string. It says it has an array with one element (I guess) and that the element is a string with 13 characters: DiscussionBan.
Something went wrong. Let me check my code and check if you have copied it the right way...
Oh no, the result of
a:1:{s:13:"DiscussionBan";N;}
isSo everything is correct except for the fact that $userIDs is null when you save it. There is a typo:
The last $userIDs has a lower case "d".
I got that from doing a print_r on it and saw the value.
INteresting on how to follow the controllers back.
Aha!!! I see it. I think that was the result of intellisense on my editor because at one point I had it with the lower case d and I must have hit return when it had that highlighted. I hate "intelli"sense
Ok now it is saving: a:1:{s:13:"DiscussionBan";s:7:"[16,19]";}
That looks right for the users that I selected in the form
Reading Vanillas source and investigating in there is the best way to become a plugin author!
I will be reviewing this entire thread for quite some time over and over and over again.
Ok so one of the first steps I need to do is to populate the text box if there already was people banned from the thread.
I went looking how to do that in the discussion model but I didn't see how to do that. (In fact I didn't see the save to serialized either)
Yes, you really should
What is it that you want to populate? A field in the database (class model) or a form field (class form)?
https://open.vanillaforums.com/discussion/comment/248317/#Comment_248317
This time you have to follow back the DiscussionModels ancestors
Not sure why this isn't working:
If I do
print_r($DiscussionModel)
I can see all the data for that row in the discussion table.Shouldn't
$discussionAttributes = $DiscussionModel->Attributes;
pull out just the attributes field from that?instead I was able to get the value of the attributes field by using a query:
Not sure this is the best method to use and then I need to figure out how to loop through the data
You need
>
The result of discussionModel->getID is a discussion object. That's what you are looking for. So you would need to use it like that
$Discussion = $DiscussionModel->getID($DiscussionID);
. Afterwards you have a Discussion object that you holds the information you need.If you look at the contents of the $discussion with print_r you would find everything you need.
Yeah I did a print_r on $discussion and found that there were like 3 listing for attributes.
If a discussion has Attributes (not every discussion need to have that information) it is stored as an array.
Maybe it's time to post your complete code to do some cleaning on it and see what is working and what is missing
Here is my class...Where I do not know how to get at the attributes data. While I have done a lot of PHP scripting I am new to object oriented PHP coding.
Here is my view...
Alright, here is the plugin with a few changes:
1. added
'MobileFriendly' => true,
to PluginInfo array so that your plugin would also be available on mobile browsers2. I understood that you have a problem with the short array notation: only using
[1,2,3]
instead ofarray(1,2,3)
isn't working for you. You should update your PHP version! I've deleted a comment block frombase_discussionOptions_handler
3. Added docblock to
base_discussionOptions_handler
4. Added some extra blank lines and removed trailing spaces here and there
5. New line 72 & 73: print discussion attributes
6. Commente the wrong
$userIDs = "[".implode(',', $userIDs)."]";
I will give some explanation on that - give me some time...