/**
  * @param DataObject $owner
  * @param string $association_name
  * @param string $inversed_by
  */
 public function __construct(DataObject $owner, $association_name, $inversed_by = null, QueryObject $target_query = null)
 {
     $this->owner = $owner;
     $this->association_name = $association_name;
     $this->inversed_by = $inversed_by;
     $this->target_class = $this->owner->has_one($association_name);
     $this->snapshot = $this->owner->getComponent($this->association_name);
     $this->target = $this->snapshot;
     if (is_null($target_query)) {
         $target_query = new QueryObject();
     }
     $this->target_query = $target_query;
     UnitOfWork::getInstance()->loadMany2OneAssociation($this);
 }
 public function saveInto(DataObject $record)
 {
     $fieldName = $this->name . 'ID';
     $hasOnes = $record->has_one($this->name);
     if (!$hasOnes) {
         $hasOnes = $record->has_one($fieldName);
     }
     // assume that the file is connected via a has-one
     if (!$hasOnes || !isset($_FILES[$this->name]) || !$_FILES[$this->name]['name']) {
         return;
     }
     $file = new File();
     $file->loadUploaded($_FILES[$this->name]);
     $record->{$fieldName} = $file->ID;
 }
 /**
  * Recursivly search for a PlaceholderImage.
  *
  * @param DataObject $object
  * @return Image | null
  */
 protected function getPlaceholderImageRecursive(DataObject $object)
 {
     if ($object->has_one('PlaceholderImage')) {
         $image = $object->getComponent('PlaceholderImage');
         if ($image->exists()) {
             return $image;
         }
     }
     $parentObject = $object->hasMethod('Parent') ? $object->Parent() : null;
     return isset($parentObject) && $parentObject->exists() ? $this->getPlaceholderImageRecursive($parentObject) : null;
 }
 public function __construct(DataObject $onObject, $relationName, $targetFragment = 'before')
 {
     $this->onObject = $onObject;
     $this->relationName = $relationName;
     $hasOne = $onObject->has_one($relationName);
     if (!$hasOne) {
         user_error('Unable to find a has_one relation named ' . $relationName . ' on ' . $onObject->ClassName, E_USER_WARNING);
     }
     $this->targetObject = $hasOne;
     parent::__construct(false, $targetFragment);
 }
 /**
  * Return a formfield for the extra field column or an edit button for the actions column
  * 
  * @param  GridField $gridField
  * @param  DataObject $record - Record displayed in this row
  * @param  string $columnName
  * @return string - HTML for the column. Return NULL to skip.
  */
 public function getColumnContent($gridField, $record, $columnName)
 {
     Requirements::javascript('GridFieldAddOns/javascript/GridFieldEditableCells.js');
     Requirements::css('GridFieldAddOns/css/GridFieldEditableCells.css');
     $name = "{$gridField->Name}_EditableCell[{$record->ID}][{$columnName}]";
     $value = $record->has_one($columnName) ? $record->{$columnName . 'ID'} : $record->{$columnName};
     $field = clone $this->fields->fieldByName($columnName);
     $field->setName($name);
     $field->setValue($value);
     return $field->Field();
 }
