]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - classes/Managed_DataObject.php
pkeyGet is now static and more similar to getKV
[quix0rs-gnu-social.git] / classes / Managed_DataObject.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2010, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * Wrapper for Memcached_DataObject which knows its own schema definition.
22  * Builds its own damn settings from a schema definition.
23  *
24  * @author Brion Vibber <brion@status.net>
25  */
26 abstract class Managed_DataObject extends Memcached_DataObject
27 {
28     /**
29      * The One True Thingy that must be defined and declared.
30      */
31     public static abstract function schemaDef();
32
33     /**
34      * Get an instance by key
35      *
36      * @param string $k Key to use to lookup (usually 'id' for this class)
37      * @param mixed  $v Value to lookup
38      *
39      * @return get_called_class() object if found, or null for no hits
40      *
41      */
42     static function getKV($k,$v=NULL)
43     {
44         return parent::getClassKV(get_called_class(), $k, $v);
45     }
46
47     /**
48      * Get an instance by compound key
49      *
50      * This is a utility method to get a single instance with a given set of
51      * key-value pairs. Usually used for the primary key for a compound key; thus
52      * the name.
53      *
54      * @param array $kv array of key-value mappings
55      *
56      * @return get_called_class() object if found, or null for no hits
57      *
58      */
59     static function pkeyGet($kv)
60     {
61         return parent::pkeyGetClass(get_called_class(), $kv);
62     }
63
64     /**
65      * get/set an associative array of table columns
66      *
67      * @access public
68      * @return array (associative)
69      */
70     function table()
71     {
72         // Hack for PHP 5.2 not supporting late static binding
73         //$table = static::schemaDef();
74         $table = call_user_func(array(get_class($this), 'schemaDef'));
75         return array_map(array($this, 'columnBitmap'), $table['fields']);
76     }
77
78     /**
79      * get/set an  array of table primary keys
80      *
81      * Key info is pulled from the table definition array.
82      * 
83      * @access private
84      * @return array
85      */
86     function keys()
87     {
88         return array_keys($this->keyTypes());
89     }
90
91     /**
92      * Get a sequence key
93      *
94      * Returns the first serial column defined in the table, if any.
95      *
96      * @access private
97      * @return array (column,use_native,sequence_name)
98      */
99
100     function sequenceKey()
101     {
102         $table = call_user_func(array(get_class($this), 'schemaDef'));
103         foreach ($table['fields'] as $name => $column) {
104             if ($column['type'] == 'serial') {
105                 // We have a serial/autoincrement column.
106                 // Declare it to be a native sequence!
107                 return array($name, true, false);
108             }
109         }
110
111         // No sequence key on this table.
112         return array(false, false, false);
113     }
114
115     /**
116      * Return key definitions for DB_DataObject and Memcache_DataObject.
117      *
118      * DB_DataObject needs to know about keys that the table has; this function
119      * defines them.
120      *
121      * @return array key definitions
122      */
123
124     function keyTypes()
125     {
126         $table = call_user_func(array(get_class($this), 'schemaDef'));
127         $keys = array();
128
129         if (!empty($table['unique keys'])) {
130             foreach ($table['unique keys'] as $idx => $fields) {
131                 foreach ($fields as $name) {
132                     $keys[$name] = 'U';
133                 }
134             }
135         }
136
137         if (!empty($table['primary key'])) {
138             foreach ($table['primary key'] as $name) {
139                 $keys[$name] = 'K';
140             }
141         }
142         return $keys;
143     }
144
145     /**
146      * Build the appropriate DB_DataObject bitfield map for this field.
147      *
148      * @param array $column
149      * @return int
150      */
151     function columnBitmap($column)
152     {
153         $type = $column['type'];
154
155         // For quoting style...
156         $intTypes = array('int',
157                           'integer',
158                           'float',
159                           'serial',
160                           'numeric');
161         if (in_array($type, $intTypes)) {
162             $style = DB_DATAOBJECT_INT;
163         } else {
164             $style = DB_DATAOBJECT_STR;
165         }
166
167         // Data type formatting style...
168         $formatStyles = array('blob' => DB_DATAOBJECT_BLOB,
169                               'text' => DB_DATAOBJECT_TXT,
170                               'date' => DB_DATAOBJECT_DATE,
171                               'time' => DB_DATAOBJECT_TIME,
172                               'datetime' => DB_DATAOBJECT_DATE | DB_DATAOBJECT_TIME,
173                               'timestamp' => DB_DATAOBJECT_MYSQLTIMESTAMP);
174
175         if (isset($formatStyles[$type])) {
176             $style |= $formatStyles[$type];
177         }
178
179         // Nullable?
180         if (!empty($column['not null'])) {
181             $style |= DB_DATAOBJECT_NOTNULL;
182         }
183
184         return $style;
185     }
186
187     function links()
188     {
189         $links = array();
190
191         $table = call_user_func(array(get_class($this), 'schemaDef'));
192
193         foreach ($table['foreign keys'] as $keyname => $keydef) {
194             if (count($keydef) == 2 && is_string($keydef[0]) && is_array($keydef[1]) && count($keydef[1]) == 1) {
195                 if (isset($keydef[1][0])) {
196                     $links[$keydef[1][0]] = $keydef[0].':'.$keydef[1][1];
197                 }
198             }
199         }
200         return $links;
201     }
202
203     /**
204      * Return a list of all primary/unique keys / vals that will be used for
205      * caching. This will understand compound unique keys, which
206      * Memcached_DataObject doesn't have enough info to handle properly.
207      *
208      * @return array of strings
209      */
210     function _allCacheKeys()
211     {
212         $table = call_user_func(array(get_class($this), 'schemaDef'));
213         $ckeys = array();
214
215         if (!empty($table['unique keys'])) {
216             $keyNames = $table['unique keys'];
217             foreach ($keyNames as $idx => $fields) {
218                 $val = array();
219                 foreach ($fields as $name) {
220                     $val[$name] = self::valueString($this->$name);
221                 }
222                 $ckeys[] = self::multicacheKey($this->tableName(), $val);
223             }
224         }
225
226         if (!empty($table['primary key'])) {
227             $fields = $table['primary key'];
228             $val = array();
229             foreach ($fields as $name) {
230                 $val[$name] = self::valueString($this->$name);
231             }
232             $ckeys[] = self::multicacheKey($this->tableName(), $val);
233         }
234         return $ckeys;
235     }
236 }