public function Form()
 {
     $player = DataObject::get('GridFieldTest_Player')->find('Email', '*****@*****.**');
     $config = GridFieldConfig::create()->addComponents($relationComponent = new GridFieldAddExistingAutocompleter('before'), new GridFieldDataColumns());
     $field = new GridField('testfield', 'testfield', $player->Teams(), $config);
     return new Form($this, 'Form', new FieldList($field), new FieldList());
 }
 public function testCreateWithTransaction()
 {
     if (DB::get_conn()->supportsTransactions() == true) {
         DB::get_conn()->transactionStart();
         $obj = new TransactionTest_Object();
         $obj->Title = 'First page';
         $obj->write();
         $obj = new TransactionTest_Object();
         $obj->Title = 'Second page';
         $obj->write();
         //Create a savepoint here:
         DB::get_conn()->transactionSavepoint('rollback');
         $obj = new TransactionTest_Object();
         $obj->Title = 'Third page';
         $obj->write();
         $obj = new TransactionTest_Object();
         $obj->Title = 'Fourth page';
         $obj->write();
         //Revert to a savepoint:
         DB::get_conn()->transactionRollback('rollback');
         DB::get_conn()->transactionEnd();
         $first = DataObject::get('TransactionTest_Object', "\"Title\"='First page'");
         $second = DataObject::get('TransactionTest_Object', "\"Title\"='Second page'");
         $third = DataObject::get('TransactionTest_Object', "\"Title\"='Third page'");
         $fourth = DataObject::get('TransactionTest_Object', "\"Title\"='Fourth page'");
         //These pages should be in the system
         $this->assertTrue(is_object($first) && $first->exists());
         $this->assertTrue(is_object($second) && $second->exists());
         //These pages should NOT exist, we reverted to a savepoint:
         $this->assertFalse(is_object($third) && $third->exists());
         $this->assertFalse(is_object($fourth) && $fourth->exists());
     } else {
         $this->markTestSkipped('Current database does not support transactions');
     }
 }
 public function testDelete()
 {
     $role = $this->objFromFixture('SilverStripe\\Security\\PermissionRole', 'role');
     $role->delete();
     $this->assertEquals(0, DataObject::get('SilverStripe\\Security\\PermissionRole', "\"ID\"={$role->ID}")->count(), 'Role is removed');
     $this->assertEquals(0, DataObject::get('SilverStripe\\Security\\PermissionRoleCode', "\"RoleID\"={$role->ID}")->count(), 'Permissions removed along with the role');
 }
 public function testArrayValueWithSqlMapSource()
 {
     $member1 = $this->objFromFixture('SilverStripe\\Security\\Member', 'member1');
     $member2 = $this->objFromFixture('SilverStripe\\Security\\Member', 'member2');
     $member3 = $this->objFromFixture('SilverStripe\\Security\\Member', 'member3');
     $source = DataObject::get('SilverStripe\\Security\\Member');
     $f = new LookupField('test', 'test', $source->map('ID', 'FirstName'));
     $f->setValue(array($member1->ID, $member2->ID));
     $this->assertEquals(sprintf('<span class="readonly" id="test">member1, member2</span>' . '<input type="hidden" name="test" value="%s, %s" />', $member1->ID, $member2->ID), trim($f->Field()->getValue()));
 }
 public function testLoadDataFromObject()
 {
     $article = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');
     $articleWithTags = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithtags');
     $tag1 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag1');
     $tag2 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag2');
     $field = new CheckboxSetField("Tags", "Test field", DataObject::get("CheckboxSetFieldTest_Tag")->map());
     $form = new Form(new Controller(), 'Form', new FieldList($field), new FieldList());
     $form->loadDataFrom($articleWithTags);
     $value = $field->Value();
     sort($value);
     $this->assertEquals(array($tag1->ID, $tag2->ID), $value, 'CheckboxSetField loads data from a manymany relationship in an object through Form->loadDataFrom()');
 }
 /**
  * Test plain import with clear_table_before_import
  */
 public function testDeleteExistingRecords()
 {
     $loader = new CsvBulkLoader('CsvBulkLoaderTest_Player');
     $filepath = $this->getCurrentAbsolutePath() . '/CsvBulkLoaderTest_PlayersWithHeader.csv';
     $loader->deleteExistingRecords = true;
     $results1 = $loader->load($filepath);
     $this->assertEquals(4, $results1->Count(), 'Test correct count of imported data on first load');
     //delete existing data before doing second CSV import
     $results2 = $loader->load($filepath, '512MB', true);
     //get all instances of the loaded DataObject from the database and count them
     $resultDataObject = DataObject::get('CsvBulkLoaderTest_Player');
     $this->assertEquals(4, $resultDataObject->Count(), 'Test if existing data is deleted before new data is added');
 }
 public function setUp()
 {
     parent::setUp();
     Versioned::set_stage(Versioned::DRAFT);
     // Automatically publish any object named *_published
     foreach ($this->getFixtureFactory()->getFixtures() as $class => $fixtures) {
         foreach ($fixtures as $name => $id) {
             if (stripos($name, '_published') !== false) {
                 /** @var Versioned|DataObject $object */
                 $object = DataObject::get($class)->byID($id);
                 $object->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
             }
         }
     }
 }
 /**
  * Ensure that changes to records flush overwritten files, and update the visibility
  * of other assets.
  */
 public function onBeforeWrite()
 {
     // Prepare blank manipulation
     $manipulations = new AssetManipulationList();
     // Mark overwritten object as deleted
     if ($this->owner->isInDB()) {
         $priorRecord = DataObject::get(get_class($this->owner))->byID($this->owner->ID);
         if ($priorRecord) {
             $this->addAssetsFromRecord($manipulations, $priorRecord, AssetManipulationList::STATE_DELETED);
         }
     }
     // Add assets from new record with the correct visibility rules
     $state = $this->getRecordState($this->owner);
     $this->addAssetsFromRecord($manipulations, $this->owner, $state);
     // Whitelist assets that exist in other stages
     $this->addAssetsFromOtherStages($manipulations);
     // Apply visibility rules based on the final manipulation
     $this->processManipulation($manipulations);
 }
 /**
  * Test that you can call Hierarchy::markExpanded/Unexpanded/Open() on a obj, and that
  * calling Hierarchy::isMarked() on a different instance of that object will return true.
  */
 public function testItemMarkingIsntRestrictedToSpecificInstance()
 {
     // Mark a few objs
     $this->objFromFixture('HierarchyTest_Object', 'obj2')->markExpanded();
     $this->objFromFixture('HierarchyTest_Object', 'obj2a')->markExpanded();
     $this->objFromFixture('HierarchyTest_Object', 'obj2b')->markExpanded();
     $this->objFromFixture('HierarchyTest_Object', 'obj3')->markUnexpanded();
     // Query some objs in a different context and check their m
     $objs = DataObject::get("HierarchyTest_Object", '', '"ID" ASC');
     $marked = $expanded = array();
     foreach ($objs as $obj) {
         if ($obj->isMarked()) {
             $marked[] = $obj->Title;
         }
         if ($obj->isExpanded()) {
             $expanded[] = $obj->Title;
         }
     }
     $this->assertEquals(array('Obj 2', 'Obj 3', 'Obj 2a', 'Obj 2b'), $marked);
     $this->assertEquals(array('Obj 2', 'Obj 2a', 'Obj 2b'), $expanded);
 }
 public function testSaveInto()
 {
     $group = $this->objFromFixture('SilverStripe\\Security\\Group', 'group');
     // tested group
     $untouchable = $this->objFromFixture('SilverStripe\\Security\\Group', 'untouchable');
     // group that should not change
     $field = new PermissionCheckboxSetField('Permissions', 'Permissions', 'SilverStripe\\Security\\Permission', 'GroupID', $group);
     // get the number of permissions before we start
     $baseCount = DataObject::get('SilverStripe\\Security\\Permission')->Count();
     // there are currently no permissions, save empty checkbox
     $field->saveInto($group);
     $group->flushCache();
     $untouchable->flushCache();
     $this->assertEquals($group->Permissions()->Count(), 0, 'The tested group has no permissions');
     $this->assertEquals($untouchable->Permissions()->Count(), 1, 'The other group has one permission');
     $this->assertEquals($untouchable->Permissions()->where("\"Code\"='ADMIN'")->Count(), 1, 'The other group has ADMIN permission');
     $this->assertEquals(DataObject::get('SilverStripe\\Security\\Permission')->Count(), $baseCount, 'There are no orphaned permissions');
     // add some permissions
     $field->setValue(array('ADMIN' => true, 'NON-ADMIN' => true));
     $field->saveInto($group);
     $group->flushCache();
     $untouchable->flushCache();
     $this->assertEquals($group->Permissions()->Count(), 2, 'The tested group has two permissions permission');
     $this->assertEquals($group->Permissions()->where("\"Code\"='ADMIN'")->Count(), 1, 'The tested group has ADMIN permission');
     $this->assertEquals($group->Permissions()->where("\"Code\"='NON-ADMIN'")->Count(), 1, 'The tested group has CMS_ACCESS_AssetAdmin permission');
     $this->assertEquals($untouchable->Permissions()->Count(), 1, 'The other group has one permission');
     $this->assertEquals($untouchable->Permissions()->where("\"Code\"='ADMIN'")->Count(), 1, 'The other group has ADMIN permission');
     $this->assertEquals(DataObject::get('SilverStripe\\Security\\Permission')->Count(), $baseCount + 2, 'There are no orphaned permissions');
     // remove permission
     $field->setValue(array('ADMIN' => true));
     $field->saveInto($group);
     $group->flushCache();
     $untouchable->flushCache();
     $this->assertEquals($group->Permissions()->Count(), 1, 'The tested group has 1 permission');
     $this->assertEquals($group->Permissions()->where("\"Code\"='ADMIN'")->Count(), 1, 'The tested group has ADMIN permission');
     $this->assertEquals($untouchable->Permissions()->Count(), 1, 'The other group has one permission');
     $this->assertEquals($untouchable->Permissions()->where("\"Code\"='ADMIN'")->Count(), 1, 'The other group has ADMIN permission');
     $this->assertEquals(DataObject::get('SilverStripe\\Security\\Permission')->Count(), $baseCount + 1, 'There are no orphaned permissions');
 }
 /**
  * Link this group set to a specific member.
  *
  * Recursively selects all groups applied to this member, as well as any
  * parent groups of any applied groups
  *
  * @param array|integer $id (optional) An ID or an array of IDs - if not provided, will use the current
  * ids as per getForeignID
  * @return array Condition In array(SQL => parameters format)
  */
 public function foreignIDFilter($id = null)
 {
     if ($id === null) {
         $id = $this->getForeignID();
     }
     // Find directly applied groups
     $manyManyFilter = parent::foreignIDFilter($id);
     $query = new SQLSelect('"Group_Members"."GroupID"', '"Group_Members"', $manyManyFilter);
     $groupIDs = $query->execute()->column();
     // Get all ancestors, iteratively merging these into the master set
     $allGroupIDs = array();
     while ($groupIDs) {
         $allGroupIDs = array_merge($allGroupIDs, $groupIDs);
         $groupIDs = DataObject::get("SilverStripe\\Security\\Group")->byIDs($groupIDs)->column("ParentID");
         $groupIDs = array_filter($groupIDs);
     }
     // Add a filter to this DataList
     if (!empty($allGroupIDs)) {
         $allGroupIDsPlaceholders = DB::placeholders($allGroupIDs);
         return array("\"Group\".\"ID\" IN ({$allGroupIDsPlaceholders})" => $allGroupIDs);
     } else {
         return array('"Group"."ID"' => 0);
     }
 }
 /**
  * Searches the SiteTree for display in the dropdown
  *
  * @return callback
  */
 public function siteTreeSearchCallback($sourceObject, $labelField, $search)
 {
     return DataObject::get($sourceObject)->filterAny(array('MenuTitle:PartialMatch' => $search, 'Title:PartialMatch' => $search));
 }
 /**
  * Find an existing objects based on one or more uniqueness columns
  * specified via {@link self::$duplicateChecks}.
  *
  * @todo support $columnMap
  *
  * @param array $record CSV data column
  * @param array $columnMap
  * @return DataObject
  */
 public function findExistingObject($record, $columnMap = [])
 {
     $SNG_objectClass = singleton($this->objectClass);
     // checking for existing records (only if not already found)
     foreach ($this->duplicateChecks as $fieldName => $duplicateCheck) {
         $existingRecord = null;
         if (is_string($duplicateCheck)) {
             // Skip current duplicate check if field value is empty
             if (empty($record[$duplicateCheck])) {
                 continue;
             }
             // Check existing record with this value
             $dbFieldValue = $record[$duplicateCheck];
             $existingRecord = DataObject::get($this->objectClass)->filter($duplicateCheck, $dbFieldValue)->first();
             if ($existingRecord) {
                 return $existingRecord;
             }
         } elseif (is_array($duplicateCheck) && isset($duplicateCheck['callback'])) {
             if ($this->hasMethod($duplicateCheck['callback'])) {
                 $existingRecord = $this->{$duplicateCheck['callback']}($record[$fieldName], $record);
             } elseif ($SNG_objectClass->hasMethod($duplicateCheck['callback'])) {
                 $existingRecord = $SNG_objectClass->{$duplicateCheck['callback']}($record[$fieldName], $record);
             } else {
                 user_error("CsvBulkLoader::processRecord():" . " {$duplicateCheck['callback']} not found on importer or object class.", E_USER_ERROR);
             }
             if ($existingRecord) {
                 return $existingRecord;
             }
         } else {
             user_error('CsvBulkLoader::processRecord(): Wrong format for $duplicateChecks', E_USER_ERROR);
         }
     }
     return false;
 }
 /**
  * Allows requesting a view update on specific tree nodes.
  * Similar to {@link getsubtree()}, but doesn't enforce loading
  * all children with the node. Useful to refresh views after
  * state modifications, e.g. saving a form.
  *
  * @param HTTPRequest $request
  * @return string JSON
  */
 public function updatetreenodes($request)
 {
     $data = array();
     $ids = explode(',', $request->getVar('ids'));
     foreach ($ids as $id) {
         if ($id === "") {
             continue;
         }
         // $id may be a blank string, which is invalid and should be skipped over
         $record = $this->getRecord($id);
         if (!$record) {
             continue;
         }
         // In case a page is no longer available
         $recordController = $this->stat('tree_class') == 'SilverStripe\\CMS\\Model\\SiteTree' ? CMSPageEditController::singleton() : $this;
         // Find the next & previous nodes, for proper positioning (Sort isn't good enough - it's not a raw offset)
         // TODO: These methods should really be in hierarchy - for a start it assumes Sort exists
         $next = $prev = null;
         $className = $this->stat('tree_class');
         $next = DataObject::get($className)->filter('ParentID', $record->ParentID)->filter('Sort:GreaterThan', $record->Sort)->first();
         if (!$next) {
             $prev = DataObject::get($className)->filter('ParentID', $record->ParentID)->filter('Sort:LessThan', $record->Sort)->reverse()->first();
         }
         $link = Controller::join_links($recordController->Link("show"), $record->ID);
         $html = LeftAndMain_TreeNode::create($record, $link, $this->isCurrentPage($record))->forTemplate() . '</li>';
         $data[$id] = array('html' => $html, 'ParentID' => $record->ParentID, 'NextID' => $next ? $next->ID : null, 'PrevID' => $prev ? $prev->ID : null);
     }
     $this->getResponse()->addHeader('Content-Type', 'text/json');
     return Convert::raw2json($data);
 }
 /**
  * Updates the database schema, creating tables & fields as necessary.
  *
  * @param boolean $quiet Don't show messages
  * @param boolean $populate Populate the database, as well as setting up its schema
  * @param bool $testMode
  */
 public function doBuild($quiet = false, $populate = true, $testMode = false)
 {
     if ($quiet) {
         DB::quiet();
     } else {
         $conn = DB::get_conn();
         // Assumes database class is like "MySQLDatabase" or "MSSQLDatabase" (suffixed with "Database")
         $dbType = substr(get_class($conn), 0, -8);
         $dbVersion = $conn->getVersion();
         $databaseName = method_exists($conn, 'currentDatabase') ? $conn->getSelectedDatabase() : "";
         if (Director::is_cli()) {
             echo sprintf("\n\nBuilding database %s using %s %s\n\n", $databaseName, $dbType, $dbVersion);
         } else {
             echo sprintf("<h2>Building database %s using %s %s</h2>", $databaseName, $dbType, $dbVersion);
         }
     }
     // Set up the initial database
     if (!DB::is_active()) {
         if (!$quiet) {
             echo '<p><b>Creating database</b></p>';
         }
         // Load parameters from existing configuration
         global $databaseConfig;
         if (empty($databaseConfig) && empty($_REQUEST['db'])) {
             user_error("No database configuration available", E_USER_ERROR);
         }
         $parameters = !empty($databaseConfig) ? $databaseConfig : $_REQUEST['db'];
         // Check database name is given
         if (empty($parameters['database'])) {
             user_error("No database name given; please give a value for \$databaseConfig['database']", E_USER_ERROR);
         }
         $database = $parameters['database'];
         // Establish connection and create database in two steps
         unset($parameters['database']);
         DB::connect($parameters);
         DB::create_database($database);
     }
     // Build the database.  Most of the hard work is handled by DataObject
     $dataClasses = ClassInfo::subclassesFor('SilverStripe\\ORM\\DataObject');
     array_shift($dataClasses);
     if (!$quiet) {
         if (Director::is_cli()) {
             echo "\nCREATING DATABASE TABLES\n\n";
         } else {
             echo "\n<p><b>Creating database tables</b></p>\n\n";
         }
     }
     // Initiate schema update
     $dbSchema = DB::get_schema();
     $dbSchema->schemaUpdate(function () use($dataClasses, $testMode, $quiet) {
         foreach ($dataClasses as $dataClass) {
             // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
             if (!class_exists($dataClass)) {
                 continue;
             }
             // Check if this class should be excluded as per testing conventions
             $SNG = singleton($dataClass);
             if (!$testMode && $SNG instanceof TestOnly) {
                 continue;
             }
             // Log data
             if (!$quiet) {
                 if (Director::is_cli()) {
                     echo " * {$dataClass}\n";
                 } else {
                     echo "<li>{$dataClass}</li>\n";
                 }
             }
             // Instruct the class to apply its schema to the database
             $SNG->requireTable();
         }
     });
     ClassInfo::reset_db_cache();
     if ($populate) {
         if (!$quiet) {
             if (Director::is_cli()) {
                 echo "\nCREATING DATABASE RECORDS\n\n";
             } else {
                 echo "\n<p><b>Creating database records</b></p>\n\n";
             }
         }
         foreach ($dataClasses as $dataClass) {
             // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
             // Test_ indicates that it's the data class is part of testing system
             if (strpos($dataClass, 'Test_') === false && class_exists($dataClass)) {
                 if (!$quiet) {
                     if (Director::is_cli()) {
                         echo " * {$dataClass}\n";
                     } else {
                         echo "<li>{$dataClass}</li>\n";
                     }
                 }
                 singleton($dataClass)->requireDefaultRecords();
             }
         }
         // Remap obsolete class names
         $schema = DataObject::getSchema();
         foreach ($this->config()->classname_value_remapping as $oldClassName => $newClassName) {
             $baseDataClass = $schema->baseDataClass($newClassName);
             $badRecordCount = DataObject::get($baseDataClass)->filter(["ClassName" => $oldClassName])->count();
             if ($badRecordCount > 0) {
                 if (Director::is_cli()) {
                     echo " * Correcting {$badRecordCount} obsolete classname values for {$newClassName}\n";
                 } else {
                     echo "<li>Correcting {$badRecordCount} obsolete classname values for {$newClassName}</li>\n";
                 }
                 $table = $schema->baseDataTable($baseDataClass);
                 DB::prepared_query("UPDATE \"{$table}\" SET \"ClassName\" = ? WHERE \"ClassName\" = ?", [$newClassName, $oldClassName]);
             }
         }
     }
     touch(TEMP_FOLDER . '/database-last-generated-' . str_replace(array('\\', '/', ':'), '.', Director::baseFolder()));
     if (isset($_REQUEST['from_installer'])) {
         echo "OK";
     }
     if (!$quiet) {
         echo Director::is_cli() ? "\n Database build completed!\n\n" : "<p>Database build completed!</p>";
     }
     ClassInfo::reset_db_cache();
 }
 public function testValidationWithDataList()
 {
     //test with datalist input
     $tag1 = $this->objFromFixture('ListboxFieldTest_Tag', 'tag1');
     $tag2 = $this->objFromFixture('ListboxFieldTest_Tag', 'tag2');
     $tag3 = $this->objFromFixture('ListboxFieldTest_Tag', 'tag3');
     $field = ListboxField::create('Test', 'Testing', DataObject::get("ListboxFieldTest_Tag")->map()->toArray());
     $validator = new RequiredFields();
     $field->setValue($tag1->ID);
     $this->assertTrue($field->validate($validator), 'Field validates values in source map');
     /**
      * @todo re-enable these tests when field validation is removed from {@link ListboxField::setValue()} and moved
      * to the {@link ListboxField::validate()} function
      */
     //		$field->setValue(4);
     //		$this->assertFalse(
     //			$field->validate($validator),
     //			'Field does not validate values outside of source map'
     //		);
     $field->setValue(false, new ArrayData(array($tag1->ID => $tag1->ID, $tag2->ID => $tag2->ID)));
     $this->assertTrue($field->validate($validator), 'Validates values in source map');
     //invalid value should fail
     $field->setValue(4);
     $this->assertFalse($field->validate($validator), 'Does not validate values not within source map');
 }
 /**
  * Get the object where the $keyField is equal to a certain value
  *
  * @param string|int $key
  * @return DataObject
  */
 protected function objectForKey($key)
 {
     return DataObject::get($this->sourceObject)->filter($this->keyField, $key)->first();
 }
 public function testLazyLoadedFieldsGetAllFields()
 {
     $subteam1 = $this->objFromFixture('DataObjectTest_SubTeam', 'subteam1');
     $parentTeam = $this->objFromFixture('DataObjectTest_Team', 'team1');
     $teams = DataObject::get('DataObjectTest_Team');
     // query parent class
     $subteam1Lazy = $teams->find('ID', $subteam1->ID);
     $this->assertArrayNotHasKey('SubclassDatabaseField_Lazy', $subteam1Lazy->toMap());
     $this->assertArrayHasKey('SubclassDatabaseField', $subteam1Lazy->toMap());
 }
 /**
  * Loads the related record values into this field. UploadField can be uploaded
  * in one of three ways:
  *
  *  - By passing in a list of file IDs in the $value parameter (an array with a single
  *    key 'Files', with the value being the actual array of IDs).
  *  - By passing in an explicit list of File objects in the $record parameter, and
  *    leaving $value blank.
  *  - By passing in a dataobject in the $record parameter, from which file objects
  *    will be extracting using the field name as the relation field.
  *
  * Each of these methods will update both the items (list of File objects) and the
  * field value (list of file ID values).
  *
  * @param array $value Array of submitted form data, if submitting from a form
  * @param array|DataObject|SS_List $record Full source record, either as a DataObject,
  * SS_List of items, or an array of submitted form data
  * @return $this Self reference
  * @throws ValidationException
  */
 public function setValue($value, $record = null)
 {
     // If we're not passed a value directly, we can attempt to infer the field
     // value from the second parameter by inspecting its relations
     $items = new ArrayList();
     // Determine format of presented data
     if (empty($value) && $record) {
         // If a record is given as a second parameter, but no submitted values,
         // then we should inspect this instead for the form values
         if ($record instanceof DataObject && $record->hasMethod($this->getName())) {
             // If given a dataobject use reflection to extract details
             $data = $record->{$this->getName()}();
             if ($data instanceof DataObject) {
                 // If has_one, add sole item to default list
                 $items->push($data);
             } elseif ($data instanceof SS_List) {
                 // For many_many and has_many relations we can use the relation list directly
                 $items = $data;
             }
         } elseif ($record instanceof SS_List) {
             // If directly passing a list then save the items directly
             $items = $record;
         }
     } elseif (!empty($value['Files'])) {
         // If value is given as an array (such as a posted form), extract File IDs from this
         $class = $this->getRelationAutosetClass();
         $items = DataObject::get($class)->byIDs($value['Files']);
     }
     // If javascript is disabled, direct file upload (non-html5 style) can
     // trigger a single or multiple file submission. Note that this may be
     // included in addition to re-submitted File IDs as above, so these
     // should be added to the list instead of operated on independently.
     if ($uploadedFiles = $this->extractUploadedFileData($value)) {
         foreach ($uploadedFiles as $tempFile) {
             $file = $this->saveTemporaryFile($tempFile, $error);
             if ($file) {
                 $items->add($file);
             } else {
                 throw new ValidationException($error);
             }
         }
     }
     // Filter items by what's allowed to be viewed
     $filteredItems = new ArrayList();
     $fileIDs = array();
     foreach ($items as $file) {
         if ($file->exists() && $file->canView()) {
             $filteredItems->push($file);
             $fileIDs[] = $file->ID;
         }
     }
     // Filter and cache updated item list
     $this->items = $filteredItems;
     // Same format as posted form values for this field. Also ensures that
     // $this->setValue($this->getValue()); is non-destructive
     $value = $fileIDs ? array('Files' => $fileIDs) : null;
     // Set value using parent
     parent::setValue($value, $record);
     return $this;
 }
