PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/system/application/libraries/CRUD.php

https://bitbucket.org/crynobone/extci
PHP | 1201 lines | 1026 code | 83 blank | 92 comment | 61 complexity | 9c72e86bf5146dd46f8a94f5f7a921db MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CRUD Generator for CodeIgniter
  4. *
  5. * PHP version 5
  6. *
  7. * @category CodeIgniter
  8. * @package CRUD CI
  9. * @author Mior Muhammad Zaki (hello@crynobone.com)
  10. * @version 0.1.1
  11. * Copyright (c) 2009 Mior Muhammad Zaki (http://crynobone.com)
  12. * Licensed under the MIT.
  13. */
  14. class CRUD {
  15. // CI Singleton
  16. private $CI = NULL;
  17. private $_id = 0;
  18. private $_type = 'get';
  19. private $_format = 'http';
  20. private $_ACL = 3;
  21. private $_sort_by = '';
  22. private $_order_by = '';
  23. // set default modify/delete response
  24. private $_default_response = array (
  25. 'success' => FALSE,
  26. 'redirect' => '',
  27. 'error' => '',
  28. 'data' => array ()
  29. );
  30. // Allow output to be access
  31. public $data = array ();
  32. private $_acl_lookup = array (
  33. 0 => 'NONE',
  34. 1 => 'READ',
  35. 2 => 'MODIFY',
  36. 3 => 'DELETE'
  37. );
  38. // set global configuration variables for CRUD
  39. public $config = array (
  40. 'get' => array (),
  41. 'set' => array (),
  42. 'remove' => array (),
  43. 'model' => '',
  44. 'segment' => 3,
  45. 'segment_id' => 4,
  46. 'segment_xhr' => 5,
  47. 'segment_order' => 5,
  48. 'segment_sort' => 6,
  49. 'enable_get' => TRUE,
  50. 'enable_set' => TRUE,
  51. 'enable_remove' => TRUE,
  52. '404' => '',
  53. 'ACL' => 3,
  54. 'enable_ui' => TRUE,
  55. 'auto_render' => TRUE
  56. );
  57. /**
  58. * Constructor
  59. *
  60. * @access public
  61. * @return void
  62. */
  63. public function __construct()
  64. {
  65. // load CI object
  66. $this->CI =& get_instance();
  67. // load required libraries
  68. $this->CI->load->library(array (
  69. 'Form',
  70. 'Table',
  71. 'Pagination'
  72. ));
  73. // add this class to CI object
  74. $this->CI->CRUD = $this;
  75. log_message('debug', "CRUD: Class initialized");
  76. }
  77. /**
  78. *
  79. * @param object $data [optional]
  80. * @return
  81. */
  82. public function initialize($config = array ())
  83. {
  84. // extends configurator
  85. $this->vars($config);
  86. // configure based on uri segment, enable autoloading via _remap method
  87. $segment = $this->_get_access();
  88. // set all possible uri segment value
  89. $is_get = array ('get', 'index', '');
  90. $is_set = array ('set', 'modify', 'write');
  91. $is_get_one = array ('get_one', 'detail');
  92. $is_remove = array ('delete', 'remove');
  93. $send_to = '';
  94. // test segment
  95. if (isset($segment)) {
  96. $send_to = (in_array($segment, $is_get) ? 'get' : $send_to);
  97. $send_to = (in_array($segment, $is_set) ? 'set' : $send_to);
  98. $send_to = (in_array($segment, $is_remove) ? 'remove' : $send_to);
  99. $send_to = (in_array($segment, $is_get_one) ? 'get_one' : $send_to);
  100. if ($send_to != '' ) {
  101. log_message('debug', "CRUD: set route to '{$send_to}'");
  102. // method found, so send to related method
  103. $this->generate($send_to);
  104. }
  105. else {
  106. if ( !! method_exists($this->CI, $segment)) {
  107. log_message('debug', "CRUD: ignore CRUD Class, call method '\$this->{$segment}'");
  108. // method not found but Controller contain this method
  109. $this->CI->{$segment}();
  110. }
  111. else {
  112. // to prevent blank screen if everything else failed, load the 404
  113. log_message('error', "CRUD: both CRUD and method does not exist");
  114. show_404();
  115. }
  116. }
  117. }
  118. else {
  119. // this might be impossible to happen, but let just throw a 404 (just-in-case)
  120. show_404();
  121. }
  122. }
  123. public function vars($config = array ())
  124. {
  125. $this->config = array_merge($this->config, $config);
  126. log_message('debug', 'CRUD: set variable');
  127. }
  128. /**
  129. * Generate the CRUD
  130. *
  131. * @param object $type [optional]
  132. * @param object $option [optional]
  133. * @return
  134. */
  135. public function generate($type = 'get')
  136. {
  137. $allowed = array ('get', 'get_one', 'set', 'remove');
  138. $type_data = $type = trim(strtolower($type));
  139. if ($type == 'get_one') {
  140. $type_data = 'set';
  141. }
  142. // first we need to check whether it's pointing to valid method
  143. if ( !! in_array($type, $allowed)) {
  144. $this->{$type}($this->config[$type_data]);
  145. }
  146. else {
  147. log_message('error', 'CRUD: Unable to determine request ' . $type);
  148. // 404 using CRUD callback
  149. $this->_callback_404();
  150. }
  151. }
  152. /**
  153. *
  154. * @param object $data [optional]
  155. * @access public
  156. * @return
  157. */
  158. public function get($config = array ())
  159. {
  160. // prepare configuration variable
  161. $config = $this->_prepare_get($config);
  162. $datagrid = array ();
  163. $this->_set_type('set');
  164. // output template for this method
  165. $data = array (
  166. 'output' => array (
  167. 'datagrid' => '',
  168. 'records' => FALSE,
  169. 'pagination' => ''
  170. ),
  171. 'records' => FALSE,
  172. 'total_rows' => 0
  173. );
  174. // try to set table template when included
  175. $template = $config['table_template'];
  176. if (is_array($template) && count($template)) {
  177. log_message('debug', 'CRUD: Set TABLE template');
  178. $this->CI->table->set_template($template);
  179. }
  180. // show 404 if access to method is revoke
  181. if (( ! $config['is_accessible'] || ! $this->config['enable_get']) || $this->config['ACL'] < 1) {
  182. log_message('debug', 'CRUD: Access is disabled');
  183. return $this->_callback_404();
  184. }
  185. $model = $config['model'];
  186. $method = $config['method'];
  187. if ( !! property_exists($this->CI, $model)) {
  188. log_message('debug', "CRUD: Using model '{$model}'");
  189. if ( !! method_exists($this->CI->{$model}, $method)) {
  190. log_message('debug', "CRUD: Using method: '{$method}'");
  191. // get data from method
  192. $grid = $this->CI->{$model}->{$method}(
  193. $config['limit'],
  194. $config['offset'],
  195. array (
  196. 'header' => array(),
  197. 'header_anchor' => array (),
  198. 'total_rows' => 0,
  199. 'data' => array (),
  200. 'cols' => array (),
  201. 'records' => FALSE
  202. ),
  203. array (
  204. 'order_by' => $config['order_by'],
  205. 'sort_by' => $config['sort_by']
  206. )
  207. );
  208. $grid = $this->_args_to_array(
  209. $grid,
  210. array('data', 'total_rows', 'header', 'cols', 'records', 'header_anchor')
  211. );
  212. $datagrid = $grid['data'];
  213. $data['total_rows'] = $grid['total_rows'];
  214. if ($config['enable_table'] === TRUE) {
  215. $header = $config['header'];
  216. $cols = $config['cols'];
  217. $header_anchor = $this->_set_header_anchor($config, $grid['header_anchor']);
  218. if ( isset($grid['header']) && is_array($grid['header'])) {
  219. $header = $grid['header'];
  220. }
  221. if ( isset($grid['cols']) && is_array($grid['cols'])) {
  222. $cols = $grid['cols'];
  223. }
  224. // clear table & set table
  225. $this->CI->table->clear();
  226. $this->CI->table->set_heading($header);
  227. $this->CI->table->set_heading_anchor($header_anchor);
  228. $this->CI->table->set_cols($cols);
  229. // set table data
  230. $data['output']['datagrid'] = $this->CI->table->generate($datagrid);
  231. }
  232. // define pagination configuration
  233. $pagination_config = array (
  234. 'base_url' => $config['base_url'],
  235. 'total_rows' => $data['total_rows'],
  236. 'per_page' => $config['limit'],
  237. 'cur_page' => $config['offset'],
  238. 'show_page_zero' => TRUE,
  239. 'suffix_url' => $this->_set_suffix_url($config)
  240. );
  241. // group pagination configuration & template
  242. $pagination_config = array_merge($pagination_config, $config['pagination_template']);
  243. // generate pagination links
  244. $this->CI->pagination->initialize($pagination_config);
  245. $data['output']['pagination'] = $this->CI->pagination->create_links();
  246. // paste certain information for additional use
  247. $data['records'] = $data['output']['records'] = $grid['records'];
  248. }
  249. else {
  250. // method is not available
  251. log_message('error', 'CRUD: cannot locate method under Application model class');
  252. return $this->_callback_404();
  253. }
  254. }
  255. else {
  256. // model is not available
  257. log_message('error', 'CRUD: cannot locate Application model class');
  258. return $this->_callback_404();
  259. }
  260. // extends output to global var
  261. $this->data = $data;
  262. $callback_xhr = $config['callback_xhr'];
  263. $callback = $config['callback'];
  264. $view = $config['view'];
  265. if ($this->is_format_xhr() && !! method_exists($this->CI, $callback_xhr)) {
  266. // output as an XHR callback
  267. $this->CI->{$callback_xhr}(
  268. $data['output'],
  269. $data['records'],
  270. $data['total_rows']
  271. );
  272. }
  273. elseif ( !! method_exists($this->CI, $callback)) {
  274. // output to a method in Controller
  275. $this->CI->{$callback}(
  276. $data['output'],
  277. $data['records'],
  278. $data['total_rows']
  279. );
  280. }
  281. elseif (trim($view) !== '') {
  282. // output using CRUD viewer
  283. $this->_callback_viewer($data['output'], $config);
  284. }
  285. else {
  286. // return the data
  287. return $data;
  288. }
  289. }
  290. public function get_one($config = array())
  291. {
  292. log_message('debug', 'CRUD: called get_one()');
  293. return $this->set($config, FALSE);
  294. }
  295. public function form($config = array ())
  296. {
  297. log_message('debug', 'CRUD: called form()');
  298. return $this->set($config, TRUE);
  299. }
  300. public function set($config = array(), $is_form = TRUE)
  301. {
  302. $config = $this->_prepare_set($config);
  303. $this->_set_id($config['id']);
  304. $this->_set_type(( ! $is_form ? 'get_one' : 'set'));
  305. $data = array (
  306. 'output' => array (
  307. 'form' => '',
  308. 'form_open' => '',
  309. 'form_close' => '',
  310. 'form_box' => '',
  311. 'button_box' => '',
  312. 'datagrid' => '',
  313. 'fields' => array (),
  314. 'form_hidden' => '',
  315. 'error' => '',
  316. 'value' => array ()
  317. ),
  318. 'result' => FALSE,
  319. 'response' => $this->_default_response
  320. );
  321. if ( !! $is_form) {
  322. $data['output']['form_open'] = form_open($config['action']);
  323. if ($config['multipart'] === TRUE) {
  324. $data['output']['form_open']= form_open_multipart($config['action']);
  325. }
  326. $data['output']['form_close'] = form_close();
  327. }
  328. // try to set form template when included
  329. $template = $config['form_template'];
  330. if (is_array($template) && count($template)) {
  331. log_message('debug', 'CRUD: Set form template');
  332. $this->CI->form->set_template($template);
  333. }
  334. // stop processing if method access to off
  335. if (( ! $config['is_accessible'] || ! $this->config['enable_set']) || ($this->config['ACL'] < 2 && $this->_type === 'set')) {
  336. // shouldn't be able to modify
  337. log_message('debug', 'CRUD: Access to add/edit is disabled');
  338. return $this->_callback_404();
  339. } elseif (( ! $config['is_accessible'] || ! $this->config['enable_get']) || ($this->config['ACL'] < 1 && $this->_type === 'get_one')) {
  340. // shouldn't be able to view single data
  341. log_message('debug', 'CRUD: Access to view is disabled');
  342. return $this->_callback_404();
  343. }
  344. $model = $config['model'];
  345. $method = $config['method'];
  346. if ( !! property_exists($this->CI, $model)) {
  347. log_message('debug', "CRUD: Using model '{$model}'");
  348. $config['fields'] = $this->_organizer($config, 'fields');
  349. $config['data'] = $this->_organizer($config, 'data');
  350. if (is_array($config['fields']) && count($config['fields']) > 0) {
  351. $data['output']['form'] = $this->CI->form->generate(
  352. $config['fields'],
  353. $config['prefix'],
  354. $config['data'],
  355. $is_form
  356. );
  357. $data['output']['fields'] = $this->CI->form->output[$config['prefix']];
  358. $data['output']['value'] = $this->CI->form->value[$config['prefix']];
  359. if ( !! $is_form) {
  360. $data['output']['datagrid'] = $data['output']['form_open'];
  361. $data['output']['datagrid'] .= $data['output']['form'];
  362. $data['output']['datagrid'] .= $data['output']['form_close'];
  363. $data['output']['form_box'] = $this->CI->form->form_box[$config['prefix']];
  364. $data['output']['button_box'] = $this->CI->form->button_box[$config['prefix']];
  365. $data['output']['form_hidden'] = $this->CI->form->form_hidden[$config['prefix']];
  366. }
  367. else {
  368. $data['output']['datagrid'] = $data['output']['form'];
  369. }
  370. if ( !! $this->CI->form->run($config['prefix'])) {
  371. log_message('debug', 'CRUD: Form validated');
  372. $data['result'] = $result = $this->CI->form->result($config['prefix']);
  373. if ( !! method_exists($this->CI->{$model}, $method))
  374. {
  375. log_message('debug', "CRUD: Using method '{$method}'");
  376. $data['response'] = $this->CI->{$model}->{$method}($result, $this->_default_response);
  377. }
  378. else
  379. {
  380. log_message('error', 'CRUD: cannot locate method under Application model class');
  381. return $this->_callback_404();
  382. }
  383. if ($data['response']['success'] === TRUE && trim($data['response']['redirect']) !== '')
  384. {
  385. redirect($data['response']['redirect']);
  386. }
  387. elseif ($data['response']['success'] === FALSE)
  388. {
  389. $data['output']['error'] = sprintf(
  390. '<%s class="%s">%s</%s>',
  391. $this->CI->form->template['error'],
  392. $this->CI->form->template['error_class'],
  393. $data['response']['error'],
  394. $this->CI->form->template['error']
  395. );
  396. if (property_exists($this->CI, 'ui')) {
  397. $this->CI->ui->set_flash_message('error', $data['response']['error'], FALSE);
  398. }
  399. }
  400. } else {
  401. log_message('debug', 'CRUD: Form not validated');
  402. }
  403. }
  404. }
  405. else
  406. {
  407. log_message('error', 'CRUD: cannot locate Application model class');
  408. return $this->_callback_404();
  409. }
  410. // extends output to global var
  411. $this->data = $data;
  412. $callback = $config['callback'];
  413. $callback_xhr = $config['callback_xhr'];
  414. $view = $config['view'];
  415. if ($this->is_format_xhr() && !! method_exists($this->CI, $callback_xhr))
  416. {
  417. // output as an XHR callback
  418. $this->CI->{$callback_xhr}($data['output'], $data['response']);
  419. }
  420. elseif ( !! method_exists($this->CI, $callback))
  421. {
  422. // output to a method in Controller
  423. $this->CI->{$callback}($data['output'], $data['response']);
  424. }
  425. elseif ( trim($view) !== '')
  426. {
  427. // output using CRUD viewer
  428. $this->_callback_viewer($data['output'], $config);
  429. }
  430. else
  431. {
  432. // return the data
  433. return $data;
  434. }
  435. }
  436. /**
  437. * CRUD function for Delete
  438. *
  439. * @access public
  440. * @param object $data [optional]
  441. * @return
  442. */
  443. public function remove($config = array())
  444. {
  445. // prepare configuration
  446. $config = $this->_prepare_remove($config);
  447. $model = $config['model'];
  448. $method = $config['method'];
  449. $this->_set_id($config['id']);
  450. $this->_set_type('remove');
  451. // default response value
  452. $data = array (
  453. 'response' => $this->_default_response
  454. );
  455. // disable access: useful when user doesn't have ACL access
  456. if (( ! $config['is_accessible'] && ! $this->config['enabled_remove']) || $this->config['ACL'] < 3)
  457. {
  458. log_message('debug', "CRUD: access to 'remove' is disabled");
  459. return $this->_callback_404();
  460. }
  461. if ( !! property_exists($this->CI, $model))
  462. {
  463. $response = $data['response'];
  464. if ( !! method_exists($this->CI->{$model}, $method))
  465. {
  466. // get return value from delete method
  467. // response should be based from $this->default_response
  468. log_message('debug', "CRUD: execute '\$this->{$model}->{$method}");
  469. $response = $data['response'] = $this->CI->{$model}->{$method}($config['id'], $response);
  470. }
  471. else
  472. {
  473. log_message('error', 'CRUD: cannot locate method under Application model class');
  474. return $this->_callback_404();
  475. }
  476. // if action is successful and redirect automatically
  477. if ($response['success'] === TRUE && trim($response['redirect']) !== '')
  478. {
  479. redirect($response['redirect']);
  480. }
  481. }
  482. else
  483. {
  484. log_message('error', 'CRUD: cannot locate Application model class');
  485. return $this->_callback_404();
  486. }
  487. // extends output to global var
  488. $this->data = $data;
  489. $callback = $config['callback'];
  490. $callback_xhr = $config['callback_xhr'];
  491. $view = $config['view'];
  492. if ($this->is_format_xhr() && !! method_exists($this->CI, $callback_xhr))
  493. {
  494. // output as an XHR callback
  495. log_message('debug', "CRUD: initialize a callback to '{$callback_xhr}'");
  496. $this->CI->{$callback_xhr}($data['response']);
  497. }
  498. elseif ( !! method_exists($this->CI, $callback))
  499. {
  500. // output to a method in Controller
  501. log_message('debug', "CRUD: initialize a callback to '{$callback}'");
  502. $this->CI->{$callback}($data['response']);
  503. }
  504. elseif ( trim($view) !== '')
  505. {
  506. // output using CRUD viewer
  507. $this->_callback_viewer($data['response'], $config);
  508. }
  509. else
  510. {
  511. // return the data
  512. return $data;
  513. }
  514. }
  515. /**
  516. * Prepare configuration from $this->get (Retrieve)
  517. *
  518. * @access private
  519. * @param object $data
  520. * @return
  521. */
  522. private function _prepare_get($config)
  523. {
  524. log_message('debug', "CRUD: initialize method '_prepared_get'");
  525. // set default model to 'model', unless specified otherwise
  526. $model = 'model';
  527. if ( trim($this->config['model']) !== '') {
  528. $model = $this->config['model'];
  529. }
  530. // default configuration array
  531. $default = array (
  532. 'model' => $model,
  533. 'method' => 'get',
  534. 'callback' => '',
  535. 'callback_xhr' => '',
  536. 'order_by' => '',
  537. 'sort_by' => 'ASC',
  538. 'limit' => 30,
  539. 'offset' => 0,
  540. 'base_url' => current_url(),
  541. 'suffix_url' => '',
  542. 'enable_ui' => $this->config['enable_ui'],
  543. 'output' => array (),
  544. 'view' => '',
  545. 'header' => array (),
  546. 'cols' => array (),
  547. 'no_record' => '',
  548. 'enable_table' => TRUE,
  549. 'table_template' => array (),
  550. 'pagination_template' => array(),
  551. 'is_accessible' => TRUE
  552. );
  553. // using 'segment_id' to detect offset for pagination
  554. if ( ! isset($config['offset']) && $this->config['segment_id'] > 0) {
  555. $config['offset'] = $this->CI->uri->segment($this->config['segment_id'], 0);
  556. }
  557. if ( ! isset($config['sort_by']) && $this->config['segment_sort'] > 0) {
  558. $config['sort_by'] = $this->CI->uri->segment($this->config['segment_sort'], $default['sort_by']);
  559. $this->_sort_by = $config['sort_by'];
  560. }
  561. if ( ! isset($config['order_by']) && $this->config['segment_order'] > 0) {
  562. $config['order_by'] = $this->CI->uri->segment($this->config['segment_order'], $default['order_by']);
  563. }
  564. $result = array_merge($default, $config);
  565. $this->_order_by = $result['order_by'];
  566. $this->_sort_by = $result['sort_by'];
  567. return $result;
  568. }
  569. /**
  570. * Prepare configuration for modify (create, update & retrieve single)
  571. *
  572. * @access private
  573. * @param object $data
  574. * @return
  575. */
  576. private function _prepare_set($config)
  577. {
  578. log_message('debug', "CRUD: initialize method '_prepared_set'");
  579. // set default model to 'model', unless specified otherwise
  580. $model = 'model';
  581. if ( trim($this->config['model']) !== '') {
  582. $model = $this->config['model'];
  583. }
  584. // default configuration array
  585. $default = array (
  586. 'id' => 0,
  587. 'model' => $model,
  588. 'method' => 'update',
  589. 'callback' => '',
  590. 'callback_xhr' => '',
  591. 'prefix' => 'default',
  592. 'form_template' => array(),
  593. 'action' => current_url(),
  594. 'multipart' => FALSE,
  595. 'fields' => 'fields',
  596. 'data' => 'get_one',
  597. 'enable_ui' => $this->config['enable_ui'],
  598. 'output' => array (),
  599. 'view' => '',
  600. 'view_read' => '',
  601. 'view_create' => '',
  602. 'view_update' => '',
  603. 'is_accessible' => TRUE
  604. );
  605. // using 'segment_id' to detect data identity (only support integer)
  606. if ( ! isset($config['id']) && $this->config['segment_id'] > 0) {
  607. $config['id'] = $this->CI->uri->segment($this->config['segment_id'], 0);
  608. }
  609. return array_merge($default, $config);
  610. }
  611. /**
  612. * Prepare configuration for remove (delete)
  613. *
  614. * @access private
  615. * @param object $data
  616. * @return
  617. */
  618. private function _prepare_remove($config)
  619. {
  620. log_message('debug', "CRUD: initialize method '_prepared_remove'");
  621. $model = 'model';
  622. if (trim($this->config['model']) !== '') {
  623. $model = $this->config['model'];
  624. }
  625. $default = array (
  626. 'id' => 0,
  627. 'model' => $model,
  628. 'method' => 'remove',
  629. 'callback' => '',
  630. 'callback_xhr' => '',
  631. 'enable_ui' => $this->config['enable_ui'],
  632. 'output' => array (),
  633. 'view' => '',
  634. 'is_accessible' => TRUE
  635. );
  636. if ( ! isset($config['id']) && $this->config['segment_id'] > 0) {
  637. $config['id'] = $this->CI->uri->segment($this->config['segment_id'], 0);
  638. }
  639. return array_merge($default, $config);
  640. }
  641. /**
  642. * Determine source of data from Model; Array, Method or Property
  643. *
  644. * @access private
  645. * @param object $data
  646. * @param object $prefix
  647. * @return
  648. */
  649. private function _organizer($config, $prefix)
  650. {
  651. $data = $config[$prefix];
  652. $model = $config['model'];
  653. // $output should be an array, otherwise assume it referring
  654. // to either a method or property under model
  655. if ( !! is_string($data) && trim($data) !== '') {
  656. if ( !! method_exists($this->CI->{$model}, $data)) {
  657. // get the return value from method under model
  658. $data = $this->CI->{$model}->{$data}($config['id']);
  659. }
  660. elseif ( !! property_exists($this->CI->{$model}, $data)) {
  661. // get the value from property under model
  662. $data = $this->CI->{$model}->{$data};
  663. }
  664. }
  665. if ( !is_array($data)) {
  666. // to be save return an empty array
  667. $data = array ();
  668. }
  669. return $data;
  670. }
  671. /**
  672. * Prepare Error output to browser
  673. *
  674. * @access private
  675. * @return
  676. */
  677. private function _callback_404()
  678. {
  679. log_message('debug', "CRUD: initialize method '_callback_404'");
  680. $view = ( ! empty($this->config['404']) ? $this->config['404'] : '');
  681. if ( ! isset($view) || trim($view) === '') {
  682. show_404();
  683. }
  684. else {
  685. if ( !! property_exists($this->CI, 'ui') && !! $this->config['enable_ui']) {
  686. // Using Template for CI: $this->ui
  687. $this->CI->ui->set_title('Module not accessible');
  688. $this->CI->ui->view($view);
  689. if ( !! $this->config['auto_render']) {
  690. $this->CI->ui->render();
  691. }
  692. }
  693. else {
  694. // Using CI default template
  695. $this->CI->load->view($view);
  696. }
  697. }
  698. }
  699. /**
  700. * Prepare CRUD output to browser
  701. *
  702. * @access private
  703. * @param object $scaffold [optional]
  704. * @param object $output [optional]
  705. * @param object $view [optional]
  706. * @return
  707. */
  708. private function _callback_viewer($scaffold = array (), $config = array ())
  709. {
  710. log_message('debug', "CRUD: initialize method '_callback_viewer'");
  711. $data = array_merge($config['output'], $scaffold);
  712. list($title, $view, $pre_callback, $post_callback, $enable_ui) = $this->_prepare_viewer($data, $config);
  713. $data['title'] = $title;
  714. // if Template for CI is loaded: $this->ui
  715. if ( !! property_exists($this->CI, 'ui') && !! $enable_ui) {
  716. if (trim($title) !== '') {
  717. $this->CI->ui->set_title($title);
  718. }
  719. if ( !! method_exists($this->CI, $pre_callback)) {
  720. log_message('debug', "CRUD: load pre_callback '{$pre_callback}'");
  721. $this->CI->{$pre_callback}($data, $config, $this->_type, $this->_id);
  722. }
  723. if ($view != FALSE && trim($view) != '') {
  724. log_message('debug', "CRUD: load view '{$view}'");
  725. $this->CI->ui->view($view, $data);
  726. }
  727. if ( !! method_exists($this->CI, $post_callback)) {
  728. log_message('debug', "CRUD: load post_callback '{$post_callback}'");
  729. $this->CI->{$post_callback}($data, $config, $this->_type, $this->_id);
  730. }
  731. if ( !! $this->config['auto_render']) {
  732. log_message('debug', "CRUD: auto render Template Class");
  733. $this->CI->ui->render();
  734. }
  735. }
  736. else {
  737. // Using CI default template
  738. if ( !! method_exists($this->CI, $pre_callback)) {
  739. log_message('debug', "CRUD: load pre_callback '{$pre_callback}'");
  740. $this->CI->{$pre_callback}($data, $config, $this->_type, $this->_id);
  741. }
  742. if ($view != FALSE && trim($view) != '') {
  743. log_message('debug', "CRUD: load view '{$view}' using CI Loader Class");
  744. $this->CI->load->view($view, $data);
  745. }
  746. if ( !! method_exists($this->CI, $post_callback)) {
  747. log_message('debug', "CRUD: load post_callback '{$post_callback}'");
  748. $this->CI->{$post_callback}($data, $config, $this->_type, $this->_id);
  749. }
  750. }
  751. }
  752. private function _prepare_viewer($data, $config)
  753. {
  754. log_message('debug', "CRUD: initialize method '_prepare_viewer'");
  755. $title = '';
  756. $view = $config['view'];
  757. $pre_callback = '';
  758. $post_callback = '';
  759. $enable_ui = $config['enable_ui'];
  760. // Automatically set <title> if available
  761. if (isset($data['title'])) {
  762. $title = $data['title'];
  763. }
  764. if (isset($data['pre_callback'])) {
  765. $pre_callback = $data['pre_callback'];
  766. }
  767. if (isset($data['post_callback'])) {
  768. $post_callback = $data['post_callback'];
  769. }
  770. if ($this->_type === 'get_one' && ((is_int($this->_id) && $this->_id > 0) || (is_string($this->_id) && trim($this->_id) !== ''))) {
  771. if (isset($data['title_read'])) {
  772. $title = $data['title_read'];
  773. }
  774. if (isset($config['view_read']) && trim($config['view_read']) != '') {
  775. $view = $config['view_read'];
  776. }
  777. if (isset($data['pre_callback_read'])) {
  778. $pre_callback = $data['pre_callback_read'];
  779. }
  780. if (isset($data['post_callback_read'])) {
  781. $post_callback = $data['post_callback_read'];
  782. }
  783. if (isset($data['enable_ui_read']) && is_bool($data['enable_ui_read'])) {
  784. $enable_ui = $data['enable_ui_read'];
  785. }
  786. }
  787. if ($this->_type === 'set' && ((is_int($this->_id) && $this->_id >= 0) || is_string($this->_id))) {
  788. if (isset($data['title_update'])) {
  789. $title = $data['title_update'];
  790. }
  791. if (isset($config['view_update']) && trim($config['view_update']) != '') {
  792. $view = $config['view_update'];
  793. }
  794. if (isset($data['pre_callback_update'])) {
  795. $pre_callback = $data['pre_callback_update'];
  796. }
  797. if (isset($data['pre_callback_update'])) {
  798. $pre_callback = $data['pre_callback_update'];
  799. }
  800. if (isset($data['post_callback_update'])) {
  801. $post_callback = $data['post_callback_update'];
  802. }
  803. if (isset($data['enable_ui_update']) && is_bool($data['enable_ui_update'])) {
  804. $enable_ui = $data['enable_ui_update'];
  805. }
  806. }
  807. if ($this->_type === 'set' && ((is_int($this->_id) && $this->_id === 0) || (is_string($this->_id) && (trim($this->_id) === '' || intval($this->_id) === 0)))) {
  808. if (isset($data['title_create'])) {
  809. $title = $data['title_create'];
  810. }
  811. if (isset($config['view_create']) && trim($config['view_create']) != '') {
  812. $view = $config['view_create'];
  813. }
  814. if (isset($data['pre_callback_create'])) {
  815. $pre_callback = $data['pre_callback_create'];
  816. }
  817. if (isset($data['post_callback_create'])) {
  818. $post_callback = $data['post_callback_create'];
  819. }
  820. if (isset($data['enable_ui_create']) && is_bool($data['enable_ui_create'])) {
  821. $enable_ui = $data['enable_ui_create'];
  822. }
  823. }
  824. return array ($title, $view, $pre_callback, $post_callback, $enable_ui);
  825. }
  826. private function _args_to_array($args = array(), $option = array (), $offset = 1)
  827. {
  828. $output = array ();
  829. if (count($args) == $offset) {
  830. foreach ($option as $key => $val) {
  831. if (isset($args[$key])) {
  832. $output[$val] = $args[$key];
  833. }
  834. }
  835. }
  836. else {
  837. $output = $args;
  838. }
  839. return $output;
  840. }
  841. public function enable_ui()
  842. {
  843. $this->config['enable_ui'] = TRUE;
  844. }
  845. public function disable_ui()
  846. {
  847. $this->config['enable_ui'] = FALSE;
  848. }
  849. public function enable_render()
  850. {
  851. $this->config['auto_render'] = TRUE;
  852. }
  853. public function disable_render()
  854. {
  855. $this->config['auto_render'] = FALSE;
  856. }
  857. public function set_model($model = 'model')
  858. {
  859. $this->config['model'] = $model;
  860. }
  861. public function set_404($path = '')
  862. {
  863. $this->config['404'] = $path;
  864. }
  865. public function set_format()
  866. {
  867. return ($this->_get_format() == 'xhr' ? 'xhr' : 'http');
  868. }
  869. public function is_format_http()
  870. {
  871. return $this->_format === 'html';
  872. }
  873. public function is_format_xhr()
  874. {
  875. return ! $this->is_format_http();
  876. }
  877. private function _set_type($type = 'get')
  878. {
  879. $this->_type = $type;
  880. }
  881. public function get_type()
  882. {
  883. return $this->_type;
  884. }
  885. private function _set_id($id = 0)
  886. {
  887. $this->_id = $id;
  888. }
  889. private function _get_access()
  890. {
  891. return $this->CI->uri->segment($this->config['segment'], '');
  892. }
  893. private function _get_format()
  894. {
  895. return $this->CI->uri->segment($this->config['segment_xhr'], '');
  896. }
  897. public function set_segment($id = 2, $type = 'id')
  898. {
  899. $type = strtolower(trim($type));
  900. $allowed = array ('id', 'xhr', 'order', 'sort');
  901. if ( !! in_array ($type, $allowed)) {
  902. $value = "_{$type}";
  903. if ($type === 'id') {
  904. $value = "";
  905. }
  906. return $this->config["segment{$value}"] = $id;
  907. }
  908. return FALSE;
  909. }
  910. public function get_segment($type = 'id')
  911. {
  912. $allowed = array ('id', 'xhr', 'order', 'sort');
  913. if ( !! in_array ($type, $allowed)) {
  914. $value = "_{$type}";
  915. if ($type === 'id') {
  916. $value = "";
  917. }
  918. return $this->config["segment{$value}"] ;
  919. }
  920. return FALSE;
  921. }
  922. public function get_order_by($header_anchor = array (), $default = '')
  923. {
  924. $selected = trim($this->_order_by);
  925. $value = (array_key_exists ($selected, $header_anchor) ? $selected : $default);
  926. if ( !! isset($header_anchor[$value])) {
  927. return $header_anchor[$value];
  928. }
  929. else {
  930. return FALSE;
  931. }
  932. }
  933. public function get_sort_by()
  934. {
  935. return $this->_sort_by;
  936. }
  937. public function set_sort_by($selected = 'ASC')
  938. {
  939. $selected = strtoupper(trim($selected));
  940. $options = array ('ASC', 'DESC');
  941. $this->_sort_by = strtoupper((in_array($selected, $options) ? $selected : $options[0]));
  942. return $this->_sort_by;
  943. }
  944. public function toggle_sort_by()
  945. {
  946. $selected = strtoupper(trim($this->_sort_by));
  947. $options = array ('ASC', 'DESC');
  948. return strtoupper(($selected === $options[0] ? $options[1] : $options[0]));
  949. }
  950. private function _set_header_anchor($config = array (), $header = array())
  951. {
  952. $output = array ();
  953. $count = 0;
  954. foreach ($header as $key => $value) {
  955. $uri = '';
  956. if ( ! is_int($key) && trim($key) != '') {
  957. $uri = $config['offset'] . '/' . $key;
  958. if ($this->_order_by == $key) {
  959. $uri .= '/' . strtolower($this->toggle_sort_by($this->_sort_by));
  960. }
  961. else {
  962. $uri .= '/' . strtolower($this->_sort_by);
  963. }
  964. $uri .= '/' . $config['suffix_url'];
  965. $uri = $config['base_url'] . '/' . $this->_cleanup_uri_segment($uri);
  966. }
  967. $output[$count] = $uri;
  968. $count++;
  969. }
  970. return $output;
  971. }
  972. private function _set_suffix_url($config)
  973. {
  974. $data = '';
  975. $segment = array();
  976. array_push($segment, $this->config['segment_xhr']);
  977. array_push($segment, $this->config['segment_order']);
  978. array_push($segment, $this->config['segment_sort']);
  979. $result = array_unique($segment);
  980. sort($result);
  981. $min = ($this->config['segment_id'] + 1);
  982. $max = max($result);
  983. for ($i = $min; $i <= $max; $i++) {
  984. $data .= '/' . $this->CI->uri->segment($i, '');
  985. }
  986. return $data . $config['suffix_url'];
  987. }
  988. private function _cleanup_uri_segment($uri) {
  989. $url = explode('/', $uri);
  990. $data = array ();
  991. foreach ($url as $value) {
  992. if ($value != '') {
  993. array_push($data, $value);
  994. }
  995. }
  996. return implode('/', $data);
  997. }
  998. }