Example #6
0
 public function scaffoldFormField($title = null, $params = null)
 {
     $relationName = substr($this->name, 0, -2);
     $hasOneClass = $this->object->has_one($relationName);
     if ($hasOneClass && singleton($hasOneClass) instanceof Image) {
         $field = new UploadField($relationName, $title);
         $field->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
     } elseif ($hasOneClass && singleton($hasOneClass) instanceof File) {
         $field = new UploadField($relationName, $title);
     } else {
         $titleField = singleton($hasOneClass)->hasField('Title') ? "Title" : "Name";
         $list = DataList::create($hasOneClass);
         // Don't scaffold a dropdown for large tables, as making the list concrete
         // might exceed the available PHP memory in creating too many DataObject instances
         if ($list->count() < 100) {
             $field = new DropdownField($this->name, $title, $list->map('ID', $titleField));
             $field->setEmptyString(' ');
         } else {
             $field = new NumericField($this->name, $title);
         }
     }
     return $field;
 }
 public function scaffoldFormField($title = null, $params = null)
 {
     $relationName = substr($this->name, 0, -2);
     $hasOneClass = $this->object->has_one($relationName);
     if ($hasOneClass && singleton($hasOneClass) instanceof Image) {
         if (isset($params['ajaxSafe']) && $params['ajaxSafe']) {
             $field = new ImageField($relationName, $title, $this->value);
         } else {
             $field = new SimpleImageField($relationName, $title, $this->value);
         }
     } elseif ($hasOneClass && singleton($hasOneClass) instanceof File) {
         if (isset($params['ajaxSafe']) && $params['ajaxSafe']) {
             $field = new FileIFrameField($relationName, $title, $this->value);
         } else {
             $field = new FileField($relationName, $title, $this->value);
         }
     } else {
         $titleField = singleton($hasOneClass)->hasField('Title') ? "Title" : "Name";
         $map = new SQLMap(singleton($hasOneClass)->extendedSQL(), "ID", $titleField);
         $field = new DropdownField($this->name, $title, $map, null, null, ' ');
     }
     return $field;
 }
 public function __construct(DataObject $controller, $name, $title = null, $className = null, $source = array(), $addTitle = null, $defaultsProperties = array(), $form = null)
 {
     $hasOne = false;
     if (!$title) {
         $this->title = self::name_to_label($name);
     }
     if (!$className) {
         if (substr($name, -2) == 'ID') {
             $name = substr($name, 0, -2);
         }
         if (!($hasOne = $className = $controller->has_one($name)) && !($className = $controller->belongs_to($name)) && (($settings = $controller->has_many($name)) || ($settings = $controller->many_many($name)))) {
             if (is_array($settings)) {
                 $className = $settings[1];
             } else {
                 $className = $settings;
             }
             $this->fieldType = 'CheckboxSetField';
         }
         if (!$className) {
             trigger_error('Couldn\'t determine class type from field name "' . $name . '". Please define the class name.');
         }
         if ($hasOne) {
             $name .= 'ID';
         }
     } else {
         if ($rels = $controller->has_many() + $controller->many_many()) {
             foreach ($rels as $rel => $class) {
                 if ($class == $className || ClassInfo::is_subclass_of($class, $className)) {
                     $this->fieldType = 'CheckboxSetField';
                     break;
                 }
             }
         }
     }
     if (!class_exists($className)) {
         trigger_error($className . ' class doesn\'t exist');
     }
     $this->setDefaults($defaultsProperties);
     $this->className = $className;
     $this->controller = $controller;
     parent::__construct($name, $title, $source, null, $form);
 }
	/**
	 * Gets the form fields as defined through the metadata
	 * on {@link $obj} and the custom parameters passed to FormScaffolder.
	 * Depending on those parameters, the fields can be used in ajax-context,
	 * contain {@link TabSet}s etc.
	 * 
	 * @return FieldSet
	 */
	public function getFieldSet() {
		$fields = new FieldSet();
		
		// tabbed or untabbed
		if($this->tabbed) {
			$fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
			$mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
		}
		
		// add database fields
		foreach($this->obj->db() as $fieldName => $fieldType) {
			if($this->restrictFields && !in_array($fieldName, $this->restrictFields)) continue;
			
			// @todo Pass localized title
			if($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
				$fieldClass = $this->fieldClasses[$fieldName];
				$fieldObject = new $fieldClass($fieldName);
			} else {
				$fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
			}
			$fieldObject->setTitle($this->obj->fieldLabel($fieldName));
			if($this->tabbed) {
				$fields->addFieldToTab("Root.Main", $fieldObject);
			} else {
				$fields->push($fieldObject);
			}
		}
		
		// add has_one relation fields
		if($this->obj->has_one()) {
			foreach($this->obj->has_one() as $relationship => $component) {
				if($this->restrictFields && !in_array($relationship, $this->restrictFields)) continue;
				$hasOneField = $this->obj->dbObject("{$relationship}ID")->scaffoldFormField(null, $this->getParamsArray());
				$hasOneField->setTitle($this->obj->fieldLabel($relationship));
				if($this->tabbed) {
					$fields->addFieldToTab("Root.Main", $hasOneField);
				} else {
					$fields->push($hasOneField);
				}
			}
		}
		
		// only add relational fields if an ID is present
		if($this->obj->ID) {
			// add has_many relation fields
			if($this->obj->has_many() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) {
				foreach($this->obj->has_many() as $relationship => $component) {
					if($this->tabbed) {
						$relationTab = $fields->findOrMakeTab(
							"Root.$relationship", 
							$this->obj->fieldLabel($relationship)
						);
					}
					$relationshipFields = singleton($component)->summaryFields();
					$foreignKey = $this->obj->getComponentJoinField($relationship);
					$ctf = new ComplexTableField(
						$this,
						$relationship,
						$component,
						$relationshipFields,
						"getCMSFields", 
						"$foreignKey = " . $this->obj->ID
					);
					$ctf->setPermissions(TableListField::permissions_for_object($component));
					if($this->tabbed) {
						$fields->addFieldToTab("Root.$relationship", $ctf);
					} else {
						$fields->push($ctf);
					}
				}
			}

			if($this->obj->many_many() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) {
				foreach($this->obj->many_many() as $relationship => $component) {
					if($this->tabbed) {
						$relationTab = $fields->findOrMakeTab(
							"Root.$relationship", 
							$this->obj->fieldLabel($relationship)
						);
					}

					$relationshipFields = singleton($component)->summaryFields();
					$filterWhere = $this->obj->getManyManyFilter($relationship, $component);
					$filterJoin = $this->obj->getManyManyJoin($relationship, $component);
					$ctf =  new ComplexTableField(
						$this,
						$relationship,
						$component,
						$relationshipFields,
						"getCMSFields", 
						$filterWhere,
						'', 
						$filterJoin
					);
					$ctf->setPermissions(TableListField::permissions_for_object($component));
					$ctf->popupClass = "ScaffoldingComplexTableField_Popup";
					if($this->tabbed) {
						$fields->addFieldToTab("Root.$relationship", $ctf);
					} else {
						$fields->push($ctf);
					}
				}
			}
		}
		
		return $fields;
	}
 /**
  * @param ProxyObject $proxy
  * @param DataObject $dataObject
  * @param $selectFields
  */
 private function setGroups(ProxyObject $proxy, DataObject $dataObject, $selectFields)
 {
     if (empty($this->groups)) {
         return;
     }
     $parentObject = null;
     foreach ($this->groups as $group) {
         $fields = explode('.', $group);
         if (count($fields) !== 2) {
             // TODO move to validation in ->group()
             error_log('WARNING: Group must be of format [has_one].[has_one->FieldName]');
             break;
         }
         $class = $dataObject->has_one($fields[0]);
         if (!$class) {
             error_log('WARNING: Group is not a valid has_one');
             break;
         }
         if (!isset($selectFields[$group])) {
             error_log('WARNING: Group must have a corresponding column in select');
             break;
         }
         $values = $this->getProxyFieldValues($proxy, $selectFields[$group]);
         if (empty($values)) {
             // warning
             error_log('WARNING: Group does not have a value');
             break;
         }
         $field = $fields[1];
         $value = $values[0];
         $groupObject = $class::get()->filter(array($field => $value))->first();
         if (!$groupObject) {
             $groupObject = new $class();
             $groupObject->{$field} = $value;
             $this->write($groupObject);
         }
         $this->savedRecords[$class][] = $groupObject->ID;
         // add data object to group
         $hasMany = $groupObject->has_many();
         $hasMany = array_flip($hasMany);
         if (isset($hasMany[$dataObject->ClassName])) {
             $collection = $hasMany[$dataObject->ClassName];
             $groupObject->{$collection}()->add($dataObject);
         }
         // set parent group, when multiple groups
         if ($parentObject) {
             $hasMany = $parentObject->has_many();
             $hasMany = array_flip($hasMany);
             if (isset($hasMany[$groupObject->ClassName])) {
                 $collection = $hasMany[$groupObject->ClassName];
                 $parentObject->{$collection}()->add($groupObject);
             }
         }
         $parentObject = $groupObject;
     }
 }
 /**
  * @param DataObject $obj
  * @param array $params
  * @param int|array $sort
  * @param int|array $limit
  * @param string $relationName
  * @return SQLQuery|boolean
  */
 protected function getObjectRelationQuery($obj, $params, $sort, $limit, $relationName)
 {
     if ($obj->hasMethod("{$relationName}Query")) {
         // @todo HACK Switch to ComponentSet->getQuery() once we implement it (and lazy loading)
         $query = $obj->{"{$relationName}Query"}(null, $sort, null, $limit);
         $relationClass = $obj->{"{$relationName}Class"}();
     } elseif ($relationClass = $obj->many_many($relationName)) {
         // many_many() returns different notation
         $relationClass = $relationClass[1];
         $query = $obj->getManyManyComponentsQuery($relationName);
     } elseif ($relationClass = $obj->has_many($relationName)) {
         $query = $obj->getComponentsQuery($relationName);
     } elseif ($relationClass = $obj->has_one($relationName)) {
         $query = null;
     } else {
         return false;
     }
     // get all results
     return $this->getSearchQuery($relationClass, $params, $sort, $limit, $query);
 }
