2008-08-09 06:53:34 +02:00
|
|
|
<?php
|
2013-05-11 08:05:53 +02:00
|
|
|
|
2016-06-15 06:03:16 +02:00
|
|
|
|
|
|
|
use SilverStripe\ORM\DataObject;
|
|
|
|
use SilverStripe\ORM\FieldType\DBField;
|
|
|
|
|
2015-08-30 07:02:55 +02:00
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
/**
|
2013-05-11 08:05:53 +02:00
|
|
|
* @package framework
|
|
|
|
* @subpackage tests
|
2008-08-09 06:53:34 +02:00
|
|
|
*/
|
|
|
|
class CsvBulkLoaderTest extends SapphireTest {
|
2013-05-11 08:05:53 +02:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
protected static $fixture_file = 'CsvBulkLoaderTest.yml';
|
2008-08-09 06:53:34 +02:00
|
|
|
|
2010-04-12 04:03:16 +02:00
|
|
|
protected $extraDataObjects = array(
|
|
|
|
'CsvBulkLoaderTest_Team',
|
|
|
|
'CsvBulkLoaderTest_Player',
|
|
|
|
'CsvBulkLoaderTest_PlayerContract',
|
|
|
|
);
|
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
/**
|
|
|
|
* Test plain import with column auto-detection
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testLoad() {
|
2009-12-02 10:40:28 +01:00
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
2011-03-30 08:49:11 +02:00
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithHeader.csv';
|
2009-12-02 10:40:28 +01:00
|
|
|
$file = fopen($filepath, 'r');
|
|
|
|
$compareCount = $this->getLineCount($file);
|
|
|
|
fgetcsv($file); // pop header row
|
|
|
|
$compareRow = fgetcsv($file);
|
|
|
|
$results = $loader->load($filepath);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test that right amount of columns was imported
|
|
|
|
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test that columns were correctly imported
|
2013-06-21 00:32:08 +02:00
|
|
|
$obj = DataObject::get_one("CsvBulkLoaderTest_Player", array(
|
|
|
|
'"CsvBulkLoaderTest_Player"."FirstName"' => 'John'
|
|
|
|
));
|
2009-12-02 10:40:28 +01:00
|
|
|
$this->assertNotNull($obj);
|
|
|
|
$this->assertEquals("He's a good guy", $obj->Biography);
|
|
|
|
$this->assertEquals("1988-01-31", $obj->Birthday);
|
|
|
|
$this->assertEquals("1", $obj->IsRegistered);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
fclose($file);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test plain import with clear_table_before_import
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testDeleteExistingRecords() {
|
2014-08-15 08:53:05 +02:00
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithHeader.csv';
|
2009-12-02 10:40:28 +01:00
|
|
|
$loader->deleteExistingRecords = true;
|
|
|
|
$results1 = $loader->load($filepath);
|
2014-08-15 08:53:05 +02:00
|
|
|
$this->assertEquals(4, $results1->Count(), 'Test correct count of imported data on first load');
|
|
|
|
|
|
|
|
//delete existing data before doing second CSV import
|
2012-09-26 23:34:00 +02:00
|
|
|
$results2 = $loader->load($filepath, '512MB', true);
|
|
|
|
//get all instances of the loaded DataObject from the database and count them
|
2014-08-15 08:53:05 +02:00
|
|
|
$resultDataObject = DataObject::get('CsvBulkLoaderTest_Player');
|
|
|
|
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertEquals(4, $resultDataObject->Count(),
|
2014-08-15 08:53:05 +02:00
|
|
|
'Test if existing data is deleted before new data is added');
|
2012-12-08 12:20:20 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
/**
|
|
|
|
* Test import with manual column mapping
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testLoadWithColumnMap() {
|
2009-12-02 10:40:28 +01:00
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
2011-03-30 08:49:11 +02:00
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_Players.csv';
|
2009-12-02 10:40:28 +01:00
|
|
|
$file = fopen($filepath, 'r');
|
|
|
|
$compareCount = $this->getLineCount($file);
|
|
|
|
$compareRow = fgetcsv($file);
|
|
|
|
$loader->columnMap = array(
|
|
|
|
'FirstName',
|
|
|
|
'Biography',
|
|
|
|
null, // ignored column
|
|
|
|
'Birthday',
|
|
|
|
'IsRegistered'
|
|
|
|
);
|
|
|
|
$loader->hasHeaderRow = false;
|
|
|
|
$results = $loader->load($filepath);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test that right amount of columns was imported
|
|
|
|
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test that columns were correctly imported
|
2013-06-21 00:32:08 +02:00
|
|
|
$obj = DataObject::get_one("CsvBulkLoaderTest_Player", array(
|
|
|
|
'"CsvBulkLoaderTest_Player"."FirstName"' => 'John'
|
|
|
|
));
|
2009-12-02 10:40:28 +01:00
|
|
|
$this->assertNotNull($obj);
|
|
|
|
$this->assertEquals("He's a good guy", $obj->Biography);
|
|
|
|
$this->assertEquals("1988-01-31", $obj->Birthday);
|
|
|
|
$this->assertEquals("1", $obj->IsRegistered);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
$obj2 = DataObject::get_one("CsvBulkLoaderTest_Player", array(
|
|
|
|
'"CsvBulkLoaderTest_Player"."FirstName"' => 'Jane'
|
|
|
|
));
|
2009-12-02 10:40:28 +01:00
|
|
|
$this->assertNotNull($obj2);
|
|
|
|
$this->assertEquals('0', $obj2->IsRegistered);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
fclose($file);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
/**
|
|
|
|
* Test import with manual column mapping and custom column names
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testLoadWithCustomHeaderAndRelation() {
|
2009-12-02 10:40:28 +01:00
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
2011-03-30 08:49:11 +02:00
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithCustomHeaderAndRelation.csv';
|
2009-12-02 10:40:28 +01:00
|
|
|
$file = fopen($filepath, 'r');
|
|
|
|
$compareCount = $this->getLineCount($file);
|
|
|
|
fgetcsv($file); // pop header row
|
|
|
|
$compareRow = fgetcsv($file);
|
|
|
|
$loader->columnMap = array(
|
|
|
|
'first name' => 'FirstName',
|
|
|
|
'bio' => 'Biography',
|
|
|
|
'bday' => 'Birthday',
|
|
|
|
'teamtitle' => 'Team.Title', // test existing relation
|
|
|
|
'teamsize' => 'Team.TeamSize', // test existing relation
|
|
|
|
'salary' => 'Contract.Amount' // test relation creation
|
|
|
|
);
|
|
|
|
$loader->hasHeaderRow = true;
|
|
|
|
$loader->relationCallbacks = array(
|
|
|
|
'Team.Title' => array(
|
|
|
|
'relationname' => 'Team',
|
|
|
|
'callback' => 'getTeamByTitle'
|
|
|
|
),
|
|
|
|
// contract should be automatically discovered
|
|
|
|
);
|
|
|
|
$results = $loader->load($filepath);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test that right amount of columns was imported
|
|
|
|
$this->assertEquals(1, $results->Count(), 'Test correct count of imported data');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test of augumenting existing relation (created by fixture)
|
|
|
|
$testTeam = DataObject::get_one('CsvBulkLoaderTest_Team', null, null, '"Created" DESC');
|
|
|
|
$this->assertEquals('20', $testTeam->TeamSize, 'Augumenting existing has_one relation works');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test of creating relation
|
|
|
|
$testContract = DataObject::get_one('CsvBulkLoaderTest_PlayerContract');
|
2013-06-21 00:32:08 +02:00
|
|
|
$testPlayer = DataObject::get_one("CsvBulkLoaderTest_Player", array(
|
|
|
|
'"CsvBulkLoaderTest_Player"."FirstName"' => 'John'
|
|
|
|
));
|
2009-12-02 10:40:28 +01:00
|
|
|
$this->assertEquals($testPlayer->ContractID, $testContract->ID, 'Creating new has_one relation works');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
// Test nested setting of relation properties
|
2012-03-27 06:57:42 +02:00
|
|
|
$contractAmount = DBField::create_field('Currency', $compareRow[5])->RAW();
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertEquals($testPlayer->Contract()->Amount, $contractAmount,
|
|
|
|
'Setting nested values in a relation works');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-12-02 10:40:28 +01:00
|
|
|
fclose($file);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-09 07:00:42 +02:00
|
|
|
/**
|
|
|
|
* Test import with custom identifiers by importing the data.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-08-09 07:00:42 +02:00
|
|
|
* @todo Test duplicateCheck callbacks
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testLoadWithIdentifiers() {
|
2008-08-09 07:00:42 +02:00
|
|
|
// first load
|
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
2011-03-30 08:49:11 +02:00
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithId.csv';
|
2008-08-09 07:00:42 +02:00
|
|
|
$loader->duplicateChecks = array(
|
2013-04-19 05:45:43 +02:00
|
|
|
'ExternalIdentifier' => 'ExternalIdentifier',
|
2013-04-19 05:45:43 +02:00
|
|
|
'NonExistantIdentifier' => 'ExternalIdentifier',
|
2013-04-19 05:45:43 +02:00
|
|
|
'ExternalIdentifier' => 'ExternalIdentifier',
|
2013-04-19 05:45:43 +02:00
|
|
|
'AdditionalIdentifier' => 'ExternalIdentifier'
|
2008-08-09 07:00:42 +02:00
|
|
|
);
|
|
|
|
$results = $loader->load($filepath);
|
2009-10-02 02:07:36 +02:00
|
|
|
$createdPlayers = $results->Created();
|
|
|
|
|
|
|
|
$player = $createdPlayers->First();
|
2008-08-09 07:00:42 +02:00
|
|
|
$this->assertEquals($player->FirstName, 'John');
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertEquals($player->Biography, 'He\'s a good guy',
|
|
|
|
'test updating of duplicate imports within the same import works');
|
2008-08-09 07:00:42 +02:00
|
|
|
|
|
|
|
// load with updated data
|
2012-03-24 04:38:57 +01:00
|
|
|
$filepath = FRAMEWORK_PATH . '/tests/dev/CsvBulkLoaderTest_PlayersWithIdUpdated.csv';
|
2008-08-09 07:00:42 +02:00
|
|
|
$results = $loader->load($filepath);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-10-02 02:07:36 +02:00
|
|
|
// HACK need to update the loaded record from the database
|
|
|
|
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', $player->ID);
|
2008-08-09 07:00:42 +02:00
|
|
|
$this->assertEquals($player->FirstName, 'JohnUpdated', 'Test updating of existing records works');
|
2013-05-11 08:05:53 +02:00
|
|
|
|
|
|
|
// null values are valid imported
|
|
|
|
// $this->assertEquals($player->Biography, 'He\'s a good guy',
|
|
|
|
// 'Test retaining of previous information on duplicate when overwriting with blank field');
|
2008-08-09 07:00:42 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testLoadWithCustomImportMethods() {
|
2008-11-18 02:48:37 +01:00
|
|
|
$loader = new CsvBulkLoaderTest_CustomLoader('CsvBulkLoaderTest_Player');
|
2011-03-30 08:49:11 +02:00
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithHeader.csv';
|
2008-11-18 02:48:37 +01:00
|
|
|
$loader->columnMap = array(
|
|
|
|
'FirstName' => '->importFirstName',
|
2014-08-15 08:53:05 +02:00
|
|
|
'Biography' => 'Biography',
|
2009-02-02 00:49:53 +01:00
|
|
|
'Birthday' => 'Birthday',
|
|
|
|
'IsRegistered' => 'IsRegistered'
|
2008-11-18 02:48:37 +01:00
|
|
|
);
|
|
|
|
$results = $loader->load($filepath);
|
2009-10-02 02:07:36 +02:00
|
|
|
$createdPlayers = $results->Created();
|
|
|
|
$player = $createdPlayers->First();
|
2008-11-18 02:48:37 +01:00
|
|
|
$this->assertEquals($player->FirstName, 'Customized John');
|
|
|
|
$this->assertEquals($player->Biography, "He's a good guy");
|
2009-02-02 00:49:53 +01:00
|
|
|
$this->assertEquals($player->IsRegistered, "1");
|
2008-11-18 02:48:37 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-05-11 08:05:53 +02:00
|
|
|
public function testLoadWithCustomImportMethodDuplicateMap() {
|
|
|
|
$loader = new CsvBulkLoaderTest_CustomLoader('CsvBulkLoaderTest_Player');
|
|
|
|
$filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithHeader.csv';
|
|
|
|
$loader->columnMap = array(
|
|
|
|
'FirstName' => '->updatePlayer',
|
2014-08-15 08:53:05 +02:00
|
|
|
'Biography' => '->updatePlayer',
|
2013-05-11 08:05:53 +02:00
|
|
|
'Birthday' => 'Birthday',
|
|
|
|
'IsRegistered' => 'IsRegistered'
|
|
|
|
);
|
|
|
|
|
|
|
|
$results = $loader->load($filepath);
|
|
|
|
|
|
|
|
$createdPlayers = $results->Created();
|
|
|
|
$player = $createdPlayers->First();
|
|
|
|
|
|
|
|
$this->assertEquals($player->FirstName, "John. He's a good guy. ");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
protected function getLineCount(&$file) {
|
|
|
|
$i = 0;
|
|
|
|
while(fgets($file) !== false) $i++;
|
|
|
|
rewind($file);
|
|
|
|
return $i;
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2015-08-30 15:00:25 +02:00
|
|
|
public function testLargeFileSplitIntoSmallerFiles() {
|
|
|
|
Config::inst()->update('CsvBulkLoader', 'lines', 3);
|
|
|
|
|
|
|
|
$loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
|
|
|
|
$path = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_LargeListOfPlayers.csv';
|
|
|
|
|
|
|
|
$results = $loader->load($path);
|
|
|
|
|
|
|
|
$this->assertEquals(10, $results->Count());
|
|
|
|
}
|
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
}
|
|
|
|
|
2008-11-18 02:48:37 +01:00
|
|
|
class CsvBulkLoaderTest_CustomLoader extends CsvBulkLoader implements TestOnly {
|
2012-09-19 12:07:39 +02:00
|
|
|
public function importFirstName(&$obj, $val, $record) {
|
2008-11-18 02:48:37 +01:00
|
|
|
$obj->FirstName = "Customized {$val}";
|
|
|
|
}
|
2013-05-11 08:05:53 +02:00
|
|
|
|
|
|
|
public function updatePlayer(&$obj, $val, $record) {
|
|
|
|
$obj->FirstName .= $val . '. ';
|
|
|
|
}
|
2008-11-18 02:48:37 +01:00
|
|
|
}
|
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
class CsvBulkLoaderTest_Team extends DataObject implements TestOnly {
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $db = array(
|
2008-08-09 06:53:34 +02:00
|
|
|
'Title' => 'Varchar(255)',
|
|
|
|
'TeamSize' => 'Int',
|
2014-08-15 08:53:05 +02:00
|
|
|
);
|
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $has_many = array(
|
2008-08-09 06:53:34 +02:00
|
|
|
'Players' => 'CsvBulkLoaderTest_Player',
|
|
|
|
);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class CsvBulkLoaderTest_Player extends DataObject implements TestOnly {
|
2013-05-11 08:05:53 +02:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $db = array(
|
2008-08-09 06:53:34 +02:00
|
|
|
'FirstName' => 'Varchar(255)',
|
|
|
|
'Biography' => 'HTMLText',
|
|
|
|
'Birthday' => 'Date',
|
2008-08-09 07:00:42 +02:00
|
|
|
'ExternalIdentifier' => 'Varchar(255)', // used for uniqueness checks on passed property
|
2009-02-02 00:49:53 +01:00
|
|
|
'IsRegistered' => 'Boolean'
|
2008-08-09 06:53:34 +02:00
|
|
|
);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $has_one = array(
|
2008-08-09 06:53:34 +02:00
|
|
|
'Team' => 'CsvBulkLoaderTest_Team',
|
|
|
|
'Contract' => 'CsvBulkLoaderTest_PlayerContract'
|
|
|
|
);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
public function getTeamByTitle($title) {
|
2013-06-21 00:32:08 +02:00
|
|
|
return DataObject::get_one("CsvBulkLoaderTest_Team", array(
|
|
|
|
'"CsvBulkLoaderTest_Team"."Title"' => $title
|
|
|
|
));
|
2008-08-09 06:53:34 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
/**
|
|
|
|
* Custom setter for "Birthday" property when passed/imported
|
|
|
|
* in different format.
|
|
|
|
*
|
|
|
|
* @param string $val
|
|
|
|
* @param array $record
|
|
|
|
*/
|
2008-11-18 02:48:37 +01:00
|
|
|
public function setUSBirthday($val, $record = null) {
|
2008-08-09 06:53:34 +02:00
|
|
|
$this->Birthday = preg_replace('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-90-9]{2,4})/', '\\3-\\1-\\2', $val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-11 08:05:53 +02:00
|
|
|
|
2008-08-09 06:53:34 +02:00
|
|
|
class CsvBulkLoaderTest_PlayerContract extends DataObject implements TestOnly {
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $db = array(
|
2008-08-09 06:53:34 +02:00
|
|
|
'Amount' => 'Currency',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-02-12 21:22:11 +01:00
|
|
|
|