@michaelontheroof: had forgotten this discussion - will examine my installations troubles soon.
Meanwhile, I have a suggestion! Wouldn't it be cool to integrate Predefined Attributes with the Announcements add-on? On many forums there will be members who registered before the predefined attributes add-on was implemented. They would then (I assume) have empty or missing data fields in their profile. My thought was to make the announcement add-on discretely 'irritate' the old members to go in and update their profiles. What do you think?
Error Message An error occurred while creating a column
Affected Elements PredefinedAttributes.Install();
The error occurred on or near: You have an error in your SQL syntax near 'COMMENT 'Created by Predefined Attributes Extension' AFTER Attributes' at line 3
Terrific extension. Just have one question and two small bugs:
QUESTION: Is there a way to get the predefined attributes to appear in the New Applicant Email notification? This would be an incredibly helpful feature.
BUG 1: All radio buttons are given checked="checked" attributes instead of only the default radio button.
BUG 2: While the application form properly displays a formatted error message for users who don't fill in the required predefined attributes.... it is possible for someone to then open up their Account profile and, say, switch a drop-down menu to the empty select value and remove their required information. I get the following error when this happens:
Notice: Undefined property: UserManager::$User in /home/.mypath/extensions/PredefinedAttributes/default.php on line 552
I was also having the install MySQL error "You have an error in your SQL syntax near 'COMMENT 'Created by Predefined Attributes Extension' AFTER Attributes' at line 3.
Simply open the default.php file, find the line that says COMMENT 'Created by Predefined Attributes Extension', and remove it. I'm pretty sure MySQL doesn't support a command called COMMENT, though it may just be the older versions that don't. It's not listed as a reserved word in the manual.
After activating PA, when I call "settings.php?PostBackAction=InstallPredefinedAttributes" I get no messages at all - the VF wrapper is there, but nothing in the main content area - should something be in there? I checked the table, and the PredefinedAttributes field is there - then when I run "extensions/PredefinedAttributes/default.php" I get "Warning: array_key_exists(): The second argument should be either an array or an object in /home/content/t/e/v/tevigen2/html/vf/extensions/PredefinedAttributes/default.php on line 429". I haven't changed any of the files. I had no other extensions installed when installing PA (although I do now). I am running Vanilla 1.0.3. Please help.
Also, the zip file is very confusing with all the different files - some in separate folders, some in subfolders. I'm not 100% sure I uploaded the correct files. I uploaded the PredefinedAttributes folder (in the PredefinedAttributes_v0.3.3 folder) with .DS_Store and default.php files in it.
Thank you!
Is it possible to make the information entered appear on the "Member"-page created by the extension "Members Page" or at the users account page (account.php?u=<IdOfUser>)?
Anything's possible You'll probably want to post that information in that addon's discussion though as it would most likely be a change to that, not this.
Upon entering my website and checking my user account page, the text entered is there but it does not link to the website. Most of my users would want this rather than having to user the default Vanilla custom information fields.
I echo Resilient suggestion. I imagine the easiest thing to do would be create a new type, and display that type as a hyperlink. I'm not familiar enough with the vanilla functions to see where to put it in the default.php (or how to for that matter).
You want to do something like this (this code isn't working for me yet, the new type in the case is 'Web').
function AddToAccountPage() {
$this->GetAttributesFromDatabase();
//trying to get type
/*if (array_key_exists("Type", $Attribute) && array_key_exists("Data", $Attribute) && is_array($Attribute["Data"])) {
$Type = $Attribute["Type"];
} else {
$Type = "Input";
}
$Txt = $Type.':';
*/
//$Txt .= '<h1>'.$this->Context->GetDefinition("PredefinedAttributesTitle").'</h1>';
//$Txt .= '<ul>';
$Txt ="";
foreach($this->Attributes as $a) {
if ($this->getUserAttribute($a['Label'], false)){
if (!$this->isHidden($a['Label'])
|| ($this->User->UserID == $this->Context->Session->UserID)
|| in_array('PERMISSION_APPROVE_APPLICANTS', $this->Context->Session->User->Permissions)) {
$Txt .= '<li><h3>'.$a['Label'].'</h3>';
$Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>';
}
}
}
//$Txt .= '</ul>';
echo $Txt;
}
What we need is a way to get the type, which I assume is stored in the array/database somewhere. Once you get the type, you do an if statement and go from there.
Looking into the sql tables, it doesn't record the type. But it does have some abstract things happening which may help out. If that doesn't work, then I think this can't be done with the way this extension is designed.
i tried to manually change the data stored in the sql to a hyperlink, and that caused problems--- so I'm pretty sure now if you want to make a link you have to do it when its being displayed (not setting it up when its being captured).
Next idea is to parse the text, and if starts with "http://" then make it into a html tag.
Update: Got it to work. In function AddToAccountPage add/modify the following
if (substr($this->getUserAttribute($a['Label'], false),0,7) == "http://"){
$Txt .= '<a href='.$this->getUserAttribute($a['Label'],false).'>'.$this->getUserAttribute($a['Label'],false).'</a>';
}
else{
$Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>';
}
Line preceding where this goes should be: $Txt .= '<li><h3>'.$a['Label'].'</h3>';
Full function is (since it hard to use line numbers, as everyones will be different due to their arrays at the start): function AddToAccountPage() {
$this->GetAttributesFromDatabase();
//$Txt .= '<h1>'.$this->Context->GetDefinition("PredefinedAttributesTitle").'</h1>';
//$Txt .= '<ul>';
$Txt ="";
foreach($this->Attributes as $a) {
if ($this->getUserAttribute($a['Label'], false)){
if (!$this->isHidden($a['Label'])
|| ($this->User->UserID == $this->Context->Session->UserID)
|| in_array('PERMISSION_APPROVE_APPLICANTS', $this->Context->Session->User->Permissions)) {
$Txt .= '<li><h3>'.$a['Label'].'</h3>';
if (substr($this->getUserAttribute($a['Label'], false),0,7) == "http://"){
$Txt .= '<a href='.$this->getUserAttribute($a['Label'],false).'>'.$this->getUserAttribute($a['Label'],false).'</a>';
}
else{
$Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>';
}
}
}
}
//$Txt .= '</ul>';
echo $Txt;
}
Next task: if predefined value is "http://" , make it blank. Reason: If people make new predefinedattribute for a webpage, they may want the default value to be "http://". And users enter what goes after that. If the user doesn't have a page, they may be lazy and not remove the http.
To solve the last question I posed (if you have a default value of http:// for a text box, and want to prevent that accidently being displayed as a link to just http://) add the one following line:
In the function, GetAttributesFromForm, add this line
if ($Value=="http://") $Value="";
between
$Label = str_replace("\\\"", "", $Label);
$Value = strip_tags($Value);
Full Function with modifications:
function GetAttributesFromForm() {
$UserAttributes = array();
$Label = "";
$Value = "";
$Attributes = ForceIncomingArray("PredefinedAttributes", array());
foreach ($Attributes as $Label => $Value) {
if ($this->isRequired($Label) && trim($Value) == "") {
//in next release use Vanillas Validate() Function
$this->Context->WarningCollector->Add(str_replace('//1', $Label, $this->Context->GetDefinition('ErrRequiredInput')));
} else {
$Label = strip_tags($Label);
$Label = str_replace("\\\"", "", $Label);
if ($Value=="http://") $Value="";
$Value = strip_tags($Value);
$Value = str_replace("\\\"", "", $Value);
if ($Label != "" && $Value != "") $UserAttributes[] = array("Label" => $Label, "Value" => $Value);
}
}
$this->UserAttributes = $UserAttributes;
}
I am experiencing a massively dangerous oversight within this extension in that setting fields as hidden is simply not hiding them!! A registered user can search for and look at any other user's predefined attributes on their user page even though I have set the data to hidden. Anyone else experiencing this?
This part of the conditional statement is aiming to check if the user has Applicant Approval permissions - which, if true, assumes that the user is an admin and can therefore show the hidden fields on the account page. However, the existence of the array key does not reliably indicate an admin, as a user can have that array key but with it set to 0 which simply means a user without approval permissions.
Instead, I've amended the code so it checks to see if this attribute is equal to 1. Replace the above with this line and hidden fields will really be hidden fields:
This works and fixes the problem but isn't a reliable indication of the user being an admin. However, it's the best I could do in the time I had to find a fix.
Does anyone know of a more reliable way to check if a user is an admin?
michaelontheroof - I really, really appreciate the time you've taken to build this plug-in, I do, but this was a dangerous oversight in terms of data protection!
Hello! I wanted to be able to access the new predefined attributes in the user session data. I'm pasting the following modifications to enable these new values to be accessed. Some of it could be done differently to make the key-value pairs easier to get to, but it should do to get someone up and running quickly.
This enables you for example to use the new values outside of vanilla in an integration project. I've included line numbers and those line numbers' content as the numbers could be different in your project. If you cannot match the line number in your code to what I have provided, search for the code itself.
And as always use this code at your own risk. I cannot guarantee that it will work in your project. This has only been tested on my own custom installation. I cannot be liable for any results that do not equal 100% success.
Comments
Error Message
An error occurred while creating a column
Affected Elements
PredefinedAttributes.Install();
The error occurred on or near: You have an error in your SQL syntax near 'COMMENT 'Created by Predefined Attributes Extension' AFTER Attributes' at line 3
Posted: Thursday, 15 February 2007 at 8:33AM (AEDT)
Here's how I have altered the code:
var $Attributes = array( array( "Label" => "LAN-förening", "Required" => true, "Value" => "", "Hidden" => false, "Description" => "Fyll i vilken LAN-förening du tillhör!" ) );
array( "Label" => "Website", "Required" => false, "Value" => "http://", "Hidden" => false, )
Upon entering my website and checking my user account page, the text entered is there but it does not link to the website. Most of my users would want this rather than having to user the default Vanilla custom information fields.
You want to do something like this (this code isn't working for me yet, the new type in the case is 'Web').
function AddToAccountPage() { $this->GetAttributesFromDatabase(); //trying to get type /*if (array_key_exists("Type", $Attribute) && array_key_exists("Data", $Attribute) && is_array($Attribute["Data"])) { $Type = $Attribute["Type"]; } else { $Type = "Input"; } $Txt = $Type.':'; */ //$Txt .= '<h1>'.$this->Context->GetDefinition("PredefinedAttributesTitle").'</h1>'; //$Txt .= '<ul>'; $Txt =""; foreach($this->Attributes as $a) { if ($this->getUserAttribute($a['Label'], false)){ if (!$this->isHidden($a['Label']) || ($this->User->UserID == $this->Context->Session->UserID) || in_array('PERMISSION_APPROVE_APPLICANTS', $this->Context->Session->User->Permissions)) { $Txt .= '<li><h3>'.$a['Label'].'</h3>'; $Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>'; } } } //$Txt .= '</ul>'; echo $Txt; }
What we need is a way to get the type, which I assume is stored in the array/database somewhere. Once you get the type, you do an if statement and go from there.
Looking into the sql tables, it doesn't record the type. But it does have some abstract things happening which may help out. If that doesn't work, then I think this can't be done with the way this extension is designed.
Next idea is to parse the text, and if starts with "http://" then make it into a html tag.
Update: Got it to work.
In function AddToAccountPage add/modify the following
if (substr($this->getUserAttribute($a['Label'], false),0,7) == "http://"){ $Txt .= '<a href='.$this->getUserAttribute($a['Label'],false).'>'.$this->getUserAttribute($a['Label'],false).'</a>'; } else{ $Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>'; }
Line preceding where this goes should be:
$Txt .= '<li><h3>'.$a['Label'].'</h3>';
Full function is (since it hard to use line numbers, as everyones will be different due to their arrays at the start):
function AddToAccountPage() { $this->GetAttributesFromDatabase(); //$Txt .= '<h1>'.$this->Context->GetDefinition("PredefinedAttributesTitle").'</h1>'; //$Txt .= '<ul>'; $Txt =""; foreach($this->Attributes as $a) { if ($this->getUserAttribute($a['Label'], false)){ if (!$this->isHidden($a['Label']) || ($this->User->UserID == $this->Context->Session->UserID) || in_array('PERMISSION_APPROVE_APPLICANTS', $this->Context->Session->User->Permissions)) { $Txt .= '<li><h3>'.$a['Label'].'</h3>'; if (substr($this->getUserAttribute($a['Label'], false),0,7) == "http://"){ $Txt .= '<a href='.$this->getUserAttribute($a['Label'],false).'>'.$this->getUserAttribute($a['Label'],false).'</a>'; } else{ $Txt .= '<p>'.$this->getUserAttribute($a['Label'], false).'</p></li>'; } } } } //$Txt .= '</ul>'; echo $Txt; }
Next task: if predefined value is "http://" , make it blank.
Reason: If people make new predefinedattribute for a webpage, they may want the default value to be "http://". And users enter what goes after that. If the user doesn't have a page, they may be lazy and not remove the http.
In the function, GetAttributesFromForm, add this line
if ($Value=="http://") $Value="";
between
$Label = str_replace("\\\"", "", $Label); $Value = strip_tags($Value);
Full Function with modifications:
function GetAttributesFromForm() { $UserAttributes = array(); $Label = ""; $Value = ""; $Attributes = ForceIncomingArray("PredefinedAttributes", array()); foreach ($Attributes as $Label => $Value) { if ($this->isRequired($Label) && trim($Value) == "") { //in next release use Vanillas Validate() Function $this->Context->WarningCollector->Add(str_replace('//1', $Label, $this->Context->GetDefinition('ErrRequiredInput'))); } else { $Label = strip_tags($Label); $Label = str_replace("\\\"", "", $Label); if ($Value=="http://") $Value=""; $Value = strip_tags($Value); $Value = str_replace("\\\"", "", $Value); if ($Label != "" && $Value != "") $UserAttributes[] = array("Label" => $Label, "Value" => $Value); } } $this->UserAttributes = $UserAttributes; }
|| in_array('PERMISSION_APPROVE_APPLICANTS', $this->Context->Session->User->Permissions)) {
This part of the conditional statement is aiming to check if the user has Applicant Approval permissions - which, if true, assumes that the user is an admin and can therefore show the hidden fields on the account page. However, the existence of the array key does not reliably indicate an admin, as a user can have that array key but with it set to 0 which simply means a user without approval permissions.
Instead, I've amended the code so it checks to see if this attribute is equal to 1. Replace the above with this line and hidden fields will really be hidden fields:
|| (@$this->Context->Session->User->Permissions['PERMISSION_APPROVE_APPLICANTS'] == '1')) {
This works and fixes the problem but isn't a reliable indication of the user being an admin. However, it's the best I could do in the time I had to find a fix.
Does anyone know of a more reliable way to check if a user is an admin?
michaelontheroof - I really, really appreciate the time you've taken to build this plug-in, I do, but this was a dangerous oversight in terms of data protection!
Best wishes,
Keir
I wanted to be able to access the new predefined attributes in the user session data.
I'm pasting the following modifications to enable these new values to be accessed.
Some of it could be done differently to make the key-value pairs easier to get to, but it should do to get someone up and running quickly.
This enables you for example to use the new values outside of vanilla in an integration project.
I've included line numbers and those line numbers' content as the numbers could be different in your project.
If you cannot match the line number in your code to what I have provided, search for the code itself.
And as always use this code at your own risk.
I cannot guarantee that it will work in your project.
This has only been tested on my own custom installation.
I cannot be liable for any results that do not equal 100% success.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Access New Fields By:
$Context->Session->User->PredefinedAttributes[0]['Label']; $Context->Session->User->PredefinedAttributes[0]['Value'];
etc.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Make the following modifications:
People.Class.UserManager.php
/library/Framework/People.Class.UserManager.php
After Line 314
$s->AddFieldNameValue('Attributes', '');
Add:
$s->AddFieldNameValue('PredefinedAttributes', '');
Change Line 445
$s->AddSelect(array('UserID', 'Name', 'FirstName', 'LastName', 'Email', 'UtilizeEmail', 'Icon', 'Picture', 'Attributes', 'Preferences', 'CountVisit', 'CountDiscussions', 'CountComments', 'RemoteIp', 'DateFirstVisit', 'DateLastActive', 'RoleID', 'StyleID', 'CustomStyle', 'ShowName', 'UserBlocksCategories', 'DefaultFormatType', 'Discovery', 'SendNewApplicantNotifications'), 'u');
- to -
$s->AddSelect(array('UserID', 'Name', 'FirstName', 'LastName', 'Email', 'UtilizeEmail', 'Icon', 'Picture', 'Attributes', 'PredefinedAttributes','Preferences', 'CountVisit', 'CountDiscussions', 'CountComments', 'RemoteIp', 'DateFirstVisit', 'DateLastActive', 'RoleID', 'StyleID', 'CustomStyle', 'ShowName', 'UserBlocksCategories', 'DefaultFormatType', 'Discovery', 'SendNewApplicantNotifications'), 'u');
Change Line 609
$s->AddSelect(array('UserID', 'RoleID', 'StyleID', 'CustomStyle', 'FirstName', 'LastName', 'Name', 'Email', 'UtilizeEmail', 'Icon', 'CountVisit', 'CountDiscussions', 'CountComments', 'DateFirstVisit', 'DateLastActive'), 'u');
- to -
$s->AddSelect(array('UserID', 'RoleID', 'StyleID', 'CustomStyle', 'FirstName', 'LastName', 'Name', 'Email', 'UtilizeEmail', 'PredefinedAttributes', 'Icon', 'CountVisit', 'CountDiscussions', 'CountComments', 'DateFirstVisit', 'DateLastActive'), 'u');
Change Line 648
$s->AddSelect(array('Name', 'UserID', 'RoleID', 'StyleID', 'CustomStyle', 'UserBlocksCategories', 'DefaultFormatType', 'Preferences', 'SendNewApplicantNotifications'), 'u');
- to -
$s->AddSelect(array('Name', 'UserID', 'RoleID', 'StyleID', 'CustomStyle', 'PredefinedAttributes', 'UserBlocksCategories', 'DefaultFormatType', 'Preferences', 'SendNewApplicantNotifications'), 'u');
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
People.Class.User.php
/library/Framework/People.Class.User.php
After Line 46
var $Attributes;
Add:
var $PredefinedAttributes;
After Line 108
$this->Attributes = array();
Add:
$this->PredefinedAttributes = array();
After Line 162
$this->Attributes = SerializeArray($this->Attributes);
Add:
$this->PredefinedAttributes = SerializeArray($this->Attributes);
After Line 208
$this->Attributes = UnserializeArray($this->Attributes);
Add:
$this->PredefinedAttributes = ''; $this->PredefinedAttributes = ForceString(@$DataSet['PredefinedAttributes'],''); $this->PredefinedAttributes = UnserializeArray($this->PredefinedAttributes);
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
database.php
/appg/database.php
After Line 119
$DatabaseColumns['User']['Attributes'] = 'Attributes';
Add:
$DatabaseColumns['User']['PredefinedAttributes'] = 'PredefinedAttributes';
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
You can use the session object to get the user-role ID - that can then be checked against the value for admin.
If you do a:
print_r($Context->Session);
You will see all of the contents of the $Context Object - and what values you can access.
My above modification also gives clues on how to add things to the user session object as well.
-Randall