Example #12
0
 public function saveInto(DataObject $record)
 {
     if (!isset($_FILES[$this->name])) {
         return false;
     }
     $fileClass = File::get_class_for_file_extension(pathinfo($_FILES[$this->name]['name'], PATHINFO_EXTENSION));
     if ($this->relationAutoSetting) {
         // assume that the file is connected via a has-one
         $hasOnes = $record->has_one($this->name);
         // try to create a file matching the relation
         $file = is_string($hasOnes) ? Object::create($hasOnes) : new $fileClass();
     } else {
         $file = new $fileClass();
     }
     $this->upload->loadIntoFile($_FILES[$this->name], $file, $this->folderName);
     if ($this->upload->isError()) {
         return false;
     }
     $file = $this->upload->getFile();
     if ($this->relationAutoSetting) {
         if (!$hasOnes) {
             return false;
         }
         // save to record
         $record->{$this->name . 'ID'} = $file->ID;
     }
 }
 /**
  * Gets the form fields as defined through the metadata
  * on {@link $obj} and the custom parameters passed to FormScaffolder.
  * Depending on those parameters, the fields can be used in ajax-context,
  * contain {@link TabSet}s etc.
  *
  * @return FieldList
  */
 public function getFieldList()
 {
     $fields = new FieldList();
     // tabbed or untabbed
     if ($this->tabbed) {
         $fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
         $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
     }
     // add database fields
     foreach ($this->obj->db() as $fieldName => $fieldType) {
         if ($this->restrictFields && !in_array($fieldName, $this->restrictFields)) {
             continue;
         }
         // @todo Pass localized title
         if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
             $fieldClass = $this->fieldClasses[$fieldName];
             $fieldObject = new $fieldClass($fieldName);
         } else {
             $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
         }
         $fieldObject->setTitle($this->obj->fieldLabel($fieldName));
         if ($this->tabbed) {
             $fields->addFieldToTab("Root.Main", $fieldObject);
         } else {
             $fields->push($fieldObject);
         }
     }
     // add has_one relation fields
     if ($this->obj->has_one()) {
         foreach ($this->obj->has_one() as $relationship => $component) {
             if ($this->restrictFields && !in_array($relationship, $this->restrictFields)) {
                 continue;
             }
             $fieldName = $component === 'DataObject' ? $relationship : "{$relationship}ID";
             if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) {
                 $fieldClass = $this->fieldClasses[$fieldName];
                 $hasOneField = new $fieldClass($fieldName);
             } else {
                 $hasOneField = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray());
             }
             if (empty($hasOneField)) {
                 continue;
             }
             // Allow fields to opt out of scaffolding
             $hasOneField->setTitle($this->obj->fieldLabel($relationship));
             if ($this->tabbed) {
                 $fields->addFieldToTab("Root.Main", $hasOneField);
             } else {
                 $fields->push($hasOneField);
             }
         }
     }
     // only add relational fields if an ID is present
     if ($this->obj->ID) {
         // add has_many relation fields
         if ($this->obj->has_many() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) {
             foreach ($this->obj->has_many() as $relationship => $component) {
                 if ($this->tabbed) {
                     $relationTab = $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship));
                 }
                 $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'GridField';
                 $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create());
                 if ($this->tabbed) {
                     $fields->addFieldToTab("Root.{$relationship}", $grid);
                 } else {
                     $fields->push($grid);
                 }
             }
         }
         if ($this->obj->many_many() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) {
             foreach ($this->obj->many_many() as $relationship => $component) {
                 if ($this->tabbed) {
                     $relationTab = $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship));
                 }
                 $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'GridField';
                 $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create());
                 if ($this->tabbed) {
                     $fields->addFieldToTab("Root.{$relationship}", $grid);
                 } else {
                     $fields->push($grid);
                 }
             }
         }
     }
     return $fields;
 }
 /**
  * @param DataObject $obj
  * @param array $params
  * @param int|array $sort
  * @param int|array $limit
  * @param string $relationName
  * @return SQLQuery|boolean
  */
 protected function getObjectRelationQuery($obj, $params, $sort, $limit, $relationName)
 {
     // The relation method will return a DataList, that getSearchQuery subsequently manipulates
     if ($obj->hasMethod($relationName)) {
         if ($relationClass = $obj->has_one($relationName)) {
             $joinField = $relationName . 'ID';
             $list = DataList::create($relationClass)->byIDs(array($obj->{$joinField}));
         } else {
             $list = $obj->{$relationName}();
         }
         $apiAccess = singleton($list->dataClass())->stat('api_access');
         if (!$apiAccess) {
             return false;
         }
         return $this->getSearchQuery($list->dataClass(), $params, $sort, $limit, $list);
     }
 }
