public function processRecord($record, $columnMap, &$results, $preview = false)
 {
     $objID = parent::processRecord($record, $columnMap, $results, $preview);
     $_cache_groupByCode = array();
     // Add to predefined groups
     /** @var Member $member */
     $member = DataObject::get_by_id($this->objectClass, $objID);
     foreach ($this->groups as $group) {
         // TODO This isnt the most memory effective way to add members to a group
         $member->Groups()->add($group);
     }
     // Add to groups defined in CSV
     if (isset($record['Groups']) && $record['Groups']) {
         $groupCodes = explode(',', $record['Groups']);
         foreach ($groupCodes as $groupCode) {
             $groupCode = Convert::raw2url($groupCode);
             if (!isset($_cache_groupByCode[$groupCode])) {
                 $group = Group::get()->filter('Code', $groupCode)->first();
                 if (!$group) {
                     $group = new Group();
                     $group->Code = $groupCode;
                     $group->Title = $groupCode;
                     $group->write();
                 }
                 $member->Groups()->add($group);
                 $_cache_groupByCode[$groupCode] = $group;
             }
         }
     }
     $member->destroy();
     unset($member);
     return $objID;
 }
 public function processRecord($record, $columnMap, &$results, $preview = false)
 {
     // We match by 'Code', the ID property is confusing the importer
     if (isset($record['ID'])) {
         unset($record['ID']);
     }
     $objID = parent::processRecord($record, $columnMap, $results, $preview);
     $group = DataObject::get_by_id($this->objectClass, $objID);
     // set group hierarchies - we need to do this after all records
     // are imported to avoid missing "early" references to parents
     // which are imported later on in the CSV file.
     if (isset($record['ParentCode']) && $record['ParentCode']) {
         $parentGroup = DataObject::get_one('SilverStripe\\Security\\Group', array('"Group"."Code"' => $record['ParentCode']));
         if ($parentGroup) {
             $group->ParentID = $parentGroup->ID;
             $group->write();
         }
     }
     // set permission codes - these are all additive, meaning
     // existing permissions arent cleared.
     if (isset($record['PermissionCodes']) && $record['PermissionCodes']) {
         foreach (explode(',', $record['PermissionCodes']) as $code) {
             $p = DataObject::get_one('SilverStripe\\Security\\Permission', array('"Permission"."Code"' => $code, '"Permission"."GroupID"' => $group->ID));
             if (!$p) {
                 $p = new Permission(array('Code' => $code));
                 $p->write();
             }
             $group->Permissions()->add($p);
         }
     }
     return $objID;
 }
 /**
  * Adds the item to this relation.
  *
  * It does so by setting the relationFilters.
  *
  * @param DataObject|int $item The DataObject to be added, or its ID
  */
 public function add($item)
 {
     if (is_numeric($item)) {
         $item = DataObject::get_by_id($this->dataClass, $item);
     } else {
         if (!$item instanceof $this->dataClass) {
             user_error("PolymorphicHasManyList::add() expecting a {$this->dataClass} object, or ID value", E_USER_ERROR);
         }
     }
     $foreignID = $this->getForeignID();
     // Validate foreignID
     if (!$foreignID) {
         user_error("PolymorphicHasManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
         return;
     }
     if (is_array($foreignID)) {
         user_error("PolymorphicHasManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING);
         return;
     }
     $foreignKey = $this->foreignKey;
     $classForeignKey = $this->classForeignKey;
     $item->{$foreignKey} = $foreignID;
     $item->{$classForeignKey} = $this->getForeignClass();
     $item->write();
 }
 public function getValue()
 {
     $id = $this->getIDValue();
     $class = $this->getClassValue();
     if ($id && $class && is_subclass_of($class, 'SilverStripe\\ORM\\DataObject')) {
         return DataObject::get_by_id($class, $id);
     }
     return null;
 }
 public function testSQLInsert()
 {
     $factory = new FixtureFactory();
     $relPath = ltrim(FRAMEWORK_DIR . '/tests/testing/YamlFixtureTest.yml', '/');
     $fixture = Injector::inst()->create('SilverStripe\\Dev\\YamlFixture', $relPath);
     $fixture->writeInto($factory);
     $this->assertGreaterThan(0, $factory->getId("YamlFixtureTest_DataObject", "testobject1"));
     $object1 = DataObject::get_by_id("YamlFixtureTest_DataObject", $factory->getId("YamlFixtureTest_DataObject", "testobject1"));
     $this->assertTrue($object1->ManyManyRelation()->Count() == 2, "Should be two items in this relationship");
     $this->assertGreaterThan(0, $factory->getId("YamlFixtureTest_DataObject", "testobject2"));
     $object2 = DataObject::get_by_id("YamlFixtureTest_DataObject", $factory->getId("YamlFixtureTest_DataObject", "testobject2"));
     $this->assertTrue($object2->ManyManyRelation()->Count() == 1, "Should be one item in this relationship");
 }
 public function testCleartextPasswordsAreHashedWithDefaultAlgo()
 {
     $loader = new MemberCsvBulkLoader();
     $results = $loader->load($this->getCurrentRelativePath() . '/MemberCsvBulkLoaderTest_cleartextpws.csv');
     $member = $results->Created()->First();
     $memberID = $member->ID;
     DataObject::flush_and_destroy_cache();
     $member = DataObject::get_by_id('SilverStripe\\Security\\Member', $memberID);
     // TODO Direct getter doesn't work, wtf!
     $this->assertEquals(Security::config()->password_encryption_algorithm, $member->getField('PasswordEncryption'));
     $result = $member->checkPassword('mypassword');
     $this->assertTrue($result->valid());
 }
 public function testRun()
 {
     $m = new Member();
     $m->Password = '******';
     $m->PasswordEncryption = 'none';
     $m->write();
     $t = new EncryptAllPasswordsTask();
     $t->run(null);
     $m = DataObject::get_by_id('SilverStripe\\Security\\Member', $m->ID);
     $this->assertEquals($m->PasswordEncryption, 'blowfish');
     $this->assertNotEquals($m->Password, 'plain');
     $result = $m->checkPassword('plain');
     $this->assertTrue($result->valid());
 }
 public function testNoLegacyPasswordHashMigrationOnIncompatibleAlgorithm()
 {
     Config::inst()->update('SilverStripe\\Security\\PasswordEncryptor', 'encryptors', array('crc32' => array('SilverStripe\\Security\\PasswordEncryptor_PHPHash' => 'crc32')));
     $field = Member::config()->unique_identifier_field;
     $member = new Member();
     $member->{$field} = '*****@*****.**';
     $member->PasswordEncryption = "crc32";
     $member->Password = "******";
     $member->write();
     $data = array('Email' => $member->{$field}, 'Password' => 'mypassword');
     MemberAuthenticator::authenticate($data);
     $member = DataObject::get_by_id('SilverStripe\\Security\\Member', $member->ID);
     $this->assertEquals($member->PasswordEncryption, "crc32");
     $result = $member->checkPassword('mypassword');
     $this->assertTrue($result->valid());
 }
 public function testDuplicateManyManyClasses()
 {
     //create new test classes below
     $one = new DataObjectDuplicateTestClass1();
     $two = new DataObjectDuplicateTestClass2();
     $three = new DataObjectDuplicateTestClass3();
     //set some simple fields
     $text1 = "Test Text 1";
     $text2 = "Test Text 2";
     $text3 = "Test Text 3";
     $one->text = $text1;
     $two->text = $text2;
     $three->text = $text3;
     //write the to DB
     $one->write();
     $two->write();
     $three->write();
     //create relations
     $one->twos()->add($two);
     $one->threes()->add($three);
     $one = DataObject::get_by_id("DataObjectDuplicateTestClass1", $one->ID);
     $two = DataObject::get_by_id("DataObjectDuplicateTestClass2", $two->ID);
     $three = DataObject::get_by_id("DataObjectDuplicateTestClass3", $three->ID);
     //test duplication
     $oneCopy = $one->duplicate();
     $twoCopy = $two->duplicate();
     $threeCopy = $three->duplicate();
     $oneCopy = DataObject::get_by_id("DataObjectDuplicateTestClass1", $oneCopy->ID);
     $twoCopy = DataObject::get_by_id("DataObjectDuplicateTestClass2", $twoCopy->ID);
     $threeCopy = DataObject::get_by_id("DataObjectDuplicateTestClass3", $threeCopy->ID);
     $this->assertNotNull($oneCopy, "Copy of 1 exists");
     $this->assertNotNull($twoCopy, "Copy of 2 exists");
     $this->assertNotNull($threeCopy, "Copy of 3 exists");
     $this->assertEquals($text1, $oneCopy->text);
     $this->assertEquals($text2, $twoCopy->text);
     $this->assertEquals($text3, $threeCopy->text);
     $this->assertNotEquals($one->twos()->Count(), $oneCopy->twos()->Count(), "Many-to-one relation not copied (has_many)");
     $this->assertEquals($one->threes()->Count(), $oneCopy->threes()->Count(), "Object has the correct number of relations");
     $this->assertEquals($three->ones()->Count(), $threeCopy->ones()->Count(), "Object has the correct number of relations");
     $this->assertEquals($one->ID, $twoCopy->one()->ID, "Match between relation of copy and the original");
     $this->assertEquals(0, $oneCopy->twos()->Count(), "Many-to-one relation not copied (has_many)");
     $this->assertEquals($three->ID, $oneCopy->threes()->First()->ID, "Match between relation of copy and the original");
     $this->assertEquals($one->ID, $threeCopy->ones()->First()->ID, "Match between relation of copy and the original");
 }
 /**
  * Return this field's linked items
  */
 public function getItems()
 {
     // If the value has been set, use that
     if ($this->value != 'unchanged' && is_array($this->sourceObject)) {
         $items = array();
         $values = is_array($this->value) ? $this->value : preg_split('/ *, */', trim($this->value));
         foreach ($values as $value) {
             $item = new stdClass();
             $item->ID = $value;
             $item->Title = $this->sourceObject[$value];
             $items[] = $item;
         }
         return $items;
         // Otherwise, look data up from the linked relation
     }
     if ($this->value != 'unchanged' && is_string($this->value)) {
         $items = new ArrayList();
         $ids = explode(',', $this->value);
         foreach ($ids as $id) {
             if (!is_numeric($id)) {
                 continue;
             }
             $item = DataObject::get_by_id($this->sourceObject, $id);
             if ($item) {
                 $items->push($item);
             }
         }
         return $items;
     } else {
         if ($this->form) {
             $fieldName = $this->name;
             $record = $this->form->getRecord();
             if (is_object($record) && $record->hasMethod($fieldName)) {
                 return $record->{$fieldName}();
             }
         }
     }
 }
 public function getHTMLFragments($gridField)
 {
     $modelClass = $gridField->getModelClass();
     $parentID = 0;
     if ($this->currentID) {
         $modelObj = DataObject::get_by_id($modelClass, $this->currentID);
         if ($modelObj->hasMethod('getParent')) {
             $parent = $modelObj->getParent();
         } elseif ($modelObj->ParentID) {
             $parent = $modelObj->Parent();
         }
         if ($parent) {
             $parentID = $parent->ID;
         }
         // Attributes
         $attrs = array_merge($this->attributes, array('href' => sprintf($this->linkSpec, $parentID), 'class' => 'cms-panel-link ss-ui-button font-icon-level-up no-text grid-levelup'));
         $attrsStr = '';
         foreach ($attrs as $k => $v) {
             $attrsStr .= " {$k}=\"" . Convert::raw2att($v) . "\"";
         }
         $forTemplate = new ArrayData(array('UpLink' => DBField::create_field('HTMLFragment', sprintf('<a%s></a>', $attrsStr))));
         return array('before' => $forTemplate->renderWith('Includes/GridFieldLevelup'));
     }
 }
 public function getHTMLFragments($gridField)
 {
     $modelClass = $gridField->getModelClass();
     $parentID = 0;
     if (!$this->currentID) {
         return null;
     }
     $modelObj = DataObject::get_by_id($modelClass, $this->currentID);
     $parent = null;
     if ($modelObj->hasMethod('getParent')) {
         $parent = $modelObj->getParent();
     } elseif ($modelObj->ParentID) {
         $parent = $modelObj->Parent();
     }
     if ($parent) {
         $parentID = $parent->ID;
     }
     // Attributes
     $attrs = array_merge($this->attributes, array('href' => sprintf($this->linkSpec, $parentID), 'class' => 'cms-panel-link ss-ui-button font-icon-level-up no-text grid-levelup'));
     $linkTag = FormField::create_tag('a', $attrs);
     $forTemplate = new ArrayData(array('UpLink' => DBField::create_field('HTMLFragment', $linkTag)));
     $template = SSViewer::get_templates_by_class($this, '', __CLASS__);
     return array('before' => $forTemplate->renderWith($template));
 }
 /**
  * Delete the record with the given ID.
  *
  * @param string $className The class name of the record to be deleted
  * @param int $id ID of record to be deleted
  */
 public static function delete_by_id($className, $id)
 {
     $obj = DataObject::get_by_id($className, $id);
     if ($obj) {
         $obj->delete();
     } else {
         user_error("{$className} object #{$id} wasn't found when calling DataObject::delete_by_id", E_USER_WARNING);
     }
 }
예제 #14
0
 /**
  * Check if the member is in the given group or any parent groups.
  *
  * @param int|Group|string $group Group instance, Group Code or ID
  * @param boolean $strict Only determine direct group membership if set to TRUE (Default: FALSE)
  * @return bool Returns TRUE if the member is in the given group, otherwise FALSE.
  */
 public function inGroup($group, $strict = false)
 {
     if (is_numeric($group)) {
         $groupCheckObj = DataObject::get_by_id('SilverStripe\\Security\\Group', $group);
     } elseif (is_string($group)) {
         $groupCheckObj = DataObject::get_one('SilverStripe\\Security\\Group', array('"Group"."Code"' => $group));
     } elseif ($group instanceof Group) {
         $groupCheckObj = $group;
     } else {
         user_error('Member::inGroup(): Wrong format for $group parameter', E_USER_ERROR);
     }
     if (!$groupCheckObj) {
         return false;
     }
     $groupCandidateObjs = $strict ? $this->getManyManyComponents("Groups") : $this->Groups();
     if ($groupCandidateObjs) {
         foreach ($groupCandidateObjs as $groupCandidateObj) {
             if ($groupCandidateObj->ID == $groupCheckObj->ID) {
                 return true;
             }
         }
     }
     return false;
 }
 public function testFormatFromSettings()
 {
     $memberID = $this->logInWithPermission();
     $member = DataObject::get_by_id('SilverStripe\\Security\\Member', $memberID);
     $member->DateFormat = 'dd/MM/YYYY';
     $member->write();
     $fixtures = array('2000-12-31' => '31/12/2000', '31-12-2000' => '31/12/2000', '31/12/2000' => '31/12/2000', '2014-04-01' => '01/04/2014');
     foreach ($fixtures as $from => $to) {
         $date = DBField::create_field('Date', $from);
         // With member
         $this->assertEquals($to, $date->FormatFromSettings($member));
         // Without member
         $this->assertEquals($to, $date->FormatFromSettings());
     }
 }
 protected function extractValue($item, $key)
 {
     if (is_numeric($item)) {
         $item = DataObject::get_by_id($this->dataClass, $item);
     }
     return parent::extractValue($item, $key);
 }
 public function testSaveTreeNodeParentID()
 {
     $this->loginWithPermission('ADMIN');
     $page1 = $this->objFromFixture('LeftAndMainTest_Object', 'page1');
     $page2 = $this->objFromFixture('LeftAndMainTest_Object', 'page2');
     $page3 = $this->objFromFixture('LeftAndMainTest_Object', 'page3');
     $page31 = $this->objFromFixture('LeftAndMainTest_Object', 'page31');
     $page32 = $this->objFromFixture('LeftAndMainTest_Object', 'page32');
     // Move page2 into page3, between page3.1 and page 3.2
     $siblingIDs = array($page31->ID, $page2->ID, $page32->ID);
     $data = array('SiblingIDs' => $siblingIDs, 'ID' => $page2->ID, 'ParentID' => $page3->ID);
     $response = $this->post('LeftAndMainTest_Controller/savetreenode', $data);
     $this->assertEquals(200, $response->getStatusCode());
     $page2 = DataObject::get_by_id('LeftAndMainTest_Object', $page2->ID, false);
     $page31 = DataObject::get_by_id('LeftAndMainTest_Object', $page31->ID, false);
     $page32 = DataObject::get_by_id('LeftAndMainTest_Object', $page32->ID, false);
     $this->assertEquals($page3->ID, $page2->ParentID, 'Moved page gets new parent');
     $this->assertEquals(1, $page31->Sort, 'Children pages before insertaion are unaffected');
     $this->assertEquals(2, $page2->Sort, 'Moved page is correctly sorted');
     $this->assertEquals(3, $page32->Sort, 'Children pages after insertion are resorted');
 }
 /**
  * Get an object from the fixture.
  *
  * @param $class The data class, as specified in your fixture file.  Parent classes won't work
  * @param $identifier The identifier string, as provided in your fixture file
  */
 public function get($class, $identifier)
 {
     $id = $this->getId($class, $identifier);
     if ($id) {
         return DataObject::get_by_id($class, $id);
     }
 }
 /**
  * Find local File dataobject given ID
  *
  * @param int $id
  * @return array
  */
 protected function viewfile_getLocalFileByID($id)
 {
     /** @var File $file */
     $file = DataObject::get_by_id('File', $id);
     if ($file && $file->canView()) {
         return array($file, $file->getURL());
     }
     return [null, null];
 }
예제 #20
0
 /**
  * Get foreign member record for this relation
  *
  * @return Member
  */
 protected function getMember()
 {
     $id = $this->getForeignID();
     if ($id) {
         return DataObject::get_by_id('SilverStripe\\Security\\Member', $id);
     }
 }
 /**
  * Helper method for processing batch actions.
  * Returns a set of status-updating JavaScript to return to the CMS.
  *
  * @param SS_List $objs The SS_List of objects to perform this batch action
  * on.
  * @param string $helperMethod The method to call on each of those objects.
  * @param string $successMessage
  * @param array $arguments
  * @return string JSON encoded map in the following format:
  *  {
  *     'modified': {
  *       3: {'TreeTitle': 'Page3'},
  *       5: {'TreeTitle': 'Page5'}
  *     },
  *     'deleted': {
  *       // all deleted pages
  *     }
  *  }
  */
 public function batchaction(SS_List $objs, $helperMethod, $successMessage, $arguments = array())
 {
     $status = array('modified' => array(), 'error' => array(), 'deleted' => array(), 'success' => array());
     foreach ($objs as $obj) {
         // Perform the action
         $id = $obj->ID;
         if (!call_user_func_array(array($obj, $helperMethod), $arguments)) {
             $status['error'][$id] = $id;
         } else {
             $status['success'][$id] = $id;
         }
         // Now make sure the tree title is appropriately updated
         $publishedRecord = DataObject::get_by_id($this->managedClass, $id);
         if ($publishedRecord) {
             $status['modified'][$id] = array('TreeTitle' => $publishedRecord->TreeTitle);
         } else {
             $status['deleted'][$id] = $id;
         }
         $obj->destroy();
         unset($obj);
     }
     return $this->response($successMessage, $status);
 }
 /**
  * Test that UploadField:overwriteWarning cannot overwrite Upload:replaceFile
  */
 public function testConfigOverwriteWarningCannotRelaceFiles()
 {
     Upload::config()->replaceFile = false;
     UploadField::config()->defaultConfig = array_merge(UploadField::config()->defaultConfig, array('overwriteWarning' => true));
     $tmpFileName = 'testUploadBasic.txt';
     $response = $this->mockFileUpload('NoRelationField', $tmpFileName);
     $this->assertFalse($response->isError());
     $responseData = Convert::json2array($response->getBody());
     $uploadedFile = DataObject::get_by_id('SilverStripe\\Assets\\File', (int) $responseData[0]['id']);
     $this->assertTrue(is_object($uploadedFile), 'The file object is created');
     $this->assertFileExists(AssetStoreTest_SpyStore::getLocalPath($uploadedFile));
     $tmpFileName = 'testUploadBasic.txt';
     $response = $this->mockFileUpload('NoRelationField', $tmpFileName);
     $this->assertFalse($response->isError());
     $responseData = Convert::json2array($response->getBody());
     $uploadedFile2 = DataObject::get_by_id('SilverStripe\\Assets\\File', (int) $responseData[0]['id']);
     $this->assertTrue(is_object($uploadedFile2), 'The file object is created');
     $this->assertFileExists(AssetStoreTest_SpyStore::getLocalPath($uploadedFile2));
     $this->assertTrue($uploadedFile->Filename !== $uploadedFile2->Filename, 'Filename is not the same');
     $this->assertTrue($uploadedFile->ID !== $uploadedFile2->ID, 'File database record is not the same');
 }
 public function testAlternatingRepeatedLoginAttempts()
 {
     Member::config()->lock_out_after_incorrect_logins = 3;
     // ATTEMPTING LOG-IN TWICE WITH ONE ACCOUNT AND TWICE WITH ANOTHER SHOULDN'T LOCK ANYBODY OUT
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $member1 = DataObject::get_by_id("SilverStripe\\Security\\Member", $this->idFromFixture('SilverStripe\\Security\\Member', 'test'));
     $member2 = DataObject::get_by_id("SilverStripe\\Security\\Member", $this->idFromFixture('SilverStripe\\Security\\Member', 'noexpiry'));
     $this->assertNull($member1->LockedOutUntil);
     $this->assertNull($member2->LockedOutUntil);
     // BUT, DOING AN ADDITIONAL LOG-IN WITH EITHER OF THEM WILL LOCK OUT, SINCE THAT IS THE 3RD FAILURE IN
     // THIS SESSION
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $member1 = DataObject::get_by_id("SilverStripe\\Security\\Member", $this->idFromFixture('SilverStripe\\Security\\Member', 'test'));
     $this->assertNotNull($member1->LockedOutUntil);
     $this->doTestLoginForm('*****@*****.**', 'incorrectpassword');
     $member2 = DataObject::get_by_id("SilverStripe\\Security\\Member", $this->idFromFixture('SilverStripe\\Security\\Member', 'noexpiry'));
     $this->assertNotNull($member2->LockedOutUntil);
 }
 /**
  * If an object ID is set, add the object to the list
  *
  * @param GridField $gridField
  * @param SS_List $dataList
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     $objectID = $gridField->State->GridFieldAddRelation(null);
     if (empty($objectID)) {
         return $dataList;
     }
     $object = DataObject::get_by_id($gridField->getModelClass(), $objectID);
     if ($object) {
         $dataList->add($object);
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
 /**
  * Get the list of groups that the given member belongs to.
  *
  * Call without an argument to get the groups that the current member
  * belongs to. In this case, the results will be session-cached.
  *
  * @param int $memberID The ID of the member. Leave blank for the current
  *                      member.
  * @return array Returns a list of group IDs to which the member belongs
  *               to or NULL.
  */
 public static function groupList($memberID = null)
 {
     // Default to current member, with session-caching
     if (!$memberID) {
         $member = Member::currentUser();
         if ($member && isset($_SESSION['Permission_groupList'][$member->ID])) {
             return $_SESSION['Permission_groupList'][$member->ID];
         }
     } else {
         $member = DataObject::get_by_id("SilverStripe\\Security\\Member", $memberID);
     }
     if ($member) {
         // Build a list of the IDs of the groups.  Most of the heavy lifting
         // is done by Member::Groups
         // NOTE: This isn't effecient; but it's called once per session so
         // it's a low priority to fix.
         $groups = $member->Groups();
         $groupList = array();
         if ($groups) {
             foreach ($groups as $group) {
                 $groupList[] = $group->ID;
             }
         }
         // Session caching
         if (!$memberID) {
             $_SESSION['Permission_groupList'][$member->ID] = $groupList;
         }
         return isset($groupList) ? $groupList : null;
     }
 }
 /**
  * Write a Money object to the database, then re-read it to ensure it
  * is re-read properly.
  */
 public function testGettingWrittenDataObject()
 {
     $local = i18n::get_locale();
     //make sure that the $ amount is not prefixed by US$, as it would be in non-US locale
     i18n::set_locale('en_US');
     $obj = new MoneyTest_DataObject();
     $m = new DBMoney();
     $m->setAmount(987.65);
     $m->setCurrency('USD');
     $obj->MyMoney = $m;
     $this->assertEquals("\$987.65", $obj->MyMoney->Nice(), "Money field not added to data object properly when read prior to first writing the record.");
     $objID = $obj->write();
     $moneyTest = DataObject::get_by_id('MoneyTest_DataObject', $objID);
     $this->assertTrue($moneyTest instanceof MoneyTest_DataObject);
     $this->assertEquals('USD', $moneyTest->MyMoneyCurrency);
     $this->assertEquals(987.65, $moneyTest->MyMoneyAmount);
     $this->assertEquals("\$987.65", $moneyTest->MyMoney->Nice(), "Money field not added to data object properly when read.");
     i18n::set_locale($local);
 }
 /**
  * Test import with custom identifiers by importing the data.
  *
  * @todo Test duplicateCheck callbacks
  */
 public function testLoadWithIdentifiers()
 {
     // first load
     $loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
     $filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithId.csv';
     $loader->duplicateChecks = array('ExternalIdentifier' => 'ExternalIdentifier', 'NonExistantIdentifier' => 'ExternalIdentifier', 'ExternalIdentifier' => 'ExternalIdentifier', 'AdditionalIdentifier' => 'ExternalIdentifier');
     $results = $loader->load($filepath);
     $createdPlayers = $results->Created();
     $player = $createdPlayers->First();
     $this->assertEquals($player->FirstName, 'John');
     $this->assertEquals($player->Biography, 'He\'s a good guy', 'test updating of duplicate imports within the same import works');
     // load with updated data
     $filepath = FRAMEWORK_PATH . '/tests/dev/CsvBulkLoaderTest_PlayersWithIdUpdated.csv';
     $results = $loader->load($filepath);
     // HACK need to update the loaded record from the database
     $player = DataObject::get_by_id('CsvBulkLoaderTest_Player', $player->ID);
     $this->assertEquals($player->FirstName, 'JohnUpdated', 'Test updating of existing records works');
     // 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');
 }
 /**
  * @return File
  */
 public function getItem()
 {
     return DataObject::get_by_id('SilverStripe\\Assets\\File', $this->itemID);
 }
 /**
  * Update the position and parent of a tree node.
  * Only saves the node if changes were made.
  *
  * Required data:
  * - 'ID': The moved node
  * - 'ParentID': New parent relation of the moved node (0 for root)
  * - 'SiblingIDs': Array of all sibling nodes to the moved node (incl. the node itself).
  *   In case of a 'ParentID' change, relates to the new siblings under the new parent.
  *
  * @param HTTPRequest $request
  * @return HTTPResponse JSON string with a
  * @throws HTTPResponse_Exception
  */
 public function savetreenode($request)
 {
     if (!SecurityToken::inst()->checkRequest($request)) {
         return $this->httpError(400);
     }
     if (!Permission::check('SITETREE_REORGANISE') && !Permission::check('ADMIN')) {
         $this->getResponse()->setStatusCode(403, _t('LeftAndMain.CANT_REORGANISE', "You do not have permission to rearange the site tree. Your change was not saved."));
         return;
     }
     $className = $this->stat('tree_class');
     $statusUpdates = array('modified' => array());
     $id = $request->requestVar('ID');
     $parentID = $request->requestVar('ParentID');
     if ($className == 'SilverStripe\\CMS\\Model\\SiteTree' && ($page = DataObject::get_by_id('Page', $id))) {
         $root = $page->getParentType();
         if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
             $this->getResponse()->setStatusCode(403, _t('LeftAndMain.CANT_REORGANISE', "You do not have permission to alter Top level pages. Your change was not saved."));
             return;
         }
     }
     $siblingIDs = $request->requestVar('SiblingIDs');
     $statusUpdates = array('modified' => array());
     if (!is_numeric($id) || !is_numeric($parentID)) {
         throw new InvalidArgumentException();
     }
     $node = DataObject::get_by_id($className, $id);
     if ($node && !$node->canEdit()) {
         return Security::permissionFailure($this);
     }
     if (!$node) {
         $this->getResponse()->setStatusCode(500, _t('LeftAndMain.PLEASESAVE', "Please Save Page: This page could not be updated because it hasn't been saved yet."));
         return;
     }
     // Update hierarchy (only if ParentID changed)
     if ($node->ParentID != $parentID) {
         $node->ParentID = (int) $parentID;
         $node->write();
         $statusUpdates['modified'][$node->ID] = array('TreeTitle' => $node->TreeTitle);
         // Update all dependent pages
         if (class_exists('SilverStripe\\CMS\\Model\\VirtualPage')) {
             $virtualPages = VirtualPage::get()->filter("CopyContentFromID", $node->ID);
             foreach ($virtualPages as $virtualPage) {
                 $statusUpdates['modified'][$virtualPage->ID] = array('TreeTitle' => $virtualPage->TreeTitle());
             }
         }
         $this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.')));
     }
     // Update sorting
     if (is_array($siblingIDs)) {
         $counter = 0;
         foreach ($siblingIDs as $id) {
             if ($id == $node->ID) {
                 $node->Sort = ++$counter;
                 $node->write();
                 $statusUpdates['modified'][$node->ID] = array('TreeTitle' => $node->TreeTitle);
             } else {
                 if (is_numeric($id)) {
                     // Nodes that weren't "actually moved" shouldn't be registered as
                     // having been edited; do a direct SQL update instead
                     ++$counter;
                     DB::prepared_query("UPDATE \"{$className}\" SET \"Sort\" = ? WHERE \"ID\" = ?", array($counter, $id));
                 }
             }
         }
         $this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.REORGANISATIONSUCCESSFUL', 'Reorganised the site tree successfully.')));
     }
     return Convert::raw2json($statusUpdates);
 }
 /**
  * Get the whole tree of a part of the tree via an AJAX request.
  *
  * @param HTTPRequest $request
  * @return string
  * @throws Exception
  */
 public function tree(HTTPRequest $request)
 {
     // Array sourceObject is an explicit list of values - construct a "flat tree"
     if (is_array($this->sourceObject)) {
         $output = "<ul class=\"tree\">\n";
         foreach ($this->sourceObject as $k => $v) {
             $output .= '<li id="selector-' . $this->name . '-' . $k . '"><a>' . $v . '</a>';
         }
         $output .= "</ul>";
         return $output;
     }
     // Regular source specification
     $isSubTree = false;
     $this->search = $request->requestVar('search');
     $id = is_numeric($request->latestParam('ID')) ? (int) $request->latestParam('ID') : (int) $request->requestVar('ID');
     /** @var DataObject|Hierarchy $obj */
     $obj = null;
     if ($id && !$request->requestVar('forceFullTree')) {
         $obj = DataObject::get_by_id($this->sourceObject, $id);
         $isSubTree = true;
         if (!$obj) {
             throw new Exception("TreeDropdownField->tree(): the object #{$id} of type {$this->sourceObject} could not be found");
         }
     } else {
         if ($this->baseID) {
             $obj = DataObject::get_by_id($this->sourceObject, $this->baseID);
         }
         if (!$this->baseID || !$obj) {
             $obj = DataObject::singleton($this->sourceObject);
         }
     }
     // pre-process the tree - search needs to operate globally, not locally as marking filter does
     if ($this->search) {
         $this->populateIDs();
     }
     if ($this->filterCallback || $this->search) {
         $obj->setMarkingFilterFunction(array($this, "filterMarking"));
     }
     $obj->markPartialTree($nodeCountThreshold = 30, $context = null, $this->childrenMethod, $this->numChildrenMethod);
     // allow to pass values to be selected within the ajax request
     if (isset($_REQUEST['forceValue']) || $this->value) {
         $forceValue = isset($_REQUEST['forceValue']) ? $_REQUEST['forceValue'] : $this->value;
         $values = preg_split('/,\\s*/', $forceValue);
         if ($values) {
             foreach ($values as $value) {
                 if (!$value || $value == 'unchanged') {
                     continue;
                 }
                 $obj->markToExpose($this->objectForKey($value));
             }
         }
     }
     $self = $this;
     $titleFn = function (&$child) use(&$self) {
         /** @var DataObject|Hierarchy $child */
         $keyField = $self->keyField;
         $labelField = $self->labelField;
         return sprintf('<li id="selector-%s-%s" data-id="%s" class="class-%s %s %s"><a rel="%d">%s</a>', Convert::raw2xml($self->getName()), Convert::raw2xml($child->{$keyField}), Convert::raw2xml($child->{$keyField}), Convert::raw2xml($child->class), Convert::raw2xml($child->markingClasses($self->numChildrenMethod)), $self->nodeIsDisabled($child) ? 'disabled' : '', (int) $child->ID, $child->obj($labelField)->forTemplate());
     };
     // Limit the amount of nodes shown for performance reasons.
     // Skip the check if we're filtering the tree, since its not clear how many children will
     // match the filter criteria until they're queried (and matched up with previously marked nodes).
     $nodeThresholdLeaf = Config::inst()->get('SilverStripe\\ORM\\Hierarchy\\Hierarchy', 'node_threshold_leaf');
     if ($nodeThresholdLeaf && !$this->filterCallback && !$this->search) {
         $className = $this->sourceObject;
         $nodeCountCallback = function ($parent, $numChildren) use($className, $nodeThresholdLeaf) {
             if ($className === 'SilverStripe\\CMS\\Model\\SiteTree' && $parent->ID && $numChildren > $nodeThresholdLeaf) {
                 return sprintf('<ul><li><span class="item">%s</span></li></ul>', _t('LeftAndMain.TooManyPages', 'Too many pages'));
             }
             return null;
         };
     } else {
         $nodeCountCallback = null;
     }
     if ($isSubTree) {
         $html = $obj->getChildrenAsUL("", $titleFn, null, true, $this->childrenMethod, $this->numChildrenMethod, true, null, $nodeCountCallback);
         return substr(trim($html), 4, -5);
     } else {
         $html = $obj->getChildrenAsUL('class="tree"', $titleFn, null, true, $this->childrenMethod, $this->numChildrenMethod, true, null, $nodeCountCallback);
         return $html;
     }
 }