/** * The process to automatically construct data object output configurations, executed on project build. */ public function requireDefaultRecords() { parent::requireDefaultRecords(); // Grab the list of data objects that have been completely removed. foreach (DB::getConn()->tableList() as $table) { // Delete existing output configurations for these data objects. if (!class_exists($table)) { $existing = DataObjectOutputConfiguration::get_one('DataObjectOutputConfiguration', "IsFor = '" . Convert::raw2sql($table) . "'"); $this->deleteConfiguration($table, $existing); } } // Grab the list of all data object types, along with any inclusions/exclusions defined. $objects = ClassInfo::subclassesFor('DataObject'); $inclusions = self::$custom_inclusions; $exclusions = array_unique(array_merge(self::$exclusions, self::$custom_exclusions)); // Check existing output configurations for these data objects. foreach ($objects as $object) { $existing = DataObjectOutputConfiguration::get_one('DataObjectOutputConfiguration', "IsFor = '" . Convert::raw2sql($object) . "'"); // Delete existing output configurations for invalid data objects, or for those excluded. if ($existing && (self::$disabled || get_parent_class($object) !== 'DataObject' || ClassInfo::classImplements($object, 'TestOnly') || count($inclusions) > 0 && !in_array($object, $inclusions) || count($inclusions) === 0 && in_array($object, $exclusions))) { $this->deleteConfiguration($object, $existing); } else { if (!$existing && !self::$disabled && get_parent_class($object) === 'DataObject' && !ClassInfo::classImplements($object, 'TestOnly') && (count($inclusions) > 0 && in_array($object, $inclusions) || count($inclusions) === 0 && !in_array($object, $exclusions))) { $this->addConfiguration($object); } } } }
/** * Recursively return the relationships for a given data object map. */ private function recursiveRelationships(&$object, $attributeVisibility = false, $cache = array()) { $output = array(); // Cache relationship data objects to prevent infinite recursion. if (!in_array("{$object['ClassName']} {$object['ID']}", $cache)) { $cache[] = "{$object['ClassName']} {$object['ID']}"; foreach ($object as $attribute => $value) { if ($attribute !== 'ClassName' && $attribute !== 'RecordClassName') { // Grab the name of a relationship. $relationship = substr($attribute, strlen($attribute) - 2) === 'ID' && strlen($attribute) > 2 ? substr($attribute, 0, -2) : null; if ($relationship && ($relationObject = DataObject::get_by_id($object['ClassName'], $object['ID'])) && $relationObject->hasMethod($relationship) && $value != 0) { // Grab the relationship. $relationObject = $relationObject->{$relationship}(); // Make sure recursive relationships are enabled. if (!$this->recursiveRelationships) { $output[$relationship] = array($relationObject->ClassName => array('ID' => (string) $relationObject->ID)); continue; } $temporaryMap = $relationObject->toMap(); if ($attributeVisibility) { // Grab the attribute visibility. $class = is_subclass_of($relationObject->ClassName, 'SiteTree') ? 'SiteTree' : (is_subclass_of($relationObject->ClassName, 'File') ? 'File' : $relationObject->ClassName); $relationConfiguration = DataObjectOutputConfiguration::get_one('DataObjectOutputConfiguration', "IsFor = '" . Convert::raw2sql($class) . "'"); $relationVisibility = $relationConfiguration && $relationConfiguration->APIwesomeVisibility ? explode(',', $relationConfiguration->APIwesomeVisibility) : null; $columns = array(); foreach (ClassInfo::subclassesFor($class) as $subclass) { // Prepend the table names. $subclassColumns = array(); foreach (DataObject::database_fields($subclass) as $column => $type) { $subclassColumns["{$subclass}.{$column}"] = $type; } $columns = array_merge($columns, $subclassColumns); } array_shift($columns); // Make sure this relationship has visibility customisation. if (is_null($relationVisibility) || count($relationVisibility) !== count($columns) || !in_array('1', $relationVisibility)) { $output[$relationship] = array($relationObject->ClassName => array('ID' => (string) $relationObject->ID)); continue; } // Grab all data object visible attributes. $select = array('ClassName' => $relationObject->ClassName, 'ID' => $relationObject->ID); $iteration = 0; foreach ($columns as $relationshipAttribute => $relationshipType) { if (isset($relationVisibility[$iteration]) && $relationVisibility[$iteration]) { $split = explode('.', $relationshipAttribute); $relationshipAttribute = count($split) === 2 ? $split[1] : $relationshipAttribute; if (isset($temporaryMap[$relationshipAttribute]) && $temporaryMap[$relationshipAttribute]) { // Retrieve the relationship value, and compose any asset file paths. $relationshipValue = $temporaryMap[$relationshipAttribute]; $select[$relationshipAttribute] = (strpos(strtolower($relationshipAttribute), 'file') !== false || strpos(strtolower($relationshipAttribute), 'image') !== false) && strpos($relationshipValue, 'assets/') !== false ? Director::absoluteURL($relationshipValue) : (is_integer($relationshipValue) ? (string) $relationshipValue : $relationshipValue); } } $iteration++; } } else { $select = $temporaryMap; } // Check the corresponding relationship. $output[$relationship] = array($relationObject->ClassName => $this->recursiveRelationships($select, $attributeVisibility, $cache)); } else { // Compose any asset file paths. $output[$attribute] = (strpos(strtolower($attribute), 'file') !== false || strpos(strtolower($attribute), 'image') !== false) && strpos($value, 'assets/') !== false ? Director::absoluteURL($value) : (is_integer($value) ? (string) $value : $value); } } } } else { // This relationship has previously been cached. $output['ID'] = $object['ID']; } // Return the visible relationship attributes. return $output; }