PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/scaffolding/libraries/sc.php

https://github.com/MHordecki/milionkostek
PHP | 546 lines | 412 code | 95 blank | 39 comment | 39 complexity | 54e51c32058eee6d3340dc95da69aec9 MD5 | raw file
  1. <?php
  2. class Scaffolding_Core
  3. {
  4. // Model object that needs to be scaffolded.
  5. protected $model;
  6. protected $session;
  7. protected $db;
  8. protected $inspector; // Model_Inspector
  9. protected $columns;
  10. // You know, nouns. For example, for class User_Model:
  11. protected $tablename = ''; // users
  12. protected $singular = ''; // user
  13. protected $prettysignular=''; // User
  14. protected $prettyplural=''; // Users
  15. protected $base; // base url
  16. protected $root; // array of two strings - root link title and root link address
  17. /**
  18. * Constructing a Scaffolding object.
  19. *
  20. * @param model Object of a model you wish to scaffold.
  21. * @param root (optional) Title for the root link in the navigation tree
  22. * @param root_link (optional) Link for the root link in the navigation tree
  23. */
  24. function __construct(&$model, $root = False, $root_link = False)
  25. {
  26. $this->model = &$model;
  27. $t=Model_Inspect::byModel(get_class($model));
  28. $this->db = new Database();
  29. $this->session = new Session();
  30. $this->base = url::base(TRUE).url::current() . '/';
  31. $this->root = array($root, url::base(TRUE) . $root_link);
  32. $this->tablename = inflector::plural(strtolower(substr(get_class($this->model), 0, strpos(get_class($this->model), '_Model'))));
  33. $this->singular = inflector::singular($this->tablename);
  34. $this->prettysingular = ucfirst($this->singular);
  35. $this->prettyplural = inflector::plural($this->prettysingular);
  36. $this->inspector = new Model_Inspector($model);
  37. $this->columns = $this->inspector->inspect();
  38. }
  39. /**
  40. * Call it to make Scaffolding actually work.
  41. * Just make your controller function accepting arguments as an
  42. * array, the pass it as a parameter.
  43. */
  44. public function scaffold($args)
  45. {
  46. if(count($args) == 0)
  47. return $this->_index();
  48. switch($args[0])
  49. {
  50. case 'manage':
  51. return $this->_manage();
  52. break;
  53. case 'addnew':
  54. return $this->_addnew($args);
  55. break;
  56. case 'edit':
  57. return $this->_edit($args);
  58. break;
  59. case 'delete':
  60. return $this->_delete($args);
  61. break;
  62. case 'relationship':
  63. return $this->_relationship($args,false,false);
  64. break;
  65. case 'relationshiphabtm':
  66. return $this->_relationship($args);
  67. break;
  68. case 'relationshiphabtmdelete':
  69. return $this->_relationshipdelete($args,TRUE);
  70. break;
  71. case 'relationshipdelete':
  72. return $this->_relationshipdelete($args);
  73. break;
  74. default:
  75. return $this->_index();
  76. break;
  77. }
  78. }
  79. /**
  80. * Little helper function producing those neat navigation bars.
  81. */
  82. protected function header($title, $tree)
  83. {
  84. $ret = '<span class="navtree">';
  85. $links = array();
  86. if($this->root[0])
  87. {
  88. $links[] = '<a href="' . $this->root[1] . '">' . $this->root[0] . '</a>';
  89. }
  90. foreach($tree as $key => $val)
  91. $links[] = '<a href="' . $this->base . $val . '">' . $key . '</a>';
  92. $ret .= implode(' &raquo; ', $links) . '</span><h1>'.$title.'</h1>';
  93. return $ret;
  94. }
  95. protected function _index()
  96. {
  97. $this->base=explode('main',$this->base);
  98. $this->base=$this->base[0];
  99. $ret = $this->header($this->prettyplural.' main page', array($this->prettyplural => "main"));
  100. $ret .= '<p>Choose your action:</p>
  101. <p>
  102. <ul>
  103. <li><a href="'.$this->base.'manage">Manage '.$this->tablename.'</a></li>
  104. <li><a href="'.$this->base.'addnew">Add new '.$this->singular.'</a></li>
  105. ';
  106. return $ret;
  107. }
  108. protected function getOption($col,$key)
  109. {
  110. if(!array_key_exists('options',$col))
  111. return false;
  112. if(!array_key_exists($key,$col['options']))
  113. return false;
  114. return $col['options'][$key];
  115. }
  116. protected function _manage()
  117. {
  118. // Initial
  119. $this->base=explode('manage',$this->base);
  120. $this->base=$this->base[0];
  121. $db = new Database;
  122. $count = $db->count_records($this->tablename);
  123. $pag = new Pagination(array(
  124. // 'base_url' => 'welcome/pagination_example/page/', // base_url will default to current uri
  125. 'uri_segment' => 'manage',
  126. 'total_items' => $count,
  127. 'items_per_page' => 50,
  128. 'style' => 'digg'
  129. ));
  130. $ret = $this->header($this->prettyplural.' management', array($this->prettyplural => "main", 'Management' => "manage"));
  131. $ret .= '<p> Here you can view and edit existing '.$this->tablename.'.</p>';
  132. $ret.=(string) $pag;
  133. $ret.='<table border="1"><tr>';
  134. //Field headers
  135. $columns=array();
  136. foreach($this->columns as $column)
  137. {
  138. if($this->getOption($column,'hide'))
  139. continue;
  140. $ret.='<th>'.$column['name'].'</th>';
  141. $columns[]=$column[0];
  142. }
  143. $ret.='<th>Edit</th><th>Delete</th></tr>';
  144. //Get rows
  145. $db = new Database();
  146. $result=$this->inspector->getList(Query::query($db)->limit(50)->offset($pag->sql_offset));
  147. //Rows processing
  148. foreach($result as $row)
  149. {
  150. $ret.='<tr>';
  151. foreach($columns as $col)
  152. {
  153. if($this->getOption($this->columns[$col],'hide'))
  154. continue;
  155. $ret.='<td>';
  156. if(strpos($this->columns[$col][1],'relationship')===0)
  157. {
  158. if($this->columns[$col][1]=='relationship_has_and_belongs_to_many')
  159. {
  160. $ret.='<a href="'.$this->base.'relationshiphabtm/'.$row['id'].'/'.$this->columns[$col]['has_and_belongs_to_many'].'">A total of '.$row[$col].'</a></td>';
  161. }
  162. else
  163. $ret.='<a href="'.$this->base.'relationship/'.$row['id'].'/'.$this->columns[$col]['has_many'].'">A total of '.$row[$col].'</a></td>';
  164. continue;
  165. }
  166. if(strlen($row[$col])>50)
  167. $ret.=substr($row[$col],0,47).'<b>...</b>';
  168. else
  169. $ret.=$row[$col];
  170. $ret.='</td>';
  171. }
  172. $ret.='<td><a href="'.$this->base.'edit/'.$row['id'].'">E</a></td>';
  173. $ret.='<td><a href="'.$this->base.'delete/'.$row['id'].'">X</a></td></tr>';
  174. }
  175. $ret.="</table>";
  176. return $ret;
  177. }
  178. protected function Col2Field($col,&$form)
  179. {
  180. if($col[0]=='id')
  181. {
  182. return $form->hidden('_id');
  183. }
  184. if($l=$this->getOption($col,'load'))
  185. {
  186. var_dump($l);
  187. }
  188. switch($col[1])
  189. {
  190. case 'varchar':
  191. return $form->input('_'.$col[0]);
  192. break;
  193. case 'text':
  194. return $form->textarea('_'.$col[0])->rows(6)->cols(35);
  195. break;
  196. case 'foreign':
  197. return $form->dropdown('_'.$col[0]);
  198. break;
  199. default:
  200. return $form->input('_'.$col[0]);
  201. break;
  202. }
  203. }
  204. protected function Fieldval2Dbval(&$field,$col)
  205. {
  206. switch($col[1])
  207. {
  208. case 'text':
  209. return implode("\r\n",explode("\n",$field->value));
  210. break;
  211. default:
  212. return $field->value;
  213. break;
  214. }
  215. }
  216. protected function Dbval2Fieldval(&$field,$col,$value=false)
  217. {
  218. switch($col[1])
  219. {
  220. case 'foreign':
  221. $in=Model_Inspect::byTable($col['foreign']);
  222. $res=$in->getKeyList(new Query(new Database));
  223. $opts=array();
  224. $selected=false;
  225. foreach($res as $val)
  226. {
  227. $opts[$val['id']]=$val['_key'];
  228. if($val['_key']==$value) $selected=$val['id'];
  229. }
  230. $field ->options($opts);
  231. if($selected)
  232. $field->selected($selected);
  233. break;
  234. default:
  235. if($value)
  236. $field->value($value);
  237. else
  238. $field->value('');
  239. break;
  240. }
  241. }
  242. protected function _delete($args)
  243. {
  244. //Initial
  245. $this->base=explode('delete',$this->base);
  246. $this->base=$this->base[0];
  247. $db = new Database();
  248. $db->delete($this->tablename,array('id'=>$args[1]));
  249. url::redirect($this->base.'manage');
  250. }
  251. protected function _edit($args)
  252. {
  253. //Initial
  254. $this->base=explode('edit',$this->base);
  255. $this->base=$this->base[0];
  256. //Get result
  257. $qr=new Query(new Database());
  258. $qr->where($this->tablename.'.id',$args[1]);
  259. $result=$this->inspector->getOne($qr);
  260. if(count($result)==0)
  261. return 'This record does not exist.';
  262. $result=$result[0];
  263. //More initial stuff
  264. $ret = $this->header('Editing '.$this->singular.' '.$result['_keyfield'], array($this->prettyplural => "main", 'Management' => "manage", "Editing" => "edit/".$args[1]));
  265. //$ret='<h1>Editing '.strtolower($this->prettyname).' '.$result['_keyfield'].'</h1><a href="'.$this->base.'manage">Back to the '.$this->tableplural.' list .</a><p>';
  266. $form=new Forge(NULL,'');
  267. //Get fields and their values
  268. foreach($this->columns as $col)
  269. {
  270. if($this->getOption($col,'hide_edit'))
  271. continue;
  272. if(strpos($col[1],'relationship_')===0) continue;
  273. $field=$this->Col2Field($col,$form);
  274. $this->Dbval2Fieldval($field,$col,$result[$col[0]]);
  275. $field->label($col['name']);
  276. }
  277. $form->submit('Submit');
  278. //Process input
  279. if($form->validate())
  280. {
  281. $updates=array();
  282. foreach($this->columns as $col)
  283. {
  284. if($this->getOption($col,'hide_edit'))
  285. continue;
  286. //Get actual db value
  287. if(strpos($col[1],'relationship_')===0) continue;
  288. $formfield='_'.$col[0];
  289. $formfield=$form->$formfield;
  290. if($col[1]=='foreign')
  291. {
  292. $dbvalue=$result['_inspector_'.$col[0]];
  293. }
  294. else
  295. $dbvalue=$result[$col[0]];
  296. //Get actual field value
  297. $formfield=$this->Fieldval2Dbval($formfield,$col);
  298. //Check whether needs to be updated
  299. if($formfield!=$dbvalue)
  300. {
  301. if($sav=$this->getOption($col,'save'))
  302. {
  303. $formfield=call_user_func($sav,$formfield);
  304. }
  305. $updates[$col[0]]=$formfield;
  306. }
  307. }
  308. //Run sql query
  309. if(count($updates)>0)
  310. {
  311. $db=new Database();
  312. if( $db->update($this->tablename,$updates,array($this->tablename.'.id' => $args[1])))
  313. Message::add('Data changed successfully.');
  314. else
  315. Message::add('There was an error in the processing.');
  316. }
  317. }
  318. return $ret.$form->render().'</p>';
  319. }
  320. protected function _addnew($args)
  321. {
  322. $this->base=explode('addnew',$this->base);
  323. $this->base=$this->base[0];
  324. $ret = $this->header('Adding new '.$this->singular, array($this->prettyplural => "main", 'Add new' => 'addnew'));
  325. $form=new Forge(NULL,'');
  326. foreach($this->columns as $col)
  327. {
  328. if($this->getOption($col,'hide_edit'))
  329. continue;
  330. $field=$this->Col2Field($col,$form);
  331. $this->Dbval2Fieldval($field,$col);
  332. $field->label($col['name']);
  333. }
  334. $form->submit('Submit');
  335. if($form->validate())
  336. {
  337. $inserts=array();
  338. foreach($this->columns as $col)
  339. {
  340. if($this->getOption($col,'hide_edit'))
  341. continue;
  342. $formfield='_'.$col[0];
  343. $formfield=$form->$formfield;
  344. $formfield=$this->Fieldval2Dbval($formfield,$col);
  345. if($formfield!='')
  346. {
  347. if($sav=$this->getOption($col,'save'))
  348. {
  349. $formfield=call_user_func($sav,$formfield);
  350. }
  351. $inserts[$col[0]]=$formfield;
  352. }
  353. }
  354. if(count($inserts)>0)
  355. {
  356. $db=new Database();
  357. if($db->insert($this->tablename,$inserts))
  358. Message::add('Data changed successfully.');
  359. else
  360. Message::add('There was an error in the processing.');
  361. }
  362. }
  363. return $ret.$form->render().'</p>';
  364. }
  365. protected function _relationship($args,$del=true,$add=true)
  366. {
  367. //Initial
  368. $this->base=explode('relationship',$this->base);
  369. $this->base=$this->base[0];
  370. $roles=array();
  371. //Get result
  372. $result=$this->inspector->getRelated(new Query(new Database()),$args[1],$args[2]);
  373. $ret = $this->header('Editing relationship of '.$this->singular, array($this->prettyplural => "main", 'Management' => "manage", "Editing relationship" => "relationship/".$args[1].'/'.$args[2]));
  374. if(count($result)==0)
  375. {
  376. $ret.='This relationship is empty.<br/>';
  377. }else
  378. {
  379. //More initial stuff
  380. $relname=Model_Inspect::byTable($args[2])->getKeyField();
  381. $relname=$relname['name'];
  382. $ret.='<table border="1"><tr><th>Id</th><th>'.$relname.'</th>'.($del ? '<th>Delete</th>' : '').'</tr>';
  383. $id=1;
  384. foreach($result as $row)
  385. {
  386. $ret.='<tr><td>'.($id++).'</td><td>'.$row['name'].'</td>'.($del ? '<td><a href="'.$this->base.'relationship'.($del ? 'habtm':'').'delete/'.$args[1].'/'.$args[2].'/'.$row['id'].'">X</a>':'').'</tr>';
  387. $roles[]=$row['id'];
  388. }
  389. $ret.='</table>';
  390. }
  391. $ret.='</p>';
  392. if($add)
  393. {
  394. $ret.='<br/><h2>Add new relationship</h2><p>';
  395. $form=new Forge();
  396. $field=$form->dropdown('_'.$args[2]);
  397. //Fooling Dbval2Fieldval
  398. $col=array();
  399. $col[1]='foreign';
  400. $col['foreign']=$args[2];
  401. $this->Dbval2Fieldval($field,$col);
  402. $form->submit('Submit');
  403. if($form->validate())
  404. {
  405. var_dump($field->value);
  406. if(in_array($field->value,$roles))
  407. {
  408. Message::add('This relationship is present.');
  409. } else
  410. {
  411. $tabrel=$this->tablename.'_'.$args[2];
  412. $db=new Database();
  413. $db->insert($tabrel,array(
  414. substr($this->tablename,0,-1).'_id'=>$args[1],
  415. substr($args[2],0,-1).'_id'=>$field->value
  416. ));
  417. Message::add_flash('Relationship has been added.');
  418. if($del and $add)
  419. url::redirect($this->base.'relationshiphabtm/'.$args[1].'/'.$args[2]);
  420. else
  421. url::redirect($this->base.'relationship/'.$args[1].'/'.$args[2]);
  422. }
  423. }
  424. }
  425. return $ret.(isset($form) ? $form->render() : '');
  426. }
  427. protected function _relationshipdelete($args,$habtm=false)
  428. {
  429. //Initial
  430. $this->base=explode('relationshipdelete',$this->base);
  431. $this->base=$this->base[0];
  432. $tabrel=$this->tablename.'_'.$args[2];
  433. //Get result
  434. $db=new Database();
  435. $db->delete($tabrel,
  436. array(
  437. $tabrel.'.'.substr($this->tablename,0,-1).'_id' => $args[1],
  438. $tabrel.'.'.substr($args[2],0,-1).'_id' => $args[3]
  439. ));
  440. Message::add_flash('Relationship has been deleted.');
  441. if($habtm)
  442. {
  443. $this->base=explode('relationshiphabtmdelete',$this->base);
  444. $this->base=$this->base[0];
  445. url::redirect($this->base.'relationshiphabtm/'.$args[1].'/'.$args[2]);
  446. }
  447. else
  448. url::redirect($this->base.'relationship/'.$args[1].'/'.$args[2]);
  449. }
  450. }