예제 #20
0
 public function getCMSFields()
 {
     $groups = DataObject::get('SilverStripe\\Security\\Group');
     $groupsMap = $groups ? $groups->map() : false;
     $fields = new FieldList(new HiddenField('ID', 'ID'), new CheckboxSetField('Groups', 'Groups', $groupsMap));
     return $fields;
 }
 /**
  * Test that password changes are logged properly
  */
 public function testPasswordChangeLogging()
 {
     $member = $this->objFromFixture('SilverStripe\\Security\\Member', 'test');
     $this->assertNotNull($member);
     $member->Password = "******";
     $member->write();
     $member->Password = "******";
     $member->write();
     $member->Password = "******";
     $member->write();
     $passwords = DataObject::get("SilverStripe\\Security\\MemberPassword", "\"MemberID\" = {$member->ID}", "\"Created\" DESC, \"ID\" DESC")->getIterator();
     $this->assertNotNull($passwords);
     $passwords->rewind();
     $this->assertTrue($passwords->current()->checkPassword('test3'), "Password test3 not found in MemberRecord");
     $passwords->next();
     $this->assertTrue($passwords->current()->checkPassword('test2'), "Password test2 not found in MemberRecord");
     $passwords->next();
     $this->assertTrue($passwords->current()->checkPassword('test1'), "Password test1 not found in MemberRecord");
     $passwords->next();
     $this->assertInstanceOf('SilverStripe\\ORM\\DataObject', $passwords->current());
     $this->assertTrue($passwords->current()->checkPassword('1nitialPassword'), "Password 1nitialPassword not found in MemberRecord");
     //check we don't retain orphaned records when a member is deleted
     $member->delete();
     $passwords = MemberPassword::get()->filter('MemberID', $member->OldID);
     $this->assertCount(0, $passwords);
 }
 /**
  * Cleanup function to reset all the Filename fields.  Visit File/fixfiles to call.
  */
 public function fixfiles()
 {
     if (!Permission::check('ADMIN')) {
         return Security::permissionFailure($this);
     }
     $files = DataObject::get("File");
     foreach ($files as $file) {
         $file->updateFilesystem();
         echo "<li>", $file->Filename;
         $file->write();
     }
     echo "<p>Done!";
 }
 /**
  * Safely query and return all pages queried
  *
  * @param array $ids
  * @return SS_List
  */
 protected function getPages($ids)
 {
     // Check empty set
     if (empty($ids)) {
         return new ArrayList();
     }
     $recordClass = $this->recordClass;
     // Bypass translatable filter
     if (class_exists('Translatable') && $recordClass::has_extension('Translatable')) {
         Translatable::disable_locale_filter();
     }
     // Bypass versioned filter
     if ($recordClass::has_extension(Versioned::class)) {
         // Workaround for get_including_deleted not supporting byIDs filter very well
         // Ensure we select both stage / live records
         $pages = Versioned::get_including_deleted($recordClass, array('"RecordID" IN (' . DB::placeholders($ids) . ')' => $ids));
     } else {
         $pages = DataObject::get($recordClass)->byIDs($ids);
     }
     if (class_exists('Translatable') && $recordClass::has_extension('Translatable')) {
         Translatable::enable_locale_filter();
     }
     return $pages;
 }
 /**
  * Safely get a DataObject from a client-supplied ID and ClassName, checking: argument
  * validity; existence; and canView permissions.
  *
  * @param int $id The ID of the DataObject
  * @param string $class The Class of the DataObject
  * @return DataObject The referenced DataObject
  * @throws SS_HTTPResponse_Exception
  */
 protected function getObject($id, $class)
 {
     $id = (int) $id;
     $class = ClassInfo::class_name($class);
     if (!$class || !is_subclass_of($class, 'SilverStripe\\ORM\\DataObject') || !Object::has_extension($class, 'SilverStripe\\ORM\\Versioning\\Versioned')) {
         $this->editForm->httpError(400, _t('AddToCampaign.ErrorGeneral', 'We apologise, but there was an error'));
         return null;
     }
     $object = DataObject::get($class)->byID($id);
     if (!$object) {
         $this->editForm->httpError(404, _t('AddToCampaign.ErrorNotFound', 'That {Type} couldn\'t be found', '', ['Type' => $class]));
         return null;
     }
     if (!$object->canView()) {
         $this->editForm->httpError(403, _t('AddToCampaign.ErrorItemPermissionDenied', 'It seems you don\'t have the necessary permissions to add {ObjectTitle} to a campaign', '', ['ObjectTitle' => $object->Title]));
         return null;
     }
     return $object;
 }
 /**
  * Return the first item matching the given query.
  * All calls to get_one() are cached.
  *
  * @param string $callerClass The class of objects to be returned
  * @param string|array $filter A filter to be inserted into the WHERE clause.
  * Supports parameterised queries. See SQLSelect::addWhere() for syntax examples.
  * @param boolean $cache Use caching
  * @param string $orderby A sort expression to be inserted into the ORDER BY clause.
  *
  * @return DataObject The first item matching the query
  */
 public static function get_one($callerClass, $filter = "", $cache = true, $orderby = "")
 {
     $SNG = singleton($callerClass);
     $cacheComponents = array($filter, $orderby, $SNG->extend('cacheKeyComponent'));
     $cacheKey = md5(var_export($cacheComponents, true));
     // Flush destroyed items out of the cache
     if ($cache && isset(self::$_cache_get_one[$callerClass][$cacheKey]) && self::$_cache_get_one[$callerClass][$cacheKey] instanceof DataObject && self::$_cache_get_one[$callerClass][$cacheKey]->destroyed) {
         self::$_cache_get_one[$callerClass][$cacheKey] = false;
     }
     $item = null;
     if (!$cache || !isset(self::$_cache_get_one[$callerClass][$cacheKey])) {
         $dl = DataObject::get($callerClass)->where($filter)->sort($orderby);
         $item = $dl->first();
         if ($cache) {
             self::$_cache_get_one[$callerClass][$cacheKey] = $item;
             if (!self::$_cache_get_one[$callerClass][$cacheKey]) {
                 self::$_cache_get_one[$callerClass][$cacheKey] = false;
             }
         }
     }
     return $cache ? self::$_cache_get_one[$callerClass][$cacheKey] : $item;
 }
 public function testBrokenLateStaticBindingStyle()
 {
     // If you call DataObject::get() you have to pass a first argument
     $this->setExpectedException('InvalidArgumentException');
     DataObject::get();
 }
 public function load($filepath)
 {
     increase_time_limit_to(3600);
     increase_memory_limit_to('512M');
     //get all instances of the to be imported data object
     if ($this->deleteExistingRecords) {
         DataObject::get($this->objectClass)->removeAll();
     }
     return $this->processAll($filepath);
 }
 public function testArchiveVersion()
 {
     // In 2005 this file was created
     DBDatetime::set_mock_now('2005-01-01 00:00:00');
     $testPage = new VersionedTest_Subclass();
     $testPage->Title = 'Archived page';
     $testPage->Content = 'This is the content from 2005';
     $testPage->ExtraField = '2005';
     $testPage->write();
     // In 2007 we updated it
     DBDatetime::set_mock_now('2007-01-01 00:00:00');
     $testPage->Content = "It's 2007 already!";
     $testPage->ExtraField = '2007';
     $testPage->write();
     // In 2009 we updated it again
     DBDatetime::set_mock_now('2009-01-01 00:00:00');
     $testPage->Content = "I'm enjoying 2009";
     $testPage->ExtraField = '2009';
     $testPage->write();
     // End mock, back to the present day:)
     DBDatetime::clear_mock_now();
     // Test 1 - 2006 Content
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Archive.2006-01-01 00:00:00');
     $testPage2006 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPage2006);
     $this->assertEquals("2005", $testPage2006->ExtraField);
     $this->assertEquals("This is the content from 2005", $testPage2006->Content);
     // Test 2 - 2008 Content
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Archive.2008-01-01 00:00:00');
     $testPage2008 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPage2008);
     $this->assertEquals("2007", $testPage2008->ExtraField);
     $this->assertEquals("It's 2007 already!", $testPage2008->Content);
     // Test 3 - Today
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Stage.Stage');
     $testPageCurrent = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPageCurrent);
     $this->assertEquals("2009", $testPageCurrent->ExtraField);
     $this->assertEquals("I'm enjoying 2009", $testPageCurrent->Content);
 }
 /**
  * Helper method for applicablePages() methods.  Acts as a skeleton implementation.
  *
  * @param array $ids The IDs passed to applicablePages
  * @param string $methodName The canXXX() method to call on each page to check if the action is applicable
  * @param bool $checkStagePages Set to true if you want to check stage pages
  * @param bool $checkLivePages Set to true if you want to check live pages (e.g, for deleted-from-draft)
  * @return array
  */
 public function applicablePagesHelper($ids, $methodName, $checkStagePages = true, $checkLivePages = true)
 {
     if (!is_array($ids)) {
         user_error("Bad \$ids passed to applicablePagesHelper()", E_USER_WARNING);
     }
     if (!is_string($methodName)) {
         user_error("Bad \$methodName passed to applicablePagesHelper()", E_USER_WARNING);
     }
     $applicableIDs = array();
     $managedClass = $this->managedClass;
     $draftPages = DataObject::get($managedClass)->byIDs($ids);
     // Filter out the live-only ids
     $onlyOnLive = array_fill_keys($ids, true);
     if ($checkStagePages) {
         foreach ($draftPages as $obj) {
             unset($onlyOnLive[$obj->ID]);
             if ($obj->{$methodName}()) {
                 $applicableIDs[] = $obj->ID;
             }
         }
     }
     $onlyOnLive = array_keys($onlyOnLive);
     if ($checkLivePages && $onlyOnLive && Object::has_extension($managedClass, 'SilverStripe\\ORM\\Versioning\\Versioned')) {
         // Get the pages that only exist on live (deleted from stage)
         $livePages = Versioned::get_by_stage($managedClass, "Live")->byIDs($onlyOnLive);
         foreach ($livePages as $obj) {
             if ($obj->{$methodName}()) {
                 $applicableIDs[] = $obj->ID;
             }
         }
     }
     return $applicableIDs;
 }
예제 #30
0
 /**
  * Get a set of class instances by the given stage.
  *
  * @param string $class The name of the class.
  * @param string $stage The name of the stage.
  * @param string $filter A filter to be inserted into the WHERE clause.
  * @param string $sort A sort expression to be inserted into the ORDER BY clause.
  * @param string $join Deprecated, use leftJoin($table, $joinClause) instead
  * @param int $limit A limit on the number of records returned from the database.
  * @param string $containerClass The container class for the result set (default is DataList)
  *
  * @return DataList A modified DataList designated to the specified stage
  */
 public static function get_by_stage($class, $stage, $filter = '', $sort = '', $join = '', $limit = null, $containerClass = 'SilverStripe\\ORM\\DataList')
 {
     $result = DataObject::get($class, $filter, $sort, $join, $limit, $containerClass);
     return $result->setDataQueryParam(array('Versioned.mode' => 'stage', 'Versioned.stage' => $stage));
 }