Example #15
0
 public function saveInto(DataObject $record)
 {
     if (!isset($_FILES[$this->name])) {
         return false;
     }
     if ($this->relationAutoSetting) {
         // assume that the file is connected via a has-one
         $hasOnes = $record->has_one($this->name);
         // try to create a file matching the relation
         $file = is_string($hasOnes) ? Object::create($hasOnes) : new File();
     } else {
         $file = new File();
     }
     $this->upload->setAllowedExtensions($this->allowedExtensions);
     $this->upload->setAllowedMaxFileSize($this->allowedMaxFileSize);
     $this->upload->loadIntoFile($_FILES[$this->name], $file, $this->folderName);
     if ($this->upload->isError()) {
         return false;
     }
     $file = $this->upload->getFile();
     if ($this->relationAutoSetting) {
         if (!$hasOnes) {
             return false;
         }
         // save to record
         $record->{$this->name . 'ID'} = $file->ID;
     }
 }
 /**
  * Saves the form data into a record. The {@see $name} property of the object is used
  * to determine the foreign key on the record, e.g. "SomeFileID".
  *
  * @param DataObject $record The record associated with the parent form
  */
 public function saveInto(DataObject $record)
 {
     if (isset($_REQUEST[$this->name . "ID"])) {
         $file_id = (int) $_REQUEST[$this->name . "ID"];
         if ($file_class = $record->has_one($this->name)) {
             if ($f = DataObject::get_by_id("File", $file_id)) {
                 if ($f->ClassName != $file_class) {
                     $file = $f->newClassInstance($file_class);
                     $file->write();
                 }
             }
         }
         $record->{$this->name . 'ID'} = $_REQUEST[$this->name . "ID"];
     }
 }
 /**
  * @param DataObject $entity
  * @param             $association_name
  * @param null $inversed_by
  * @param QueryObject $target_query
  * @return bool|Many2OneAssociation
  * @throws Exception
  */
 public function getMany2OneAssociation(DataObject $entity, $association_name, $inversed_by = null, QueryObject $target_query = null)
 {
     $class_name = $entity->has_one($association_name);
     if (!$class_name) {
         throw new Exception(sprintf("entity %s has not an many-to-one association called %s", get_class($entity), $association_name));
     }
     $old = UnitOfWork::getInstance()->getMany2OneAssociation($entity, $association_name);
     if ($old) {
         return $old;
     }
     return new Many2OneAssociation($entity, $association_name, $inversed_by, $target_query);
 }
 /**
  * Update all has_ones that are linked to assets
  *
  * @param \DataObject $localObject
  * @param \ArrayData $remoteObject
  * @return null
  */
 protected function updateLocaleAssetRelations(\DataObject $localObject, \ArrayData $remoteObject)
 {
     // Now update all has_one => file relations
     $changed = false;
     $relations = $localObject->has_one();
     if (empty($relations)) {
         $this->task->message(" ** No has_ones on {$localObject->Title}", 2);
         return;
     }
     foreach ($relations as $relation => $class) {
         $this->task->message(" *** Checking relation name {$relation}", 3);
         // Link file
         if (!ImportHelper::is_a($class, 'File')) {
             $this->task->message(" **** {$relation} is not a File", 4);
             continue;
         }
         // Don't link folders
         if (ImportHelper::is_a($class, 'Folder')) {
             $this->task->message(" **** {$relation} is a folder", 4);
             continue;
         }
         // No need to import if found in a previous step
         $field = $relation . "ID";
         if ($localObject->{$field}) {
             $this->task->message(" **** {$relation} already has value {$localObject->{$field}} on local object", 4);
             continue;
         }
         // If the remote object doesn't have this field then can also skip it
         $remoteFileID = intval($remoteObject->{$field});
         if (empty($remoteFileID)) {
             $this->task->message(" **** {$relation} has no value on remote object", 4);
             continue;
         }
         // Find remote file with this ID
         $remoteFile = $this->findRemoteFile(array(sprintf('"ID" = %d', intval($remoteFileID))));
         if (!$remoteFile) {
             $this->task->error("Could not find {$relation} file with id {$remoteFileID}");
             continue;
         }
         // Ensure that this file has a valid name
         if (!$this->isValidFile($remoteFile->Name)) {
             $this->task->error("Remote {$relation} file does not have a valid name '" . $remoteFile->Name . "'");
             continue;
         }
         // Copy file to filesystem and save
         $localFile = $this->findOrImportFile($remoteFile);
         if (!$localFile) {
             $this->task->error("Failed to import {$relation} file '" . $remoteFile->Name . "'");
             continue;
         }
         // Save new file
         $changed = true;
         $this->task->message(" *** {$relation} assigned local value {$localFile->ID}", 3);
         $localObject->{$field} = $localFile->ID;
     }
     if ($changed) {
         $localObject->write();
     } else {
         $this->task->message(" ** No changes made to relations on {$localObject->Title}", 2);
     }
 }