00001 <?php
00013 define('VALID_IMAGE_TYPES', 'image/png image/pjpeg image/jpeg image/jpg image/gif');
00014
00015 class Page_CRUD extends Page
00016 {
00017 var $model_name;
00018 var $human_name;
00019 var $model;
00020
00021 var $create_template;
00022 var $edit_template;
00023 var $list_template;
00024 var $edit_url;
00025 var $list_url;
00026 var $after_url;
00027 var $after_template;
00028
00029
00030
00031 var $file_dir;
00032
00033
00034
00035 var $enabled_actions = array('create','edit','delete','list','file');
00036
00037
00038
00039 var $ajax_reload_parent = false;
00040
00045 function Page_CRUD()
00046 {
00047 $this->Page();
00048 }
00049
00057 function set_entity($model_name, $human_name, $template_prefix=false)
00058 {
00059 $this->model_name = $model_name;
00060 $this->human_name = $human_name;
00061 $this->model =& $this->models->{$this->model_name};
00062
00063 if($template_prefix === false) $template_prefix = $model_name.'/';
00064
00065
00066 $this->create_template = "{$template_prefix}create.php";
00067 $this->edit_template = "{$template_prefix}create.php";
00068 $this->list_template = "{$template_prefix}list.php";
00069
00070
00071 $cn = substr(get_class($this), 1);
00072 $this->edit_url = url($cn, 'edit').'?id=<id>';
00073 $this->list_url = url($cn, 'list');
00074
00075
00076
00077
00078 $this->after_url = $this->list_url;
00079 $this->after_template = "";
00080 }
00081
00086 function make_url($url, $id='')
00087 {
00088 return str_replace(array('_ID_','<id>'), $id, $url);
00089 }
00090
00091
00092
00093
00094
00095 function GET_create()
00096 {
00097 $this->auth_create();
00098 if(!in_array('create', $this->enabled_actions)) $this->web->forbidden();
00099
00100 $json = array();
00101
00102
00103 if($this->template->is_set('data')) {
00104 $data = $this->template->get('data');
00105 $this->template->un_set('data');
00106 $json['errors'] = $this->template->get('errors');
00107
00108
00109 } else {
00110 $data = $this->model->create_record();
00111 if($this->hook_create__pre_edit($data) === false) return;
00112 if($this->hook__pre_edit($data) === false) return;
00113 }
00114 $this->template->set('data', $data);
00115
00116 if($this->ajax) {
00117 $this->ajax_render($this->create_template, $json);
00118 } else {
00119 $this->render($this->create_template);
00120 }
00121 }
00122
00126 function POST_create()
00127 {
00128 $this->auth_create();
00129
00130 $data = $this->load_input();
00131 $is_update = isset($data['id']) && !empty($data['id']);
00132
00133 if(!$is_update && !in_array('create', $this->enabled_actions)) $this->web->forbidden();
00134
00135 if(preg_match('|^Model|', get_parent_class($this->model))) {
00136
00137 $errors = $this->model->validate($data, $is_update);
00138 } else {
00139 $errors = $this->model->validate($data);
00140 }
00141
00142
00143 if(is_array($this->model->files)) {
00144 foreach($this->model->files as $k=>$v) {
00145 if(!isset($_FILES[$k])) continue;
00146 if($_FILES[$k]['error'] != 0) continue;
00147 $f =& $_FILES[$k];
00148 if($f['error'] != 0) $errors[$k] = __('An error occurred while uploading - please try again');
00149 if(isset($v['type'])) {
00150
00151 $match = false;
00152 if($v['type'] == 'image') {
00153 $v['type'] = explode(' ', VALID_IMAGE_TYPES);
00154 }
00155 if(is_array($v['type'])) {
00156 foreach($v['type'] as $m) {
00157 if($f['type'] == $m) $match = true;
00158 }
00159 } else {
00160 if($f['type'] == $v['type']) $match = true;
00161 }
00162 if(!$match) $errors[$k] = __('%s: Invalid file type uploaded', ucwords(str_replace('_',' ',$k)));
00163 }
00164 }
00165 }
00166
00167 if(!empty($errors)) {
00168 $this->template->set('errors', $errors);
00169 if($is_update) {
00170 if($this->hook_edit__failed_validation($data) === false) return;
00171 if($this->hook__failed_validation($data) === false) return;
00172 if($this->hook_edit__pre_edit($data) === false) return;
00173 if($this->hook__pre_edit($data) === false) return;
00174 $this->template->set('data', $data);
00175 $this->GET_edit();
00176 } else {
00177 if($this->hook_create__failed_validation($data) === false) return;
00178 if($this->hook__failed_validation($data) === false) return;
00179 if($this->hook_create__pre_edit($data) === false) return;
00180 if($this->hook__pre_edit($data) === false) return;
00181 $this->template->set('data', $data);
00182 $this->GET_create();
00183 }
00184 return;
00185 }
00186
00187 if($is_update) {
00188 $id = $data['id'];
00189 if($this->hook_update__pre_save($data) === false) return;
00190 if($this->hook__pre_save($data) === false) return;
00191 $this->model->save($data);
00192 $flash = __('%s has been updated.', $this->human_name);
00193 } else {
00194 if($this->hook_insert__pre_save($data) === false) return;
00195 if($this->hook__pre_save($data) === false) return;
00196 $id = $this->model->save($data);
00197 $data['id'] = $id;
00198 $flash = __('%s has been created.', $this->human_name);
00199 }
00200
00201
00202 if(is_array($this->model->files)) {
00203 foreach($this->model->files as $k=>$v) {
00204 if(!isset($_FILES[$k])) continue;
00205 if($_FILES[$k]['error'] != 0) continue;
00206 $f =& $_FILES[$k];
00207 foreach($data as $dk=>$dv) {
00208 if(is_array($dv)) continue;
00209 $v['filename'] = str_replace("<$dk>", $dv, $v['filename']);
00210 }
00211 $path = $v['fileroot'].DS.$v['filename'];
00212 if($v['type'] == 'image') {
00213 if(!isset($this->plugins->image)) $this->import_plugin('image');
00214 if(isset($v['max_width'])) {
00215 $this->plugins->image->resize($f['type'], $f['tmp_name'], $path, $v['max_width'], $v['max_height'], true);
00216 } else {
00217 $this->plugins->image->convert($f['type'], $f['tmp_name'], $path);
00218 }
00219 } else {
00220 move_uploaded_file($f['tmp_name'], $path);
00221 }
00222 }
00223 }
00224
00225
00226 if($is_update) {
00227 if($this->hook_update__post_save($data) === false) return;
00228 } else {
00229 if($this->hook_insert__post_save($data) === false) return;
00230 }
00231 if($this->hook__post_save($data) === false) return;
00232
00233 if($this->ajax) {
00234 if($this->ajax_reload_parent) {
00235 if(!$this->flash_isset()) $this->flash($flash);
00236 $this->ajax_render($this->after_template, array('success'=>true,'reload'=>true));
00237 } else {
00238 $flash = $this->flash_isset() ? $this->flash_get() : $flash;
00239 $this->ajax_render($this->after_template, array('success'=>true,'flash'=>$flash));
00240 }
00241 } else {
00242 if(!$this->flash_isset()) $this->flash($flash);
00243 if($this->after_template) {
00244 $this->render($this->after_template);
00245 } else {
00246 $this->redirect($this->make_url($this->after_url, $id));
00247 }
00248 }
00249 }
00250
00251
00252
00253
00254 function GET_edit()
00255 {
00256 $this->auth_create();
00257 if(!in_array('edit', $this->enabled_actions)) $this->web->forbidden();
00258
00259 $json = array();
00260
00261
00262 if($this->template->is_set('data')) {
00263 $data = $this->template->get('data');
00264 $this->template->un_set('data');
00265 $json['errors'] = $this->template->get('errors');
00266
00267
00268 } else {
00269 $id = $this->param('id');
00270 $data = $this->model->load($id) or $this->web->notfound();
00271 }
00272 if($this->hook_edit__pre_edit($data) === false) return;
00273 if($this->hook__pre_edit($data) === false) return;
00274 $this->template->set('data', $data);
00275
00276
00277 if(is_array($this->model->files)) {
00278 foreach($this->model->files as $k=>$v) {
00279 foreach($data as $dk=>$dv) {
00280 if(!is_array($dv)) $v['filename'] = str_replace("<$dk>", $dv, $v['filename']);
00281 }
00282 if(file_exists($v['fileroot'].DS.$v['filename'])) {
00283 $data[$k] = $v['webroot'].'/'.$v['filename'];
00284 }
00285 }
00286 }
00287
00288 if($this->ajax) {
00289 $this->ajax_render($this->edit_template, $json);
00290 } else {
00291 $this->render($this->edit_template);
00292 }
00293 }
00294 function POST_edit()
00295 {
00296 $this->auth_create();
00297 if(!in_array('edit', $this->enabled_actions)) $this->web->forbidden();
00298 $this->POST_create();
00299 }
00300
00301
00302
00303
00304 function GET_delete()
00305 {
00306 $this->auth_delete();
00307 if(!in_array('delete', $this->enabled_actions)) $this->web->forbidden();
00308
00309 $ids = $this->param('delete_ids', $this->param('ids', array($this->param('id'))));
00310 foreach($ids as $id) {
00311 $data = $this->model->load($id) or $this->web->notfound();
00312 if($this->hook_delete__pre_delete($data) === false) return;
00313 $this->model->delete($data['id']);
00314
00315
00316 if(is_array($this->model->files)) {
00317 foreach($this->model->files as $k=>$v) @unlink($this->model->files[$k]['path'].DS.$id);
00318 }
00319
00320 if($this->hook_delete__post_delete($data) === false) return;
00321 }
00322 $this->flash(__('%s has been deleted.', $this->human_name));
00323 if($this->ajax) {
00324 $this->ajax_render('', array('success'=>true));
00325 } else {
00326 $this->redirect($this->make_url($this->list_url));
00327 }
00328 }
00329
00330
00331
00332
00333 function GET_list()
00334 {
00335 $this->auth_list();
00336 if(!in_array('list', $this->enabled_actions)) $this->web->forbidden();
00337
00338
00339 $params = $this->model->enum_schema();
00340 if(empty($params['order'])) $params['order'] = "{$this->model->pk} ASC";
00341 if(empty($params['limit'])) $params['limit'] = 50;
00342 if($this->hook_list__params($params) === false) return;
00343
00344 list($data,$ttlrows,$curpage,$perpage) = $this->sql->enumerate($params);
00345 if($this->hook_list__post_select($data) === false) return;
00346
00347 if($this->ajax) {
00348 $ret = array(
00349 'total' => ceil($ttlrows / $perpage),
00350 'page' => $curpage,
00351 'records' => $ttlrows,
00352 'rows' => array(),
00353 );
00354
00355
00356 $cols = $this->param('cols');
00357 if($cols) {
00358
00359 $cols = explode('&', urldecode($this->param('cols')));
00360 foreach($data as $k=>$v) {
00361 $row = array('cell' => array());
00362 if(isset($v['id'])) $row['id'] = $v['id'];
00363 foreach($cols as $c) $row['cell'][] = $v[$c];
00364 $ret['rows'][] = $row;
00365 }
00366 } else {
00367 foreach($data as $k=>$v) {
00368 $row = array();
00369 foreach($v as $key=>$val) $row[$key] = $val;
00370 $ret['rows'][] = $row;
00371 }
00372 }
00373
00374 echo json_encode($ret);
00375 } else {
00376 $this->template->set('data', $data);
00377 $this->template->set('totalrows', $ttlrows);
00378 $this->template->set('curpage', $curpage);
00379 $this->template->set('perpage', $perpage);
00380 $this->render($this->list_template);
00381 }
00382 }
00383
00384
00385
00386
00387 function GET_file__preview()
00388 {
00389 $this->auth_list();
00390 if(!in_array('file', $this->enabled_actions)) $this->web->forbidden();
00391
00392 $id = $this->param('id');
00393 if(!is_numeric($id)) $this->web->notfound();
00394 $key = $this->param('key');
00395 if(!isset($this->model->files[$key])) $this->web->notfound();
00396
00397
00398 $data = $this->model->load($id) or $this->web->notfound();
00399 $filename = $this->model->files[$key]['filename'];
00400 foreach($data as $k=>$v) {
00401 if(is_array($v)) continue;
00402 $filename = str_replace("<$k>", $v, $filename);
00403 }
00404
00405 if($this->model->files[$key]['type'] == 'image') {
00406 header('Content-Type: image/jpeg');
00407 } else if(isset($this->model->files[$key]['type'])) {
00408 header('Content-Type: '.$this->model->files[$key]['type']);
00409 }
00410 readfile($this->model->files[$key]['fileroot'].DS.$filename);
00411 die;
00412 }
00413 function GET_file__remove()
00414 {
00415 $this->auth_delete();
00416 if(!in_array('file', $this->enabled_actions)) $this->web->forbidden();
00417
00418 $id = $this->param('id');
00419 if(!is_numeric($id)) $this->web->notfound();
00420 $key = $this->param('key');
00421 if(!isset($this->model->files[$key])) $this->web->notfound();
00422
00423
00424 $data = $this->model->get_or_404($id);
00425 $filename = $this->model->files[$key]['filename'];
00426 foreach($data as $k=>$v) {
00427 if(is_array($v)) continue;
00428 $filename = str_replace("<$k>", $v, $filename);
00429 }
00430
00431 @unlink($this->model->files[$key]['fileroot'].DS.$filename);
00432 $this->redirect($this->make_url($this->edit_url, $id));
00433 }
00434
00435
00436
00437
00438
00439 function authenticate() {}
00440 function auth_create() { $this->authenticate(); }
00441 function auth_delete() { $this->authenticate(); }
00442 function auth_list() { $this->authenticate(); }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 function hook__pre_edit(&$data) { return true; }
00453 function hook__failed_validation(&$data) { return true; }
00454 function hook__pre_save(&$data) { return true; }
00455 function hook__post_save(&$data) { return true; }
00456
00457
00458 function hook_create__pre_edit(&$data) { return true; }
00459 function hook_create__failed_validation(&$data) { return true; }
00460 function hook_edit__pre_edit(&$data) { return true; }
00461 function hook_edit__failed_validation(&$data) { return true; }
00462
00463 function hook_insert__pre_save(&$data) { return true; }
00464 function hook_insert__post_save(&$data) { return true; }
00465 function hook_update__pre_save(&$data) { return true; }
00466 function hook_update__post_save(&$data) { return true; }
00467
00468 function hook_delete__pre_delete(&$data) { return true; }
00469 function hook_delete__post_delete(&$data) { return true; }
00470
00471 function hook_list__params(&$params) { return true; }
00472 function hook_list__post_select(&$data) { return true; }
00473 }
00474
00475 ?>