function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields = null, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); $classes = array_reverse(ClassInfo::ancestry($this->controllerClass())); foreach ($classes as $class) { $singleton = singleton($class); $manyManyRelations = $singleton->uninherited('many_many', true); if (isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $class . '_' . $this->name; break; } $belongsManyManyRelations = $singleton->uninherited('belongs_many_many', true); if (isset($belongsManyManyRelations) && array_key_exists($this->name, $belongsManyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $this->name; break; } } $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); $source = array_shift($tableClasses); $sourceField = $this->sourceClass; if ($this->manyManyParentClass == $sourceField) { $sourceField = 'Child'; } $parentID = $this->controller->ID; $this->sourceJoin .= " LEFT JOIN `{$manyManyTable}` ON (`{$source}`.`ID` = `{$sourceField}ID` AND `{$this->manyManyParentClass}ID` = '{$parentID}')"; $this->joinField = 'Checked'; }
/** * Most of the code below was copied from ManyManyComplexTableField. * Painful, but necessary, until PHP supports multiple inheritance. */ function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields = null, $sourceFilter = "", $sourceSort = "Created DESC", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); $manyManyTable = false; $classes = array_reverse(ClassInfo::ancestry($this->controllerClass())); foreach ($classes as $class) { if ($class != "Object") { $singleton = singleton($class); $manyManyRelations = $singleton->uninherited('many_many', true); if (isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $class . '_' . $this->name; break; } $belongsManyManyRelations = $singleton->uninherited('belongs_many_many', true); if (isset($belongsManyManyRelations) && array_key_exists($this->name, $belongsManyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $this->name; break; } } } if (!$manyManyTable) { user_error("I could not find the relation {$this}-name in " . $this->controllerClass() . " or any of its ancestors.", E_USER_WARNING); } $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); $source = array_shift($tableClasses); $sourceField = $this->sourceClass; if ($this->manyManyParentClass == $sourceField) { $sourceField = 'Child'; } $parentID = $this->controller->ID; $this->sourceJoin .= " LEFT JOIN `{$manyManyTable}` ON (`{$source}`.`ID` = `{$sourceField}ID` AND `{$this->manyManyParentClass}ID` = '{$parentID}')"; $this->joinField = 'Checked'; }
/** * Modified version of the SiteTree publish method. * * @return <type> */ public function doPublish() { if (!$this->owner->canPublish()) { return false; } $class = $this->owner->class; $ownerId = $this->owner->ID; $dataClasses = ClassInfo::dataClassesFor($class); $dataClasses = array_values($dataClasses); $class = $dataClasses[count($dataClasses) - 1]; $original = Versioned::get_one_by_stage("{$class}", "Live", "\"{$class}\".\"ID\" = {$ownerId}"); if (!$original) { $original = new $class(); } $this->owner->invokeWithExtensions('onBeforePublish', $original); // Handle activities undertaken by decorators $this->owner->Status = "Published"; //$this->PublishedByID = Member::currentUser()->ID; $this->owner->write(); $this->owner->publish("Stage", "Live"); if ($this->owner->hasField('Sort')) { // find the table that actually defines the sortable field $class = get_class($this->owner); if ($this->owner->hasMethod('findClassDefiningSortField')) { $class = $this->owner->findClassDefiningSortField(); } DB::query("UPDATE \"{$class}_Live\"\n\t\t\t\tSET \"Sort\" = (SELECT \"{$class}\".\"Sort\" FROM \"{$class}\" WHERE \"{$class}_Live\".\"ID\" = \"{$class}\".\"ID\")"); } // Handle activities undertaken by decorators $this->owner->invokeWithExtensions('onAfterPublish', $original); return true; }
function __construct($controller, $name, $sourceClass, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { Deprecation::notice('3.0', 'Use GridField with GridFieldConfig_RelationEditor'); parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); $classes = array_reverse(ClassInfo::ancestry($this->controllerClass())); foreach($classes as $class) { $singleton = singleton($class); $manyManyRelations = $singleton->uninherited('many_many', true); if(isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $class . '_' . $this->name; break; } $belongsManyManyRelations = $singleton->uninherited( 'belongs_many_many', true ); if( isset( $belongsManyManyRelations ) && array_key_exists( $this->name, $belongsManyManyRelations ) ) { $this->manyManyParentClass = $class; $manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $this->name; break; } } $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); $source = array_shift($tableClasses); $sourceField = $this->sourceClass; if($this->manyManyParentClass == $sourceField) $sourceField = 'Child'; $parentID = $this->controller->ID; $this->sourceJoin .= " LEFT JOIN \"$manyManyTable\" ON (\"$source\".\"ID\" = \"$manyManyTable\".\"{$sourceField}ID\" AND \"{$this->manyManyParentClass}ID\" = '$parentID')"; $this->joinField = 'Checked'; }
function __construct($controller, $name, $sourceClass, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); //Sort by heirarchy, depending on number of parents indent $classes = array_reverse(ClassInfo::ancestry($this->controllerClass())); foreach ($classes as $class) { $singleton = singleton($class); $manyManyRelations = $singleton->uninherited('many_many', true); if (isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { $this->manyManyParentClass = $class; $this->manyManyTable = $class . '_' . $this->name; break; } $belongsManyManyRelations = $singleton->uninherited('belongs_many_many', true); if (isset($belongsManyManyRelations) && array_key_exists($this->name, $belongsManyManyRelations)) { $singleton = singleton($belongsManyManyRelations[$this->name]); $manyManyRelations = $singleton->uninherited('many_many', true); $this->manyManyParentClass = $class; $relation = array_flip($manyManyRelations); $this->manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $relation[$class]; break; } } $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); $source = array_shift($tableClasses); $sourceField = $this->sourceClass; if ($this->manyManyParentClass == $sourceField) { $sourceField = 'Child'; } $parentID = $this->controller->ID; $this->sourceJoin .= " LEFT JOIN \"{$this->manyManyTable}\" ON (\"{$source}\".\"ID\" = \"{$this->manyManyTable}\".\"{$sourceField}ID\" AND \"{$this->manyManyTable}\".\"{$this->manyManyParentClass}ID\" = '{$parentID}')"; $this->joinField = 'Checked'; }
/** * @covers ClassInfo::dataClassesFor() */ public function testDataClassesFor() { $expect = array('ClassInfoTest_BaseDataClass' => 'ClassInfoTest_BaseDataClass', 'ClassInfoTest_HasFields' => 'ClassInfoTest_HasFields'); $classes = array('ClassInfoTest_BaseDataClass', 'ClassInfoTest_NoFields', 'ClassInfoTest_HasFields'); foreach ($classes as $class) { $this->assertEquals($expect, ClassInfo::dataClassesFor($class)); } }
/** * Assign a sort number when object is written * @see DataExtension::onBeforeWrite() */ public function onBeforeWrite() { if (!$this->owner->ID && !$this->owner->SortOrder || !$this->owner->SortOrder) { $classes = ClassInfo::dataClassesFor($this->owner->ClassName); $sql = new SQLQuery('count(ID)', array_shift($classes)); $val = $sql->execute()->value(); $this->owner->SortOrder = is_numeric($val) ? $val + 1 : 1; } }
/** * Assign a sort number when object is written * @see DataExtension::onBeforeWrite() */ public function onBeforeWrite() { if (!$this->owner->exists() || !$this->owner->SortOrder) { $classes = ClassInfo::dataClassesFor($this->owner->ClassName); $sql = new SQLQuery('MAX("SortOrder")', '"' . array_shift($classes) . '"'); $val = $sql->execute()->value(); $this->owner->SortOrder = is_numeric($val) ? $val + 1 : 1; } }
public static function allFieldsForClass($class) { $dataClasses = ClassInfo::dataClassesFor($class); $fields = array(); foreach ($dataClasses as $dataClass) { $fields = array_merge($fields, array_keys(DataObject::database_fields($dataClass))); } return array_combine($fields, $fields); }
/** * @covers ClassInfo::dataClassesFor() */ public function testDataClassesFor() { $expect = array('ClassInfoTest_BaseDataClass' => 'ClassInfoTest_BaseDataClass', 'ClassInfoTest_HasFields' => 'ClassInfoTest_HasFields', 'ClassInfoTest_WithRelation' => 'ClassInfoTest_WithRelation'); $classes = array('ClassInfoTest_BaseDataClass', 'ClassInfoTest_NoFields', 'ClassInfoTest_HasFields'); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[0])); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[1])); $expect = array('ClassInfoTest_BaseDataClass' => 'ClassInfoTest_BaseDataClass', 'ClassInfoTest_HasFields' => 'ClassInfoTest_HasFields'); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[2])); }
/** * @refactor move to SQLQuery * @todo fix hack */ protected function applyBaseTableFields() { $classes = ClassInfo::dataClassesFor($this->modelClass); $fields = array("`" . ClassInfo::baseDataClass($this->modelClass) . '`.*'); if ($this->modelClass != $classes[0]) { $fields[] = '`' . $classes[0] . '`.*'; } //$fields = array_keys($model->db()); $fields[] = '`' . $classes[0] . '`.ClassName AS RecordClassName'; return $fields; }
/** * @return JoinSpecification[] */ public function build() { $specs = array(); $relation_name = $this->alias->getName(); $child_class = $this->relations[$relation_name]; $child_hierarchy = ClassInfo::dataClassesFor($child_class); $base_child_class = array_shift($child_hierarchy); $class_name = ClassInfo::baseDataClass($this->base_entity); $specs[] = new JoinSpecification($child_class, $child_class . '.ID = ' . $class_name . '.' . $relation_name . 'ID'); $this->base_table = $base_child_class; return $specs; }
/** * Most of the code below was copied from ManyManyComplexTableField. * Painful, but necessary, until PHP supports multiple inheritance. */ function __construct($controller, $name, $sourceClass, $fileFieldName = null, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fileFieldName, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); $manyManyTable = false; $classes = array_reverse(ClassInfo::ancestry($this->controllerClass())); foreach($classes as $class) { if($class != "Object") { $singleton = singleton($class); $manyManyRelations = $singleton->uninherited('many_many', true); if(isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { $this->manyManyParentClass = $class; $manyManyTable = $class . '_' . $this->name; break; } $belongsManyManyRelations = $singleton->uninherited( 'belongs_many_many', true ); if( isset( $belongsManyManyRelations ) && array_key_exists( $this->name, $belongsManyManyRelations ) ) { $this->manyManyParentClass = $class; // @modification http://open.silverstripe.org/ticket/5194 $manyManyClass = $belongsManyManyRelations[$this->name]; $manyManyRelations = singleton($manyManyClass)->uninherited('many_many', true); foreach($manyManyRelations as $manyManyRelationship => $manyManyChildClass) if ($manyManyChildClass == $class) break; $manyManyTable = $manyManyClass . '_' . $manyManyRelationship; break; } } } if(!$manyManyTable) user_error("I could not find the relation $this->name in " . $this->controllerClass() . " or any of its ancestors.",E_USER_WARNING); $this->manyManyTable = $manyManyTable; $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); $source = array_shift($tableClasses); $sourceField = $this->sourceClass; if($this->manyManyParentClass == $sourceField) $sourceField = 'Child'; $parentID = $this->controller->ID; $this->sourceJoin .= " LEFT JOIN \"$manyManyTable\" ON (\"$source\".\"ID\" = \"{$sourceField}ID\" AND \"$manyManyTable\".\"{$this->manyManyParentClass}ID\" = '$parentID')"; $this->joinField = 'Checked'; if(isset($_REQUEST['ctf'][$this->Name()]['only_related'])) $this->OnlyRelated = $_REQUEST['ctf'][$this->Name()]['only_related']; $this->addPermission('only_related'); // If drag-and-drop is enabled, we need to turn on the only related filter if($this->ShowAll() && SortableDataObject::is_sortable_many_many($this->sourceClass())) $this->OnlyRelated = '1'; }
/** * @return JoinSpecification[] */ public function build() { $specs = array(); $relation_name = $this->alias->getName(); $class_name = ClassInfo::baseDataClass($this->base_entity); $child_class = $this->relations[$relation_name]; $child_hierarchy = ClassInfo::dataClassesFor($child_class); $base_child_class = array_shift($child_hierarchy); $join_field = $this->base_entity->getRemoteJoinField($relation_name, 'has_many'); $specs[] = new JoinSpecification($base_child_class, $base_child_class . '.' . $join_field . ' = ' . $class_name . '.ID'); $this->base_table = $base_child_class; $this->query->addAndCondition(QueryCriteria::equal("{$base_child_class}.ClassName", $child_class)); return $specs; }
public function onAfterWrite() { parent::onAfterWrite(); $ID = $this->owner->ID; $className = $this->owner->ClassName; $subClasses = ClassInfo::dataClassesFor($className); $versionsToDelete = array(); $version_limit = Config::inst()->get('VersionTruncator', 'version_limit'); if (is_numeric($version_limit)) { $search = DB::query('SELECT "RecordID", "Version" FROM "SiteTree_versions" WHERE "RecordID" = ' . $ID . ' AND "ClassName" = \'' . $className . '\' AND "PublisherID" > 0 ORDER BY "LastEdited" DESC LIMIT ' . $version_limit . ', 200'); foreach ($search as $row) { array_push($versionsToDelete, array('RecordID' => $row['RecordID'], 'Version' => $row['Version'])); } } $draft_limit = Config::inst()->get('VersionTruncator', 'draft_limit'); if (is_numeric($draft_limit)) { $search = DB::query('SELECT "RecordID", "Version" FROM "SiteTree_versions" WHERE "RecordID" = ' . $ID . ' AND "ClassName" = \'' . $className . '\' AND "PublisherID" = 0 ORDER BY "LastEdited" DESC LIMIT ' . $draft_limit . ', 200'); foreach ($search as $row) { array_push($versionsToDelete, array('RecordID' => $row['RecordID'], 'Version' => $row['Version'])); } } $delete_old_page_types = Config::inst()->get('VersionTruncator', 'delete_old_page_types'); if ($delete_old_page_types) { $search = DB::query('SELECT "RecordID", "Version" FROM "SiteTree_versions" WHERE "RecordID" = ' . $ID . ' AND "ClassName" != \'' . $className . '\''); foreach ($search as $row) { array_push($versionsToDelete, array('RecordID' => $row['RecordID'], 'Version' => $row['Version'])); } } /* If versions to delete, start deleting */ if (count($versionsToDelete) > 0) { $affected_tables = array(); foreach ($subClasses as $subclass) { $versionsTable = $subclass . '_versions'; foreach ($versionsToDelete as $d) { DB::query('DELETE FROM "' . $versionsTable . '"' . ' WHERE "RecordID" = ' . $d['RecordID'] . ' AND "Version" = ' . $d['Version']); if (DB::affectedRows() == 1) { array_push($affected_tables, $versionsTable); } } } $this->vacuumTables($affected_tables); } }
public function importPass() { if (ImportHelper::is_a($this->targetClass, 'SiteTree')) { throw new InvalidArgumentException("Don't run TruncateImporter on a SiteTree class"); } // Check extensions if (!Object::has_extension($this->targetClass, 'LegacyDataObject')) { throw new Exception($this->targetClass . " does not have the LegacyDataObject extension"); } // Update remote table to include _ImportedID column $this->setupRemoteTable(); // Delete all existing records $existingRecords = DataObject::get($this->targetClass); $existingCount = $existingRecords->count(); // Get other records $query = $this->getRemoteObjectsQuery(); $remoteObjects = $this->task->query($query); $remoteCount = $remoteObjects->numRecords(); // Start $this->task->message(" * Replacing {$existingCount} records with {$remoteCount} ones"); // Truncate all tables $tables = ClassInfo::dataClassesFor($this->targetClass); foreach ($tables as $table) { DB::query('TRUNCATE "' . $table . '"'); } $this->task->message(" * " . count($tables) . " tables truncated"); // Add all objects $total = 0; foreach ($remoteObjects as $remoteObject) { // Show progress indicator $this->task->progress(++$total, $remoteCount); // Make new object $class = isset($remoteObject['ClassName']) && ImportHelper::is_a($remoteObject['ClassName'], $this->targetClass) ? $remoteObject['ClassName'] : $this->targetClass; // Direct copy data into the new object $localObject = $class::create(); foreach ($remoteObject as $field => $value) { $localObject->{$field} = $value; } $localObject->LegacyID = $remoteObject['ID']; $localObject->write(false, true); } // Bulk update remote table $conn = $this->task->getRemoteConnection(); $baseTable = $this->getRemoteBaseTable(); $conn->query('UPDATE "' . $baseTable . '" SET "_ImportedID" = "ID", "_ImportedDate" = NOW()'); // Done! $this->task->message(" * Result: {$total} added"); }
/** * @covers ClassInfo::dataClassesFor() */ public function testDataClassesFor() { $expect = array('ClassInfoTest_BaseDataClass' => 'ClassInfoTest_BaseDataClass', 'ClassInfoTest_HasFields' => 'ClassInfoTest_HasFields', 'ClassInfoTest_WithRelation' => 'ClassInfoTest_WithRelation', 'ClassInfoTest_WithCustomTable' => 'ClassInfoTest_WithCustomTable'); $classes = array('ClassInfoTest_BaseDataClass', 'ClassInfoTest_NoFields', 'ClassInfoTest_HasFields'); ClassInfo::reset_db_cache(); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[0])); ClassInfo::reset_db_cache(); $this->assertEquals($expect, ClassInfo::dataClassesFor(strtoupper($classes[0]))); ClassInfo::reset_db_cache(); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[1])); $expect = array('ClassInfoTest_BaseDataClass' => 'ClassInfoTest_BaseDataClass', 'ClassInfoTest_HasFields' => 'ClassInfoTest_HasFields'); ClassInfo::reset_db_cache(); $this->assertEquals($expect, ClassInfo::dataClassesFor($classes[2])); ClassInfo::reset_db_cache(); $this->assertEquals($expect, ClassInfo::dataClassesFor(strtolower($classes[2]))); }
public function getCMSFields() { $fields = parent::getCMSFields(); $types = ClassInfo::dataClassesFor('DataObject'); array_shift($types); asort($types); $source = array_combine($types, $types); $fields->replaceField('Title', new DropdownField('Title', _t('Solr.TYPE_CONFIG_TITLE', 'Data type'), $source)); if ($this->Title) { $keys = $this->getFieldsFor($this->Title); $vals = array('default' => _t('Solr.DEFAULT_MAPPING', 'Default type'), ':field_as' => _t('Solr.CASE_INSENSITIVE', 'Case Insensitive text'), ':field_ms' => _t('Solr.CASE_SENSITIVE', 'Case Sensitive, untokenised text')); $fields->replaceField('FieldMappings', new KeyValueField('FieldMappings', _t('Solr.FIELD_MAPPINGS', 'Indexed fields'), $keys, $vals, $this->FieldMappings)); } else { $fields->removeByName('FieldMappings'); } return $fields; }
/** * Gets the table which contains the sort field. * * @param DataList $list * @return string */ public function getSortTable(DataList $list) { $field = $this->getSortField(); if ($list instanceof ManyManyList) { $extra = $list->getExtraFields(); $table = $list->getJoinTable(); if ($extra && array_key_exists($field, $extra)) { return $table; } } $classes = ClassInfo::dataClassesFor($list->dataClass()); foreach ($classes as $class) { if (singleton($class)->hasOwnTableDatabaseField($field)) { return $class; } } throw new Exception("Couldn't find the sort field '{$field}'"); }
public function run($request) { HTTP::set_cache_age(0); increase_time_limit_to(); // This can be a time consuming task $classes = ClassInfo::dataClassesFor('DataObject'); $conn = DB::getConn(); $go = $request->getVar('go'); if (!$go) { echo 'Set ?go=1 to really delete the fields'; echo '<hr/>'; } foreach ($classes as $class) { $hasTable = ClassInfo::hasTable($class); if (!$hasTable) { continue; } $toDrop = array(); $fields = $class::database_fields($class); $list = $conn->fieldList($class); foreach ($list as $fieldName => $type) { if ($fieldName == 'ID') { continue; } if (!isset($fields[$fieldName])) { $toDrop[] = $fieldName; } } if (empty($toDrop)) { continue; } if ($go) { $this->dropColumns($class, $toDrop); DB::alteration_message("Dropped " . implode(',', $toDrop) . " for {$class}", "obsolete"); } else { DB::alteration_message("Would drop " . implode(',', $toDrop) . " for {$class}", "obsolete"); } } }
/** * Returns a filtered list of fields which could contain shortcodes. * * @param String * @return Array Map of class names to an array of field names on these classes. */ function getShortcodeFields($class) { $fields = array(); $ancestry = array_values(ClassInfo::dataClassesFor($class)); foreach ($ancestry as $ancestor) { if (ClassInfo::classImplements($ancestor, 'TestOnly')) { continue; } $ancFields = DataObject::custom_database_fields($ancestor); if ($ancFields) { foreach ($ancFields as $ancFieldName => $ancFieldSpec) { if (preg_match($this->fieldSpecRegex, $ancFieldSpec)) { if (!@$fields[$ancestor]) { $fields[$ancestor] = array(); } $fields[$ancestor][$ancFieldName] = $ancFieldSpec; } } } } return $fields; }
public function run($request) { $classes = ClassInfo::dataClassesFor('DataObject'); $conn = DB::getConn(); foreach ($classes as $class) { $fields = $class::database_fields($class); $list = $conn->fieldList($class); foreach ($list as $fieldName => $type) { if ($fieldName == 'ID') { continue; } if (strpos($fieldName, '_obsolete_') === 0) { $this->dropColumns($class, array($fieldName)); DB::alteration_message("Dropped {$fieldName}", "obsolete"); continue; } if (!isset($fields[$fieldName])) { $conn->dontRequireField($class, $fieldName); } } } }
/** * Get the name of the base table for this object */ public function baseTable() { $tableClasses = ClassInfo::dataClassesFor($this->class); return array_shift($tableClasses); }
public function getAlias($join_type = QueryAlias::INNER) { $join = array(); foreach ($this->alias as $alias) { if ($alias->getJoinType() !== $join_type) { continue; } $child = $alias->getName(); $has_many = Config::inst()->get(get_class($this->base_entity), 'has_many'); $class_name = ClassInfo::baseDataClass($this->base_entity); if (!is_null($has_many)) { $has_many_classes = array_flip($has_many); if (array_key_exists($child, $has_many_classes)) { $tableClasses = ClassInfo::dataClassesFor($child); $baseClass = array_shift($tableClasses); $joinField = $this->base_entity->getRemoteJoinField($has_many_classes[$child], 'has_many'); $join[$baseClass] = $baseClass . '.' . $joinField . ' = ' . $class_name . '.ID'; $this->addAndCondition(QueryCriteria::equal("{$baseClass}.ClassName", $child)); } } $has_many_many = Config::inst()->get(get_class($this->base_entity), 'many_many'); if (!is_null($has_many_many)) { $has_many_many_classes = array_flip($has_many_many); if (array_key_exists($child, $has_many_many_classes)) { $base_entity_name = get_class($this->base_entity); $component = $has_many_many_classes[$child]; $joinTable = "{$base_entity_name}_{$component}"; $parentField = $base_entity_name . "ID"; $childField = $child . "ID"; $join[$joinTable] = $joinTable . '.' . $parentField . ' = ' . $class_name . '.ID'; $join[$child] = $child . '.ID = ' . $joinTable . '.' . $childField; } } $has_one = Config::inst()->get(get_class($this->base_entity), 'has_one'); if (!is_null($has_one)) { if (array_key_exists($child, $has_one)) { $table = $has_one[$child]; $join[$table] = $has_one[$child] . '.ID = ' . $class_name . '.' . $child . 'ID'; } else { $has_one_classes = array_flip($has_one); if (array_key_exists($child, $has_one_classes)) { $join[$child] = $child . '.ID = ' . $class_name . '.' . $has_one_classes[$child] . 'ID'; } } } $belongs_many_many = Config::inst()->get(get_class($this->base_entity), 'belongs_many_many'); if (!is_null($belongs_many_many)) { $belongs_many_many_classes = array_flip($belongs_many_many); if (array_key_exists($child, $belongs_many_many_classes)) { $child_many_many = Config::inst()->get($child, 'many_many'); $child_many_many_classes = array_flip($child_many_many); $component_name = $child_many_many_classes[$class_name]; list($parentClass, $componentClass, $child_join_field, $join_field, $join_table) = Singleton($child)->many_many($component_name); $join[$join_table] = $join_table . '`.' . $join_field . ' = `' . $class_name . '`.ID'; $join[$child] = $child . '`.ID = `' . $join_table . '`.' . $child_join_field; } } if ($alias->hasSubAlias()) { $join = array_merge($join, $alias->subAlias($join_type)); } } return $join; }
function baseTable() { $record = $this->record; $classes = ClassInfo::dataClassesFor($record->ClassName); return array_pop($classes); }
/** * Ensure that if a query has an order by clause, those columns are present in the select. * * @param SQLQuery $query * @return null */ protected function ensureSelectContainsOrderbyColumns($query, $originalSelect = array()) { $tableClasses = ClassInfo::dataClassesFor($this->dataClass); $baseClass = array_shift($tableClasses); if ($orderby = $query->getOrderBy()) { $newOrderby = array(); $i = 0; foreach ($orderby as $k => $dir) { $newOrderby[$k] = $dir; // don't touch functions in the ORDER BY or public function calls // selected as fields if (strpos($k, '(') !== false) { continue; } $col = str_replace('"', '', trim($k)); $parts = explode('.', $col); // Pull through SortColumn references from the originalSelect variables if (preg_match('/_SortColumn/', $col)) { if (isset($originalSelect[$col])) { $query->selectField($originalSelect[$col], $col); } continue; } if (count($parts) == 1) { $databaseFields = DataObject::database_fields($baseClass); // database_fields() doesn't return ID, so we need to // manually add it here $databaseFields['ID'] = true; if (isset($databaseFields[$parts[0]])) { $qualCol = "\"{$baseClass}\".\"{$parts[0]}\""; } else { $qualCol = "\"{$parts['0']}\""; } // remove original sort unset($newOrderby[$k]); // add new columns sort $newOrderby[$qualCol] = $dir; // To-do: Remove this if block once SQLQuery::$select has been refactored to store getSelect() // format internally; then this check can be part of selectField() $selects = $query->getSelect(); if (!isset($selects[$col]) && !in_array($qualCol, $selects)) { $query->selectField($qualCol); } } else { $qualCol = '"' . implode('"."', $parts) . '"'; if (!in_array($qualCol, $query->getSelect())) { unset($newOrderby[$k]); $newOrderby["\"_SortColumn{$i}\""] = $dir; $query->selectField($qualCol, "_SortColumn{$i}"); $i++; } } } $query->setOrderBy($newOrderby); } }
/** * Returns the base class name of the owner used for SQL * * @return string */ public function getBaseClassName() { $tableClasses = ClassInfo::dataClassesFor($this->owner->class); $baseClassName = array_shift($tableClasses); return $baseClassName; }
/** * Get the parent of this class. * @return DataObject */ public function getParent($filter = null) { if ($p = $this->owner->__get("ParentID")) { $tableClasses = ClassInfo::dataClassesFor($this->owner->class); $baseClass = array_shift($tableClasses); return DataObject::get_one($this->owner->class, array(array("\"{$baseClass}\".\"ID\"" => $p), $filter)); } }
/** * Get the parent of this class. * @return DataObject */ public function getParent($filter = '') { if ($p = $this->owner->__get("ParentID")) { $tableClasses = ClassInfo::dataClassesFor($this->owner->class); $baseClass = array_shift($tableClasses); $filter .= $filter ? " AND " : "" . "\"{$baseClass}\".\"ID\" = {$p}"; return DataObject::get_one($this->owner->class, $filter); } }
/** * Checks the database is in a state to perform security checks. * See {@link DatabaseAdmin->init()} for more information. * * @return bool */ public static function database_is_ready() { // Used for unit tests if (self::$force_database_is_ready !== NULL) { return self::$force_database_is_ready; } if (self::$database_is_ready) { return self::$database_is_ready; } $requiredTables = ClassInfo::dataClassesFor('Member'); $requiredTables[] = 'Group'; $requiredTables[] = 'Permission'; foreach ($requiredTables as $table) { // Skip test classes, as not all test classes are scaffolded at once if (is_subclass_of($table, 'TestOnly')) { continue; } // if any of the tables aren't created in the database if (!ClassInfo::hasTable($table)) { return false; } // HACK: DataExtensions aren't applied until a class is instantiated for // the first time, so create an instance here. singleton($table); // if any of the tables don't have all fields mapped as table columns $dbFields = DB::field_list($table); if (!$dbFields) { return false; } $objFields = DataObject::database_fields($table, false); $missingFields = array_diff_key($objFields, $dbFields); if ($missingFields) { return false; } } self::$database_is_ready = true; return true; }