1: <?php
2: namespace Module\DB;
3:
4: require_once(dirname(__FILE__) . '/class.db.php');
5: require_once(dirname(__FILE__) . '/../../core/class.debug.php');
6:
7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
61:
62: class Record {
63: 64: 65:
66: protected $db;
67:
68: 69: 70:
71: protected $table;
72:
73: 74: 75:
76: protected $primaryKey = 'id';
77:
78: 79: 80:
81: public $columns;
82:
83: 84: 85:
86: public $meta;
87:
88: 89: 90: 91: 92:
93: public function __construct($id=0) {
94: $this->db = DB::getInstance();
95:
96: $select = $this->db->query("SELECT * FROM `{$this->table}` LIMIT 1");
97:
98: for ($i = 0; $i <= $select->columnCount(); $i ++) {
99: $meta = $select->getColumnMeta($i);
100: if (isset($meta['name'])) {
101: $this->meta[$meta['name']] = $meta;
102: }
103: }
104:
105: if ($id) {
106: $this->load($id);
107: }
108: }
109:
110: 111: 112: 113: 114: 115:
116: public function load($id=0) {
117: if ($this->table == '') {
118: throw new \Exception('$this->table is not set.');
119: }
120:
121: $query = $this->db->prepare("SELECT * FROM `{$this->table}` WHERE {$this->primaryKey}=:{$this->primaryKey}");
122: $query->execute(array(":{$this->primaryKey}" => $id));
123: $query->setFetchMode(\PDO::FETCH_ASSOC);
124:
125: if ($this->columns = $query->fetch()) {
126: return true;
127: } else {
128: throw new \Exception("{$this->table}: Record does not exist.");
129: }
130: }
131:
132: 133: 134: 135: 136:
137: public function save() {
138: $sql = "";
139: $col = array();
140:
141:
142: if ($new = !isset($this->columns[$this->primaryKey])) {
143: $sql = "INSERT INTO {$this->table} SET";
144: } else {
145: $sql = "UPDATE {$this->table} SET";
146: }
147:
148:
149: foreach ($this->columns as $key => $value) {
150: if ($key !== $this->primaryKey) {
151: $sql .= " {$key}=:{$key},";
152: $col[":{$key}"] = $value;
153: } else {
154: $col[":{$key}"] = $value;
155: }
156: }
157:
158:
159: $sql = substr($sql, 0, -1);
160:
161: if (!$new) {
162: $sql = $sql . " WHERE {$this->primaryKey}=:{$this->primaryKey}";
163: }
164:
165: $result = $this->db->prepare($sql);
166:
167:
168: \Sleepy\Hook::addAction('recordBeforeSave');
169: $result->execute($col);
170: \Sleepy\Hook::addAction('recordAfterSave');
171:
172: if ($new) {
173: if ($result->rowCount()) {
174: $this->columns[$this->primaryKey] = $this->db->lastInsertId();
175: return $this->columns[$this->primaryKey];
176: } else {
177: throw new Exception("{$this->table}: Record was not saved.");
178: }
179: } else {
180: return $this->columns[$this->primaryKey];
181: }
182: }
183:
184: 185: 186: 187: 188:
189: public function delete() {
190: \Sleepy\Hook::addAction('recordBeforeDelete');
191: $query = $this->db->prepare('DELETE FROM ' . $this->table . " WHERE {$this->primaryKey}=:{$this->primaryKey}");
192:
193: if ($query->execute(array(":{$this->primaryKey}" => $this->columns[$this->primaryKey]))) {
194: \Sleepy\Hook::addAction('recordDeleteSucessful');
195: return true;
196: } else {
197: \Sleepy\Hook::addAction('recordDeleteError');
198: throw new \Exception("{$this->table}: Record was not deleted.");
199: }
200: }
201:
202: 203: 204: 205: 206: 207: 208: 209:
210: public function form(Array $fields, $legend='table_name', $submit=true) {
211:
212: if ($legend == 'table_name') {
213: $legend = $this->table;
214: }
215:
216:
217: if (empty($fields)) {
218: foreach ($this->meta as $meta) {
219: $fields[$meta['name']] = $meta['name'];
220: }
221: }
222:
223: ?>
224: <fieldset>
225: <legend><?php echo $legend;?></legend>
226: <ul>
227: <?php
228:
229: foreach ($fields as $field => $label) {
230: $class = "";
231: $buffer = "";
232: $meta = $this->meta[$field];
233:
234:
235:
236: if (!is_array($meta)) {
237: $meta['name'] = $field;
238: $meta['flags'] = Array();
239: $meta['native_type'] = 'VAR_STRING';
240: $class .= 'not-binded ';
241: }
242:
243:
244: foreach ($meta['flags'] as $flag) {
245: if ($flag == 'not_null') {
246: $class .= 'required ';
247: }
248:
249: if ($flag == 'primary_key') {
250: $class .= 'primary-key ';
251: }
252: }
253:
254: $label = \Sleepy\Hook::addFilter('dbForm_label', $label);
255:
256: ?>
257: <li>
258: <?php
259:
260: if (!isset($meta['native_type'])) {
261: if ($meta['len'] == 1) {
262: $meta['native_type'] = 'BOOL';
263: }
264: }
265:
266:
267: if (strpos(strtolower($label), 'password') > -1) {
268: $meta['native_type'] = 'PASSWORD';
269: }
270:
271:
272: if (strpos(strtolower($label), 'email') > -1) {
273: $class = "email ";
274: }
275:
276: $value = htmlspecialchars($this->columns[$field]);
277:
278: switch ($meta['native_type']) {
279: case 'LONG':
280: case 'FLOAT':
281: $class .= "digits ";
282: $inputId = "txt_" . $meta['name'];
283:
284: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
285: $buffer .= "<input class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" value=\"{$value}\" />";
286: break;
287: case 'STRING':
288: case 'VAR_STRING':
289: $class .= "string ";
290: $inputId = "txt_" . $meta['name'];
291: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
292: $buffer .= "<input class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" value=\"{$value}\" />";
293: break;
294: case 'PASSWORD':
295: $class .= "password ";
296: $inputId = "pwd_" . $meta['name'];
297: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
298: $buffer .= "<input class=\"{$class}\" type=\"password\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" />";
299: break;
300: case 'DATETIME':
301: $class .= "datetime ";
302: $inputId = "txt_" . $meta['name'];
303: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
304: $buffer .= "<input class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" value=\"{$value}\" />";
305: break;
306: case 'TIMESTAMP':
307: $class .= "timestamp ";
308: $inputId = "txt_" . $meta['name'];
309: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
310: $buffer .= "<input class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" value=\"{$value}\" />";
311: break;
312: case 'NEWDECIMAL':
313: $class .= "decimal ";
314: $inputId = "txt_" . $meta['name'];
315: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
316: $buffer .= "<input class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\" value=\"{$value}\" />";
317: break;
318: case 'BOOL':
319: $class .= "bool ";
320: $inputId = "chk_" . $meta['name'];
321: if ($value) {
322: $checked = "checked=\"checked\"";
323: }
324: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
325: $buffer .= "<input class=\"{$class}\" type=\"checkbox\" name=\"{$inputId}\" id=\"{$inputId}\" value=\"1\" {$checked} />";
326: break;
327: case 'BLOB':
328: $class .= "string ";
329: $inputId = "txt_" . $meta['name'];
330: $buffer .= "<label class=\"{$class}\" for=\"{$inputId}\">{$label}</label>";
331: $buffer .= "<textarea class=\"{$class}\" type=\"text\" name=\"{$inputId}\" id=\"{$inputId}\" maxlength=\"{$meta['len']}\">{$value}</textarea>";
332: break;
333: default:
334: $buffer .= "No Handler for {$meta['native_type']} defined.";
335: }
336:
337:
338: foreach(Array(
339: 'dbForm_list',
340: $this->table . "_dbForm_list"
341: ) as $filterName) {
342: $buffer = \Sleepy\Hook::addFilter($filterName, Array(
343: $buffer,
344: $meta['native_type'],
345: $label,
346: $value,
347: $class,
348: $inputId
349: ));
350: }
351:
352: echo $buffer;
353: ?>
354: </li>
355: <?php
356: }
357: ?>
358: </ul>
359: </fieldset>
360: <?php
361: if ($submit) {
362: ?>
363: <fieldset class="submit">
364: <legend></legend>
365: <ul>
366: <li><input type="submit" value="Save"></li>
367: </ul>
368: </fieldset>
369: <?php
370: }
371: }
372: }