Version: current

      1 <?php
      2 /**
      3  * Single field in the database.
      4  * Every field from the database is represented as a sub-class of DBField.
      5  *
      6  * <h2>Multi-value DBField objects</h2>
      7  * Sometimes you will want to make DBField classes that don't have a 1-1 match to database fields.  To do this, there are a
      8  * number of fields for you to overload.
      9  *  - Overload {@link writeToManipulation} to add the appropriate references to the INSERT or UPDATE command
     10  *  - Overload {@link addToQuery} to add the appropriate items to a SELECT query's field list
     11  *  - Add appropriate accessor methods
     12  *
     13  * @package sapphire
     14  * @subpackage model
     15  */
     16 abstract class DBField extends ViewableData {
     17
     18     protected $value;
     19
     20     protected $tableName;
     21
     22     protected $name;
     23
     24     protected $arrayValue;
     25
     26     /**
     27      * The escape type for this field when inserted into a template - either "xml" or "raw".
     28      *
     29      * @var string
     30      */
     31     public static $escape_type = 'raw';
     32
     33     /**
     34      * Subclass of {@link SearchFilter} for usage in {@link defaultSearchFilter()}.
     35      *
     36      * @var string
     37      */
     38     public static $default_search_filter_class = 'PartialMatchFilter';
     39
     40     /**
     41      * @var $default mixed Default-value in the database.
     42      * Might be overridden on DataObject-level, but still useful for setting defaults on
     43      * already existing records after a db-build.
     44      */
     45     protected $defaultVal;
     46
     47     function __construct($name = null) {
     48         $this->name = $name;
     49
     50         parent::__construct();
     51     }
     52
     53     /**
     54      * Create a DBField object that's not bound to any particular field.
     55      * Useful for accessing the classes behaviour for other parts of your code.
     56      */
     57     static function create($className, $value, $name = null, $object = null) {
     58         $dbField = Object::create($className, $name, $object);
     59         $dbField->setValue($value, null, false);
     60         return $dbField;
     61     }
     62
     63     /**
     64      * Set the name of this field.
     65      * The name should never be altered, but it if was never given a name in the first place you can set a name.
     66      * If you try an alter the name a warning will be thrown.
     67      */
     68     function setName($name) {
     69         if($this->name) {
     70             user_error("DBField::setName() shouldn't be called once a DBField already has a name.  It's partially immutable - it shouldn't be altered after it's given a value.", E_USER_WARNING);
     71         }
     72         $this->name = $name;
     73     }
     74
     75     /**
     76      * Returns the name of this field.
     77      * @return string
     78      */
     79     function getName() {
     80         return $this->name;
     81     }
     82
     83     /**
     84      * Returns the value of this field.
     85      * @return mixed
     86      */
     87     function getValue() {
     88         return $this->value;
     89     }
     90
     91     /**
     92      * Set the value on the field.
     93      * Optionally takes the whole record as an argument,
     94      * to pick other values.
     95      *
     96      * @param mixed $value
     97      * @param array $record
     98      */
     99     function setValue($value, $record = null) {
    100         $this->value = $value;
    101     }
    102
    103     /**
    104      * Determines if the field has a value which
    105      * is not considered to be 'null' in
    106      * a database context.
    107      *
    108      * @return boolean
    109      */
    110     function hasValue() {
    111         return ($this->value);
    112     }
    113
    114     /**
    115      * @return bool
    116      */
    117     public function exists() {
    118         return $this->hasValue();
    119     }
    120
    121     /**
    122      * Return an encoding of the given value suitable
    123      * for inclusion in a SQL statement. If necessary,
    124      * this should include quotes.
    125      *
    126      * @param $value mixed The value to check
    127      * @return string The encoded value
    128      */
    129     function prepValueForDB($value) {
    130         if($value === null || $value === "" || $value === false) {
    131             return "null";
    132         } else {
    133             return "'" . Convert::raw2sql($value) . "'";
    134         }
    135     }
    136
    137     /**
    138      * Prepare the current field for usage in a
    139      * database-manipulation (works on a manipulation reference).
    140      *
    141      * Make value safe for insertion into
    142      * a SQL SET statement by applying addslashes() -
    143      * can also be used to apply special SQL-commands
    144      * to the raw value (e.g. for GIS functionality).
    145      * {@see prepValueForDB}
    146      *
    147      * @param array $manipulation
    148      */
    149     function writeToManipulation(&$manipulation) {
    150         $manipulation['fields'][$this->name] = $this->hasValue() ? $this->prepValueForDB($this->value) : $this->nullValue();
    151     }
    152
    153     /**
    154      * Add custom query parameters for this field,
    155      * mostly SELECT statements for multi-value fields.
    156      *
    157      * By default, the ORM layer does a
    158      * SELECT <tablename>.* which
    159      * gets you the default representations
    160      * of all columns.
    161      *
    162      * @param SS_Query $query
    163      */
    164     function addToQuery(&$query) {
    165
    166     }
    167
    168     function setTable($tableName) {
    169         $this->tableName = $tableName;
    170     }
    171
    172     /**
    173      * @return string
    174      */
    175     public function forTemplate() {
    176         return $this->XML();
    177     }
    178
    179     function HTMLATT() {
    180         return Convert::raw2htmlatt($this->value);
    181     }
    182     function URLATT() {
    183         return urlencode($this->value);
    184     }
    185     function RAWURLATT() {
    186         return rawurlencode($this->value);
    187     }
    188     function ATT() {
    189         return Convert::raw2att($this->value);
    190     }
    191
    192     function RAW() {
    193         return $this->value;
    194     }
    195
    196     function JS() {
    197         return Convert::raw2js($this->value);
    198     }
    199
    200     function HTML(){
    201         return Convert::raw2xml($this->value);
    202     }
    203
    204     function XML(){
    205         return Convert::raw2xml($this->value);
    206     }
    207
    208     /**
    209      * Converts the current value for this Enum DBField to lowercase.
    210      * @return string
    211      */
    212     function LowerCase() {
    213         return Convert::raw2xml(strtolower($this->value));
    214     }
    215
    216     /**
    217      * Converts the current value for this Enum DBField to uppercase.
    218      * @return string
    219      */
    220     function UpperCase() {
    221         return Convert::raw2xml(strtoupper($this->value));
    222     }
    223
    224
    225     /**
    226      * Returns the value to be set in the database to blank this field.
    227      * Usually it's a choice between null, 0, and ''
    228      */
    229     function nullValue() {
    230         return "null";
    231     }
    232
    233     /**
    234      * Saves this field to the given data object.
    235      */
    236     function saveInto($dataObject) {
    237         $fieldName = $this->name;
    238         if($fieldName) {
    239             $dataObject->$fieldName = $this->value;
    240         } else {
    241             user_error("DBField::saveInto() Called on a nameless '" . get_class($this) . "' object", E_USER_ERROR);
    242         }
    243     }
    244
    245     /**
    246      * Returns a FormField instance used as a default
    247      * for form scaffolding.
    248      *
    249      * Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}
    250      *
    251      * @param string $title Optional. Localized title of the generated instance
    252      * @return FormField
    253      */
    254     public function scaffoldFormField($title = null) {
    255         $field = new TextField($this->name, $title);
    256
    257         return $field;
    258     }
    259
    260     /**
    261      * Returns a FormField instance used as a default
    262      * for searchform scaffolding.
    263      *
    264      * Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}.
    265      *
    266      * @param string $title Optional. Localized title of the generated instance
    267      * @return FormField
    268      */
    269     public function scaffoldSearchField($title = null) {
    270         return $this->scaffoldFormField($title);
    271     }
    272
    273     /**
    274      * @todo documentation
    275      *
    276      * @todo figure out how we pass configuration parameters to
    277      * search filters (note: parameter hack now in place to pass in the required full path - using $this->name won't work)
    278      *
    279      * @return SearchFilter
    280      */
    281     public function defaultSearchFilter($name = false) {
    282         $name = ($name) ? $name : $this->name;
    283         $filterClass = $this->stat('default_search_filter_class');
    284         return new $filterClass($name);
    285     }
    286
    287     /**
    288      * Add the field to the underlying database.
    289      */
    290     abstract function requireField();
    291
    292     function debug() {
    293         return <<<DBG
    294 <ul>
    295     <li><b>Name:</b>{$this->name}</li>
    296     <li><b>Table:</b>{$this->tableName}</li>
    297     <li><b>Value:</b>{$this->value}</li>
    298 </ul>
    299 DBG;
    300     }
    301
    302 }
    303 ?>

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -