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

/modules/scaffolding/libraries/Scaffolding.php

https://github.com/MHordecki/milionkostek
PHP | 549 lines | 412 code | 99 blank | 38 comment | 46 complexity | 869482a6b6455600ad2a664270f82ff2 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. $ret .= '<a href="' . $this->base . 'relationshiphabtm/' . $row['id'] . '/' . $this->columns[$col]['has_and_belongs_to_many'] . '">A total of ' . $row[$col] . '</a></td>';
  160. else
  161. $ret .= '<a href="' . $this->base . 'relationship/' . $row['id'] . '/' . $this->columns[$col]['has_many'] . '">A total of ' . $row[$col] . '</a></td>';
  162. continue;
  163. }
  164. if(strlen($row[$col]) > 50)
  165. $ret .= substr($row[$col], 0, 47) . '<b>...</b>';
  166. else
  167. $ret .= $row[$col];
  168. $ret .= '</td>';
  169. }
  170. $ret .= '<td><a href="' . $this->base . 'edit/' . $row['id'] . '">E</a></td>';
  171. $ret .= '<td><a href="' . $this->base . 'delete/' . $row['id'] . '">X</a></td></tr>';
  172. }
  173. $ret .= "</table>";
  174. return $ret;
  175. }
  176. protected function Col2Field($col,&$form)
  177. {
  178. if($col[0] == 'id')
  179. {
  180. return $form->hidden('_id');
  181. }
  182. if($l = $this->getOption($col, 'load'))
  183. {
  184. var_dump($l);
  185. }
  186. switch($col[1])
  187. {
  188. case 'varchar':
  189. return $form->input('_' . $col[0]);
  190. break;
  191. case 'text':
  192. return $form->textarea('_' . $col[0])->rows(6)->cols(35);
  193. break;
  194. case 'foreign':
  195. return $form->dropdown('_' . $col[0]);
  196. break;
  197. default:
  198. return $form->input('_' . $col[0]);
  199. break;
  200. }
  201. }
  202. protected function Fieldval2Dbval(&$field,$col)
  203. {
  204. switch($col[1])
  205. {
  206. case 'text':
  207. return implode("\r\n", explode("\n", $field->value));
  208. break;
  209. default:
  210. return $field->value;
  211. break;
  212. }
  213. }
  214. protected function Dbval2Fieldval(&$field,$col,$value=false)
  215. {
  216. switch($col[1])
  217. {
  218. case 'foreign':
  219. $in = Model_Inspect::byTable($col['foreign']);
  220. $res = $in->getKeyList(new Query(new Database));
  221. $opts = array();
  222. $selected = false;
  223. foreach($res as $val)
  224. {
  225. $opts[$val['id']] = $val['_key'];
  226. if($val['_key'] == $value)
  227. $selected = $val['id'];
  228. }
  229. $field->options($opts);
  230. if($selected)
  231. $field->selected($selected);
  232. break;
  233. default:
  234. if($value)
  235. $field->value($value);
  236. else
  237. $field->value('');
  238. break;
  239. }
  240. }
  241. protected function _delete($args)
  242. {
  243. //Initial
  244. $this->base = explode('delete', $this->base);
  245. $this->base = $this->base[0];
  246. $db = new Database();
  247. $db->delete($this->tablename,array('id' => $args[1]));
  248. url::redirect($this->base . 'manage');
  249. }
  250. protected function _edit($args)
  251. {
  252. //Initial
  253. $this->base = explode('edit', $this->base);
  254. $this->base = $this->base[0];
  255. //Get result
  256. $qr = new Query(new Database());
  257. $qr->where($this->tablename . '.id', $args[1]);
  258. $result = $this->inspector->getOne($qr);
  259. if(count($result) == 0)
  260. return 'This record does not exist.';
  261. $result = $result[0];
  262. //More initial stuff
  263. $ret = $this->header('Editing ' . $this->singular . ' ' . $result['_keyfield'], array($this->prettyplural => "main", 'Management' => "manage", "Editing" => "edit/" . $args[1]));
  264. $form = new Forge(NULL,'');
  265. //Get fields and their values
  266. foreach($this->columns as $col)
  267. {
  268. if($this->getOption($col, 'hide_edit'))
  269. continue;
  270. if(strpos($col[1], 'relationship_') === 0)
  271. continue;
  272. $field = $this->Col2Field($col, $form);
  273. $this->Dbval2Fieldval($field, $col, $result[$col[0]]);
  274. $field->label($col['name']);
  275. }
  276. $form->submit('Submit');
  277. //Process input
  278. if($form->validate())
  279. {
  280. $updates = array();
  281. foreach($this->columns as $col)
  282. {
  283. if($this->getOption($col,'hide_edit'))
  284. continue;
  285. //Get current db value
  286. if(strpos($col[1], 'relationship_') === 0) continue;
  287. $formfield = '_' . $col[0];
  288. $formfield = $form->$formfield;
  289. if($col[1] == 'foreign')
  290. {
  291. $dbvalue = $result['_inspector_' . $col[0]];
  292. }
  293. else
  294. $dbvalue = $result[$col[0]];
  295. //Get actual field value
  296. $formfield = $this->Fieldval2Dbval($formfield, $col);
  297. //Check whether needs to be updated
  298. if($formfield != $dbvalue)
  299. {
  300. if($sav = $this->getOption($col, 'save'))
  301. {
  302. $formfield = call_user_func($sav, $formfield);
  303. }
  304. $updates[$col[0]] = $formfield;
  305. }
  306. }
  307. //Run sql query
  308. if(count($updates) > 0)
  309. {
  310. $db=new Database();
  311. if($db->update($this->tablename, $updates, array($this->tablename . '.id' => $args[1])))
  312. Message::add('Data changed successfully.');
  313. else
  314. Message::add('There was an error in the processing.');
  315. }
  316. }
  317. return $ret . $form->render() . '</p>';
  318. }
  319. protected function _addnew($args)
  320. {
  321. $this->base = explode('addnew', $this->base);
  322. $this->base = $this->base[0];
  323. $ret = $this->header('Adding new ' . $this->singular, array($this->prettyplural => "main", 'Add new' => 'addnew'));
  324. $form = new Forge(NULL,'');
  325. foreach($this->columns as $col)
  326. {
  327. if($this->getOption($col, 'hide_edit'))
  328. continue;
  329. $field = $this->Col2Field($col, $form);
  330. $this->Dbval2Fieldval($field, $col);
  331. $field->label($col['name']);
  332. }
  333. $form->submit('Submit');
  334. if($form->validate())
  335. {
  336. $inserts = array();
  337. foreach($this->columns as $col)
  338. {
  339. if($this->getOption($col, 'hide_edit'))
  340. continue;
  341. $formfield = '_' . $col[0];
  342. $formfield = $form->$formfield;
  343. $formfield = $this->Fieldval2Dbval($formfield, $col);
  344. if($formfield != '')
  345. {
  346. if($sav = $this->getOption($col, 'save'))
  347. {
  348. $formfield = call_user_func($sav, $formfield);
  349. }
  350. $inserts[$col[0]] = $formfield;
  351. }
  352. }
  353. if(count($inserts) > 0)
  354. {
  355. $db = new Database();
  356. if($db->insert($this->tablename, $inserts))
  357. Message::add('Data changed successfully.');
  358. else
  359. Message::add('There was an error in the processing.');
  360. }
  361. }
  362. return $ret . $form->render() . '</p>';
  363. }
  364. protected function _relationship($args,$del=true,$add=true)
  365. {
  366. //Initial
  367. $orig_base = $this->base;
  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($orig_base.'/'.$args[1].'/'.$args[2]);
  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 already 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, array(
  436. $tabrel . '.' . substr($this->tablename, 0, -1) . '_id' => $args[1],
  437. $tabrel . '.' . substr($args[2], 0, -1) . '_id' => $args[3]
  438. ));
  439. Message::add_flash('Relationship has been deleted.');
  440. if($habtm)
  441. {
  442. $this->base = explode('relationshiphabtmdelete',$this->base);
  443. $this->base = $this->base[0];
  444. url::redirect($this->base . 'relationshiphabtm/' . $args[1] . '/' . $args[2]);
  445. }
  446. else
  447. url::redirect($this->base . 'relationship/' . $args[1] . '/' . $args[2]);
  448. }
  449. }