PDA

View Full Version : datamanager_init('User') save() "Duplicate entry" error in "usertextfield" table


inmateaid
12-01-2012, 12:25 PM
I have spent the last 2 days trying to integrate vB 4.2 into CI 2.1.2...

Everything seems fine, but the datamanager outputs an SQL error page when saving a new user (outside of vB).

My index.php...

<?php

// vBulletin
define('REGISTERED_USERGROUP', 2); // typical default for registered users
define('PERMANENT_COOKIE', false); // false=session cookies (recommended)
define('THIS_SCRIPT', __FILE__);
define('VB_AREA', 'External');
$dir = getcwd();
chdir('forum/');
require_once('./includes/init.php'); // includes class_core.php
require_once('./includes/class_dm.php'); // for class_dm_user.php
require_once('./includes/class_dm_user.php'); // for user functions
require_once('./includes/functions.php'); // vbsetcookie etc.
require_once('./includes/functions_login.php'); // process login/logout
chdir($dir);




My library...

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Forum2 {

private $dmuser;

public function __construct()
{
global $vbulletin;
$this->dmuser =& datamanager_init('User', $vbulletin, ERRTYPE_ARRAY);
}

public function register($data = array(), $login = FALSE)
{
global $vbulletin;
foreach ($data as $key => $value) {
if (!is_array($value)) {
$this->dmuser->set($key, $value);
}
}
if (isset($data['options']) && is_array($data['options'])) {
foreach ($data['options'] as $key => $value) {
$this->dmuser->set_bitfield('options', $key, $value);
}
}
$this->dmuser->pre_save();
//print_r($this->dm);
if (count($this->dmuser->errors) > 0) {
return implode('<li>', $this->dmuser->errors);
}
return $this->dm->save();
}
}


My controller...

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Sandbox extends CI_Controller {

public function __construct()
{
parent::__construct();
}

public function vb_test()
{
$this->load->library('forum2');
$this->forum2->register(array(
'username' => 'testing5',
'email' => 'test@test5.com',
'password' => 'password5'
));
}

}


Loading mydomain.com/sandbox/vb_test generates the vB sql error page and I receive the following email...

Database error in vBulletin 4.2.0:

Invalid SQL:
INSERT INTO usertextfield
(userid)
VALUES
(29);

MySQL Error : Duplicate entry '29' for key 1


I am at a loss. Why is the datamanager is trying to insert the "usertextfield" record twice? The records for user, userfield, and usertextfield are all added to the database. I simply can't figure out why the sql error is coming through using the datamanager. I've rewritten this library a few times already to make sure it was an issue with me providing incorrect data to the manager, but nothing gets around this problem.

Please help :(

Notes: We have a custom cms in place that already has users. Any new registrations will be processed on the main site, and our script adds the forum user to the vB database using the datamanager. Registration and login are handled externally. Login/logout works fine so I did not include those methods in the code above.

kh99
12-01-2012, 01:09 PM
When updating an existing user the vb code uses the datamanager function set_existing() and passes an array of the data, instead of calling set() for each field. This calls set_condition(), and if a condition is set, when save() is called it does an update instead of an insert. So you could try either using set_existing(), or else call set_condition() if you're trying to update an existing user.

If you're adding a new user, then you could try not setting the userid (and it will be assigned the next highest userid).

inmateaid
12-01-2012, 01:11 PM
Adding a new user...

only username, email and password are sent to the datamanager (as shown in the "controller" code above)

kh99
12-01-2012, 01:23 PM
Oops, right, I see now. I also missed that the database error is for the usertextfield table. Did you by any chance delete users by truncating the user table? If so, you also should truncate the usertextfield and userfield tables.

inmateaid
12-01-2012, 01:30 PM
This error occurred upon first use. The only existing record was the main admin and one test user account. The thing is, the record is added in lieu of the error so it seems like it's calling twice unless the call was actually successful and the error was after-the-fact.

I can truncate the tables to reset them if needed, but the initial user insert is where the userid comes from and is what's used as the primary key in the subsequent tables. So I don't see how that could be corrupted

kh99
12-01-2012, 01:37 PM
OK, I tried this code and it worked for me (it inserted a user and there was no db error):

<?php

// vBulletin
define('REGISTERED_USERGROUP', 2); // typical default for registered users
define('PERMANENT_COOKIE', false); // false=session cookies (recommended)
define('THIS_SCRIPT', __FILE__);
define('VB_AREA', 'External');
$dir = getcwd();
chdir('forum4.2.0/');
require_once('./includes/init.php'); // includes class_core.php
require_once('./includes/class_dm.php'); // for class_dm_user.php
require_once('./includes/class_dm_user.php'); // for user functions
require_once('./includes/functions.php'); // vbsetcookie etc.
require_once('./includes/functions_login.php'); // process login/logout
chdir($dir);

class Forum2 {

private $dmuser;

public function __construct()
{
global $vbulletin;
$this->dmuser =& datamanager_init('User', $vbulletin, ERRTYPE_ARRAY);
}

public function register($data = array(), $login = FALSE)
{
global $vbulletin;
foreach ($data as $key => $value) {
if (!is_array($value)) {
$this->dmuser->set($key, $value);
}
}
if (isset($data['options']) && is_array($data['options'])) {
foreach ($data['options'] as $key => $value) {
$this->dmuser->set_bitfield('options', $key, $value);
}
}
$this->dmuser->pre_save();
//print_r($this->dm);
if (count($this->dmuser->errors) > 0) {
return implode('<li>', $this->dmuser->errors);
}
return $this->dmuser->save();
}
}

$f2 = new Forum2();

$f2->register(array(
'username' => 'testing5',
'email' => 'test@test5.com',
'password' => 'password5'
));




other than removing your controller class and changing the directory, the only thing I changed was the part in red, which said "dm" instead of "dmuser".

ETA: I was thinking you might throw this is a php file and try it, to see if the problem is somewhere else.

inmateaid
12-01-2012, 01:53 PM
i renamed some things for the example for clarity, must have missed the one "dm" reference ;) I'll give this a shot in a standalone file as suggested. Guessing if it doesn't work, I'll rebuild the tables. Will post the results soon.

--------------- Added 1354373919 at 1354373919 ---------------

It threw the same error. Going to truncate the tables and reinsert the initial admin record after backing up what's already there. Will see if that helps

--------------- Added 1354374216 at 1354374216 ---------------

Ok, truncated the tables and manually reinserted the inital user, userfield, and usertextfield records and it works without error. I must have deleted a row in phpMyAdmin and thrown off the index at some point.

kh99
12-01-2012, 02:45 PM
So does that solve the problem, or is there still an issue with your original code?

inmateaid
12-01-2012, 03:10 PM
I have to come back to it later today, but the code seems to be fine. I'm going to update my original library now that it's working standalone and will post the status here after that's done. Thanks for mentioning "delete users" as that made me remember doing so when I initially started working on this bridge ;)