diff --git a/api/RestfulServer.php b/api/RestfulServer.php index 5f437ea9f..25fd6d019 100644 --- a/api/RestfulServer.php +++ b/api/RestfulServer.php @@ -38,8 +38,10 @@ class RestfulServer extends Controller { ContentNegotiator::disable(); $requestMethod = $_SERVER['REQUEST_METHOD']; + + if(!isset($this->urlParams['ClassName'])) return $this->notFound(); $className = $this->urlParams['ClassName']; - $id = $this->urlParams['ID']; + $id = (isset($this->urlParams['ID'])) ? $this->urlParams['ID'] : null; switch($requestMethod) { case 'GET': diff --git a/core/ViewableData.php b/core/ViewableData.php index 3789b3a47..0d52b29b6 100644 --- a/core/ViewableData.php +++ b/core/ViewableData.php @@ -334,7 +334,11 @@ class ViewableData extends Object implements IteratorAggregate { if($constructor) { $fieldObj = eval($constructor); - $fieldObj->setVal($val); + if($this->hasMethod('getAllFields')) { + $fieldObj->setVal($val, $this->getAllFields()); + } else { + $fieldObj->setVal($val); + } } } diff --git a/core/model/DataObject.php b/core/model/DataObject.php index 971e7c2b6..1c5ea2f10 100644 --- a/core/model/DataObject.php +++ b/core/model/DataObject.php @@ -601,12 +601,15 @@ class DataObject extends ViewableData implements DataObjectInterface { } // Divvy up field saving into a number of database manipulations + $manipulation = array(); if(isset($ancestry) && is_array($ancestry)) { foreach($ancestry as $idx => $class) { $classSingleton = singleton($class); - foreach($this->record as $fieldName => $value) { + foreach($this->record as $fieldName => $fieldValue) { if(isset($this->changed[$fieldName]) && $this->changed[$fieldName] && $fieldType = $classSingleton->fieldExists($fieldName)) { - $manipulation[$class]['fields'][$fieldName] = $value ? ("'" . addslashes($value) . "'") : singleton($fieldType)->nullValue(); + $fieldObj = $this->obj($fieldName); + if(!isset($manipulation[$class])) $manipulation[$class] = array(); + if($fieldObj) $fieldObj->writeToManipulation($manipulation[$class]); } } @@ -1487,7 +1490,7 @@ class DataObject extends ViewableData implements DataObjectInterface { $constructor = $helperPair['castingHelper']; if($obj = eval($constructor)) { - $obj->setVal($this->$fieldName); + $obj->setVal($this->$fieldName, $this->record); } return $obj; @@ -1562,6 +1565,11 @@ class DataObject extends ViewableData implements DataObjectInterface { foreach($tableClasses as $tableClass) { $query->from[$tableClass] = "LEFT JOIN `$tableClass` ON `$tableClass`.ID = `$baseClass`.ID"; $query->select[] = "`$tableClass`.*"; + // ask each $db field on the specific table for alterations to the query + $uninheritedDbFields = singleton($tableClass)->uninherited('db',true); + if($uninheritedDbFields) foreach($uninheritedDbFields as $fieldName => $fieldType) { + singleton($tableClass)->obj($fieldName)->addToQuery($query); + } } } $query->select[] = "`$baseClass`.ID"; diff --git a/core/model/fieldtypes/DBField.php b/core/model/fieldtypes/DBField.php index 25c5a1774..ead6c510e 100644 --- a/core/model/fieldtypes/DBField.php +++ b/core/model/fieldtypes/DBField.php @@ -38,14 +38,62 @@ abstract class DBField extends ViewableData { return $dbField; } - function setVal($value) { + function setVal($value, $record = null) { return $this->setValue($value); } - function setValue($value) { + /** + * Set the value on the field. + * Optionally takes the whole record as an argument, + * to pick other values. + * + * @param mixed $value + * @param array $record + */ + function setValue($value, $record = null) { $this->value = $value; } + /** + * Determines if the field has a value which + * is not considered to be 'null' in + * a database context. + * + * @return boolean + */ + function hasValue() { + return ($this->value); + } + + /** + * Prepare the current field for usage in a + * database-manipulation (works on a manipulation reference). + * + * Make value safe for insertion into + * a SQL SET statement by applying addslashes() - + * can also be used to apply + * special SQL-commands to the raw value + * (e.g. for GIS functionality). + * + * @param array $manipulation + */ + function writeToManipulation(&$manipulation) { + $manipulation['fields'][$this->name] = $this->hasValue() ? "'" . addslashes($this->value) . "'" : $this->nullValue(); + } + + /** + * Add custom query parameters for this field, + * mostly SELECT statements for multi-value fields. + * + * By default, the ORM layer does a + * SELECT .* which + * gets you the default representations + * of all columns. + * + * @param Query $query + */ + function addToQuery(&$query) {} + function setTable($tableName) { $this->tableName = $tableName; } diff --git a/core/model/fieldtypes/Double.php b/core/model/fieldtypes/Double.php index 2225925b1..b96c85677 100644 --- a/core/model/fieldtypes/Double.php +++ b/core/model/fieldtypes/Double.php @@ -1,7 +1,6 @@ tableName, $this->name, "mediumtext character set utf8 collate utf8_general_ci"); } + function hasValue() { + return ($this->value || $this->value == '0'); + } + //useed for search results show only limited contents function LimitWordCount($numWords = 26) { $this->value = Convert::xml2raw($this->value); diff --git a/core/model/fieldtypes/Varchar.php b/core/model/fieldtypes/Varchar.php index d5c9b66fd..52c2b8d24 100644 --- a/core/model/fieldtypes/Varchar.php +++ b/core/model/fieldtypes/Varchar.php @@ -5,6 +5,7 @@ * @subpackage model */ class Varchar extends DBField { + protected $size; function __construct($name, $size = 50) { @@ -14,6 +15,11 @@ class Varchar extends DBField { function requireField() { DB::requireField($this->tableName, $this->name, "varchar($this->size) character set utf8 collate utf8_general_ci"); } + + function hasValue() { + return ($this->value || $this->value == '0'); + } + /** * Return the first letter of the string followed by a . */ diff --git a/forms/Form.php b/forms/Form.php index 536cb99cc..a79bd26bb 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -590,7 +590,7 @@ class Form extends ViewableData { if($o || !isset($object[$name . '_unchanged'])) { // Second check was the original check: save the value if we have one if(isset($val) || $loadBlanks) { - $field->setValue($val); + $field->setValue($val, $object); } } }