PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/fuel/modules/fuel/controllers/Module.php

http://github.com/daylightstudio/FUEL-CMS
PHP | 2388 lines | 1678 code | 416 blank | 294 comment | 255 complexity | 46b38ce1205c7dad8c0cc20cb3617741 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. require_once(FUEL_PATH.'/libraries/Fuel_base_controller.php');
  3. class Module extends Fuel_base_controller {
  4. public $module_obj; // the module object
  5. public $module = ''; // the name of the module
  6. public $uploaded_data = array(); // reference to the uploaded data
  7. protected $_orig_post = array(); // used for reference
  8. function __construct($validate = TRUE)
  9. {
  10. parent::__construct($validate);
  11. $this->load->module_model(FUEL_FOLDER, 'fuel_archives_model');
  12. if (empty($this->module))
  13. {
  14. $this->module = fuel_uri_segment(1);
  15. }
  16. if (empty($this->module))
  17. {
  18. show_error(lang('cannot_determine_module', fuel_url()));
  19. }
  20. $params = array();
  21. if ($this->fuel->modules->exists($this->module, FALSE))
  22. {
  23. $this->module_obj = $this->fuel->modules->get($this->module, FALSE);
  24. $params = $this->module_obj->info();
  25. }
  26. else if ($this->fuel->modules->exists($this->module.'_'.fuel_uri_segment(2), FALSE))
  27. {
  28. // if it is a module with multiple controllers, then we'll check first and second FUEL segment with an underscore'
  29. $this->module = $this->module.'_'.fuel_uri_segment(2);
  30. if ($this->fuel->modules->exists($this->module, FALSE))
  31. {
  32. $this->module_obj = $this->fuel->modules->get($this->module, FALSE);
  33. $params = $this->module_obj->info();
  34. }
  35. }
  36. else if ($this->fuel->modules->exists(fuel_uri_segment(2), FALSE))
  37. {
  38. $this->module = fuel_uri_segment(2);
  39. $this->module_obj = $this->fuel->modules->get($this->module, FALSE);
  40. if ($this->module AND $this->module_obj)
  41. {
  42. $mod_name = $this->module_obj->name();
  43. }
  44. if (empty($mod_name))
  45. {
  46. show_error(lang('error_missing_module', fuel_uri_segment(1)));
  47. }
  48. unset($mod_name);
  49. $params = $this->module_obj->info();
  50. }
  51. // stop here if the module is disabled
  52. if (empty($params) OR $params['disabled'] === TRUE)
  53. {
  54. show_404();
  55. }
  56. foreach($params as $key => $val)
  57. {
  58. $this->$key = $val;
  59. }
  60. // load any configuration
  61. if ( ! empty($this->configuration))
  62. {
  63. if (is_array($this->configuration))
  64. {
  65. $config_module = key($this->configuration);
  66. $config_file = current($this->configuration);
  67. $this->config->module_load($config_module, $config_file);
  68. }
  69. else
  70. {
  71. $this->config->load($this->configuration);
  72. }
  73. }
  74. // load any language
  75. if ( ! empty($this->language))
  76. {
  77. if (is_array($this->language))
  78. {
  79. $lang_module = key($this->language);
  80. $lang_file = current($this->language);
  81. // now check to see if we need to load the language file or not...
  82. // we load the main language file automatically with the Fuel_base_controller.php
  83. $this->load->module_language($lang_module, $lang_file, $this->fuel->auth->user_lang());
  84. }
  85. else
  86. {
  87. $this->load->language($this->language);
  88. }
  89. }
  90. // load the model
  91. if ( ! empty($this->model_location))
  92. {
  93. $this->load->module_model($this->model_location, $this->model_name);
  94. }
  95. else
  96. {
  97. $this->load->model($this->model_name);
  98. }
  99. // get the model name
  100. $model_parts = explode('/', $this->model_name);
  101. $model = end($model_parts);
  102. // set the module_uri
  103. if (empty($this->module_uri)) $this->module_uri = $this->module;
  104. $this->js_controller_params['module'] = $this->module_uri;
  105. if ( ! empty($model))
  106. {
  107. $this->model =& $this->$model;
  108. }
  109. else
  110. {
  111. show_error(lang('incorrect_route_to_module'));
  112. }
  113. // global variables
  114. $vars = array();
  115. if ( ! empty($params['js']))
  116. {
  117. if (is_string($params['js']))
  118. {
  119. $params['js'] = preg_split("/,\s*/", $params['js']);
  120. }
  121. $vars['js'] = $params['js'];
  122. }
  123. if ( ! empty($this->nav_selected)) $vars['nav_selected'] = $this->nav_selected;
  124. $this->load->vars($vars);
  125. $this->fuel->admin->load_js_localized($params['js_localized']);
  126. if ( ! empty($this->permission) AND $validate)
  127. {
  128. $this->_validate_user($this->permission);
  129. }
  130. }
  131. // --------------------------------------------------------------------
  132. /**
  133. * Displays the list (table) view
  134. *
  135. * @access public
  136. * @return void
  137. */
  138. function index()
  139. {
  140. $this->items();
  141. }
  142. // --------------------------------------------------------------------
  143. /**
  144. * Displays the list (table) view
  145. *
  146. * @access public
  147. * @return void
  148. */
  149. function items()
  150. {
  151. $this->load->library('data_table');
  152. $filters = $this->model->filters($this->filters);
  153. if (is_object($filters) && ($filters instanceof Base_model_fields)) {
  154. $filters = $filters->get_fields();
  155. }
  156. $this->filters = array_merge($this->filters, $filters);
  157. // set the language dropdown if there is a language column
  158. if ($this->fuel->language->has_multiple() AND !empty($this->language_col) AND method_exists($this->model, 'get_languages'))
  159. {
  160. $languages = $this->model->get_languages($this->language_col);
  161. $first_option = current($languages);
  162. if (( ! empty($languages) AND (is_string($first_option) OR (is_array($first_option)) AND count($first_option) > 1)) AND empty($this->filters[$this->language_col.'_equal']))
  163. {
  164. $lang_filter = array('type' => 'select', 'options' => $languages, 'label' => lang('label_language'), 'first_option' => lang('label_select_a_language'));
  165. $this->filters[$this->language_col.'_equal'] = $lang_filter;
  166. $this->model->add_filter_join($this->language_col.'_equal', 'and');
  167. }
  168. }
  169. $params = $this->_list_process();
  170. // save page state
  171. $this->fuel->admin->save_page_state($params);
  172. // filter the list
  173. $this->_filter_list($params);
  174. // to prevent it from being called unnecessarily with ajax
  175. if ( ! is_ajax())
  176. {
  177. $item_total = $this->model->list_items_total();
  178. if ($this->single_item_navigate AND $item_total == 1)
  179. {
  180. $items = $this->model->list_items();
  181. $id = $items[0][$this->model->key_field()];
  182. // lets check a few permissions
  183. if ($this->fuel->auth->has_permission($this->permission, "edit"))
  184. {
  185. $url = fuel_url($this->module_uri.'/edit/'.$id);
  186. }
  187. elseif ($this->fuel->auth->has_permission($this->permission, "view"))
  188. {
  189. $url = fuel_url($this->module_uri.'/view/'.$id);
  190. }
  191. elseif ($this->fuel->auth->has_permission($this->permission, "show"))
  192. {
  193. $url = fuel_url($this->module_uri.'/show/'.$id);
  194. }
  195. if (!empty($url))
  196. {
  197. redirect($url);
  198. }
  199. }
  200. $this->config->set_item('enable_query_strings', FALSE);
  201. // pagination
  202. $query_str_arr = $this->input->get(NULL, TRUE);
  203. unset($query_str_arr['offset']);
  204. $query_str = ( ! empty($query_str_arr)) ? http_build_query($query_str_arr) : '';
  205. $config['base_url'] = fuel_url($this->module_uri).'/items/?'.$query_str;
  206. $uri_segment = 4 + (count(explode('/', $this->module_uri)) - 1);
  207. $config['total_rows'] = $item_total;
  208. $config['uri_segment'] = fuel_uri_index($uri_segment);
  209. $config['per_page'] = (int) $params['limit'];
  210. $config['query_string_segment'] = 'offset';
  211. $config['page_query_string'] = TRUE;
  212. $config['num_links'] = 5;
  213. $config['prev_link'] = lang('pagination_prev_page');
  214. $config['next_link'] = lang('pagination_next_page');
  215. $config['first_link'] = lang('pagination_first_link');
  216. $config['last_link'] = lang('pagination_last_link');
  217. // must reset these in case a config file has something different
  218. $config['full_tag_open'] = NULL;
  219. $config['full_tag_close'] = NULL;
  220. $config['num_tag_open'] = '&nbsp;';
  221. $config['num_tag_close'] = NULL;
  222. $config['cur_tag_open'] = '&nbsp;<strong>';
  223. $config['cur_tag_close'] = '</strong>';
  224. $config['next_tag_open'] = '&nbsp;';
  225. $config['next_tag_close'] = '&nbsp;';
  226. $config['prev_tag_open'] = '&nbsp;';
  227. $config['prev_tag_close'] = NULL;
  228. $config['first_tag_open'] = '&nbsp;';
  229. $config['first_tag_close'] = '&nbsp;';
  230. $config['last_tag_open'] = NULL;
  231. $config['last_tag_close'] = NULL;
  232. $this->pagination->initialize($config);
  233. $this->fuel->admin->set_notification(number_format($item_total).' '.pluralize($item_total, lang('num_items')), 'info');
  234. if (method_exists($this->model, 'tree'))
  235. {
  236. $vars['tree'] = "\n<ul></ul>\n";
  237. }
  238. // reset offset if total rows is less then limit
  239. if ($config['total_rows'] < $params['limit'])
  240. {
  241. $params['offset'] = 0;
  242. }
  243. }
  244. // set vars
  245. $vars['params'] = $params;
  246. $vars['table'] = '';
  247. // reload table
  248. if (is_ajax())
  249. {
  250. // data table items... check col value to know if we want to send sorting parameter
  251. if (empty($params['col']) OR empty($params['order']))
  252. {
  253. $items = $this->model->list_items($params['limit'], $params['offset']);
  254. }
  255. else
  256. {
  257. $items = $this->model->list_items($params['limit'], $params['offset'], $params['col'], $params['order']);
  258. $this->data_table->set_sorting($params['col'], $params['order']);
  259. }
  260. $has_edit_permission = $this->fuel->auth->has_permission($this->permission, "edit") ? '1' : '0';
  261. $has_delete_permission = $this->fuel->auth->has_permission($this->permission, "delete") ? '1' : '0';
  262. // set data table actions... look first for item_actions set in the fuel_modules
  263. $delete_func = function($cols) use ($has_delete_permission) {
  264. $CI =& get_instance();
  265. $link = "";
  266. if ($has_delete_permission)
  267. {
  268. if (!empty($cols[$CI->model->key_field()]))
  269. {
  270. $url = fuel_url($this->module_uri."/delete/".$cols[$CI->model->key_field()]);
  271. $link = "<a href=\"".$url."\" class=\"action_delete\">".lang("table_action_delete")."</a>";
  272. $link .= " <input type=\"checkbox\" name=\"delete[".$cols[$CI->model->key_field()]."]\" value=\"1\" id=\"delete_".$cols[$CI->model->key_field()]."\" class=\"multi_delete\"/>";
  273. }
  274. }
  275. return $link;
  276. };
  277. foreach($this->table_actions as $key => $val)
  278. {
  279. if ( ! is_int($key))
  280. {
  281. $action_type = 'url';
  282. $action_val = $this->table_actions[$key];
  283. $attrs = array();
  284. if (is_array($val))
  285. {
  286. if (isset($val['url']))
  287. {
  288. $action_type = 'url';
  289. $action_val = $val['url'];
  290. if (isset($val['attrs']))
  291. {
  292. $attrs = $val['attrs'];
  293. }
  294. }
  295. else
  296. {
  297. $action_type = key($val);
  298. $action_val = current($val);
  299. }
  300. $attrs = (isset($val['attrs'])) ? $val['attrs'] : array();
  301. }
  302. $this->data_table->add_action($key, $action_val, $action_type, $attrs);
  303. }
  304. else if (strtoupper($val) == 'EDIT')
  305. {
  306. if ($this->fuel->auth->has_permission($this->permission, "edit"))
  307. {
  308. $action_url = fuel_url($this->module_uri.'/edit/{'.$this->model->key_field().'}');
  309. $this->data_table->add_action(lang('table_action_edit'), $action_url, 'url');
  310. }
  311. }
  312. else if (strtoupper($val) == 'DELETE')
  313. {
  314. $this->data_table->add_action($val, $delete_func, 'func');
  315. }
  316. else
  317. {
  318. if (strtoupper($val) != 'VIEW' OR ( ! empty($this->preview_path) AND strtoupper($val) == 'VIEW'))
  319. {
  320. $action_name = lang('table_action_'.strtolower($val));
  321. if (empty($action_name)) $action_name = $val;
  322. $action_url = fuel_url($this->module_uri.'/'.strtolower($val).'/{'.$this->model->key_field().'}');
  323. $this->data_table->add_action($action_name, $action_url, 'url');
  324. }
  325. }
  326. }
  327. if ( ! $this->rows_selectable)
  328. {
  329. $this->data_table->id = 'data_table_noselect';
  330. $this->data_table->row_action = FALSE;
  331. }
  332. else
  333. {
  334. $this->data_table->row_action = TRUE;
  335. }
  336. $this->data_table->row_alt_class = 'alt';
  337. if ($this->model->has_auto_increment())
  338. {
  339. $this->data_table->only_data_fields = array($this->model->key_field());
  340. }
  341. // Key and boolean fields are data only
  342. // $this->data_table->only_data_fields = array_merge(array($this->model->key_field()), $this->model->boolean_fields);
  343. $this->data_table->auto_sort = TRUE;
  344. $this->data_table->actions_field = 'last';
  345. $this->data_table->no_data_str = lang('no_data');
  346. $this->data_table->lang_prefix = 'form_label_';
  347. $this->data_table->row_id_key = $this->model->key_field();
  348. $boolean_fields = $this->model->boolean_fields;
  349. if ( ! in_array('published', $boolean_fields)) $boolean_fields[] = 'published';
  350. if ( ! in_array('active', $boolean_fields)) $boolean_fields[] = 'active';
  351. $has_publish_permission = ($this->fuel->auth->has_permission($this->permission, 'publish')) ? '1' : '0';
  352. $has_edit_permission = $this->fuel->auth->has_permission($this->permission, 'edit') ? '1' : '0';
  353. $_publish_toggle_callback = function($cols, $heading) {
  354. $can_publish = (($heading == "published" OR $heading == "active") AND '.$has_publish_permission.' OR
  355. (($heading != "published" AND $heading != "active") AND '.$has_edit_permission.'));
  356. $no = lang("form_enum_option_no");
  357. $yes = lang("form_enum_option_yes");
  358. $col_txt = lang('click_to_toggle');
  359. $key_field = $this->model->key_field();
  360. // boolean fields
  361. if (is_null($cols[$heading]) OR $cols[$heading] == "")
  362. {
  363. return "";
  364. }
  365. else if (!is_true_val($cols[$heading]))
  366. {
  367. $text_class = ($can_publish) ? "publish_text unpublished toggle_on" : "unpublished";
  368. $action_class = ($can_publish) ? "publish_action unpublished hidden" : "unpublished hidden";
  369. return '<span class="publish_hover"><span class="'.$text_class.'" id="row_published_'.$cols[$key_field].'" data-field="'.$heading.'">'.$no.'</span><span class="'.$action_class.'">'.$col_txt.'</span></span>';
  370. }
  371. else
  372. {
  373. $text_class = ($can_publish) ? "publish_text published toggle_off" : "published";
  374. $action_class = ($can_publish) ? "publish_action published hidden" : "published hidden";
  375. return '<span class="publish_hover"><span class="'.$text_class.'" id="row_published_'.$cols[$key_field].'" data-field="'.$heading.'">'.$yes.'</span><span class="'.$action_class.'">'.$col_txt.'</span></span>';
  376. }
  377. };
  378. foreach($boolean_fields as $bool)
  379. {
  380. $this->data_table->add_field_formatter($bool, $_publish_toggle_callback);
  381. }
  382. $this->data_table->auto_sort = TRUE;
  383. $heading_sort_func = (isset($this->disable_heading_sort) AND $this->disable_heading_sort) ? '' : 'fuel.sortList';
  384. $this->data_table->sort_js_func = $heading_sort_func;
  385. $this->data_table->assign_data($items, $this->table_headers);
  386. $vars['table'] = $this->data_table->render();
  387. if ( ! empty($items[0]) AND ( ! empty($this->precedence_col) AND isset($items[0][$this->precedence_col])))
  388. {
  389. $vars['params']['precedence'] = 1;
  390. }
  391. $this->load->module_view(FUEL_FOLDER, '_blocks/module_list_table', $vars);
  392. return;
  393. }
  394. else
  395. {
  396. $this->load->library('form_builder');
  397. $this->js_controller_params['method'] = 'items';
  398. $this->js_controller_params['precedence_col'] = $this->precedence_col;
  399. $vars['table'] = $this->load->module_view(FUEL_FOLDER, '_blocks/module_list_table', $vars, TRUE);
  400. $vars['pagination'] = $this->pagination->create_links();
  401. // for extra module 'filters'
  402. $field_values = array();
  403. foreach($this->filters as $key => $val)
  404. {
  405. $field_values[$key] = $params[$key];
  406. }
  407. $this->form_builder->question_keys = array();
  408. //$this->form_builder->hidden = (array) $this->model->key_field();
  409. $this->form_builder->label_layout = 'left';
  410. $this->form_builder->load_custom_fields(APPPATH.'config/custom_fields.php');
  411. $this->form_builder->set_validator($this->model->get_validation());
  412. $this->form_builder->submit_value = NULL;
  413. $this->form_builder->use_form_tag = FALSE;
  414. $this->form_builder->set_fields($this->filters);
  415. $this->form_builder->display_errors = FALSE;
  416. $this->form_builder->css_class = 'more_filters';
  417. if ($this->config->item('date_format'))
  418. {
  419. $this->form_builder->date_format = $this->config->item('date_format');
  420. }
  421. $this->form_builder->set_field_values($field_values);
  422. if (method_exists($this->model, 'friendly_filter_info'))
  423. {
  424. $friendly_filter_info = $this->model->friendly_filter_info($field_values);
  425. if ( ! empty($friendly_filter_info))
  426. {
  427. $vars['info'] = $friendly_filter_info;
  428. }
  429. }
  430. // keycheck is already put in place by $this->form->close() in module_list layout
  431. $this->form_builder->key_check = FALSE;
  432. $vars['more_filters'] = $this->form_builder->render_divs();
  433. $vars['actions'] = $this->load->module_view(FUEL_FOLDER, '_blocks/module_list_actions', $vars, TRUE);
  434. $vars['form_action'] = $this->module_uri.'/items';
  435. $vars['form_method'] = 'get';
  436. $vars['query_string'] = $query_str;
  437. $vars['description'] = $this->description;
  438. $crumbs = array($this->module_uri => $this->module_name);
  439. $this->fuel->admin->set_titlebar($crumbs);
  440. $inline = $this->input->get('inline', TRUE);
  441. $this->fuel->admin->set_inline($inline);
  442. if ($inline === TRUE)
  443. {
  444. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT_TITLEBAR);
  445. }
  446. $this->fuel->admin->render($this->views['list'], $vars, '', FUEL_FOLDER);
  447. }
  448. }
  449. // --------------------------------------------------------------------
  450. /**
  451. * Displays the list (table) view but inline without the left menu
  452. *
  453. * @access public
  454. * @return void
  455. */
  456. function inline_items()
  457. {
  458. $this->items();
  459. }
  460. // --------------------------------------------------------------------
  461. /**
  462. * Processes the list view filters and returns an array of parameters
  463. *
  464. * @access protected
  465. * @return array
  466. */
  467. protected function _list_process()
  468. {
  469. $this->load->library('pagination');
  470. $this->load->helper('convert');
  471. $this->load->helper('cookie');
  472. /* PROCESS PARAMS BEGIN */
  473. $filters = array();
  474. $page_state = $this->fuel->admin->get_page_state($this->module_uri);
  475. unset($page_state['offset']);
  476. $defaults = array();
  477. $defaults['col'] = (!empty($this->default_col)) ? $this->default_col : $this->display_field;
  478. $defaults['order'] = (isset($this->default_order)) ? $this->default_order : 'asc';
  479. $defaults['offset'] = 0;
  480. $defaults['limit'] = key($this->limit_options);
  481. $defaults['search_term'] = '';
  482. $defaults['view_type'] = 'list';
  483. $defaults['extra_filters'] = array();
  484. $defaults['precedence'] = 0;
  485. //$defaults['language'] = '';
  486. // custom module filters defaults
  487. foreach($this->filters as $key => $val)
  488. {
  489. $defaults[$key] = (isset($val['default'])) ? $val['default'] : NULL;
  490. }
  491. $posted = array();
  492. if ( ! empty($_POST) OR !empty($_GET))
  493. {
  494. $posted['search_term'] = $this->input->get_post('search_term', TRUE);
  495. $posted_vars = array('col', 'order', 'limit', 'offset', 'precedence', 'view_type');
  496. foreach($posted_vars as $val)
  497. {
  498. if ($this->input->get_post($val)) $posted[$val] = $this->input->get_post($val, TRUE);
  499. }
  500. // custom module filters
  501. $extra_filters = array();
  502. foreach($this->filters as $key => $val)
  503. {
  504. if (isset($_POST[$key]) OR isset($_GET[$key]))
  505. {
  506. $posted[$key] = $this->input->get_post($key, TRUE);
  507. // get the raw key without the comparison operators that the model uses
  508. $raw_key = preg_replace(array('#_from$#', '#_fromequal$#', '#_to$#', '#_toequal$#', '#_equal$#'), '', $key);
  509. // manipulate the value if it's a date time field
  510. if (method_exists($this->model, 'field_type'))
  511. {
  512. $field_type = $this->model->field_type($raw_key);
  513. if (is_date_format($posted[$key]) AND $field_type == 'datetime' OR $field_type == 'date' AND (int) $posted[$key] !== 0)
  514. {
  515. $date = ($this->input->get_post($key) AND is_date_format($this->input->get_post($key))) ? current(explode(" ", $this->input->get_post($key))) : "";
  516. $hr = ($this->input->get_post($key.'_hour') AND (int)$this->input->get_post($key.'_hour') > 0 AND (int)$this->input->get_post($key.'_hour') < 24) ? $this->input->get_post($key.'_hour') : "";
  517. $min = ($this->input->get_post($key.'_min') AND is_numeric($this->input->get_post($key.'_min'))) ? $this->input->get_post($key.'_min') : "00";
  518. $ampm = ($this->input->get_post($key.'_am_pm') AND $hr AND $min) ? $this->input->get_post($key.'_am_pm') : "";
  519. if ( ! empty($ampm) AND !empty($hr) AND $hr > 12)
  520. {
  521. if ($hr > 24)
  522. {
  523. $hr = "00";
  524. }
  525. else
  526. {
  527. $hr = (int) $hr - 12;
  528. $ampm = "pm";
  529. }
  530. }
  531. $posted[$key] = $date;
  532. if ( ! empty($hr)) $posted[$key] .= " ".$hr.":".$min.$ampm;
  533. $posted[$key] = date('Y-m-d H:i:s', strtotime($posted[$key]));
  534. }
  535. }
  536. $this->filters[$key]['value'] = $posted[$key];
  537. $extra_filters[$key] = $posted[$key];
  538. }
  539. }
  540. $posted['extra_filters'] = $extra_filters;
  541. }
  542. $params = array_merge($defaults, $page_state, $posted);
  543. //$params = array_merge($defaults, $uri_params, $posted);
  544. if ($params['search_term'] == lang('label_search')) $params['search_term'] = NULL;
  545. /* PROCESS PARAMS END */
  546. return $params;
  547. }
  548. // --------------------------------------------------------------------
  549. /**
  550. * Adds filters to the model
  551. *
  552. * @access protected
  553. * @return void
  554. */
  555. function _filter_list($params)
  556. {
  557. // create search filter
  558. $search_key = !empty($this->search_field) ? $this->search_field : $this->display_field;
  559. $filters[$search_key] = trim($params['search_term']);
  560. // sort of hacky here... to make it easy for the model to just filter on the search term (like the users model)
  561. $this->model->filter_value = trim($params['search_term']);
  562. foreach($this->filters as $key => $val)
  563. {
  564. $filters[$key] = $params[$key];
  565. if ( ! empty($val['filter_join']))
  566. {
  567. if ( ! is_array($this->model->filter_join[$key]))
  568. {
  569. settype($this->model->filter_join, 'array');
  570. }
  571. $this->model->filter_join[$key] = $val['filter_join'];
  572. }
  573. }
  574. // set model filters before pagination and setting table data
  575. if (method_exists($this->model, 'add_filters'))
  576. {
  577. $this->model->add_filters($filters);
  578. }
  579. }
  580. // --------------------------------------------------------------------
  581. /**
  582. * Displays the tree view
  583. *
  584. * @access public
  585. * @return void
  586. */
  587. function items_tree()
  588. {
  589. // tree
  590. if (method_exists($this->model, 'tree') AND is_ajax())
  591. {
  592. $params = $this->_list_process();
  593. $this->load->library('menu');
  594. $this->menu->depth = NULL; // as deep as it goes
  595. $this->menu->use_titles = FALSE;
  596. $this->menu->root_value = 0;
  597. $this->model->add_filters($params['extra_filters']);
  598. $menu_items = $this->model->tree();
  599. if ( ! empty($menu_items))
  600. {
  601. $output = $this->menu->render($menu_items);
  602. }
  603. else
  604. {
  605. $output = '<div>'.lang('no_data').'</div>';
  606. }
  607. $this->output->set_output($output);
  608. }
  609. }
  610. // --------------------------------------------------------------------
  611. /**
  612. * Saves the precedence of fields
  613. *
  614. * @access public
  615. * @return void
  616. */
  617. function items_precedence()
  618. {
  619. if (is_ajax() AND ! empty($_POST['data_table']) AND ! empty($this->precedence_col))
  620. {
  621. if (is_array($_POST['data_table']))
  622. {
  623. $i = 0;
  624. foreach($_POST['data_table'] as $row)
  625. {
  626. if ( ! empty($row))
  627. {
  628. $values = array($this->precedence_col => $i);
  629. $where = array($this->model->key_field() => $row);
  630. $this->model->update($values, $where);
  631. }
  632. $i++;
  633. }
  634. // clear cache
  635. $this->_clear_cache();
  636. }
  637. }
  638. }
  639. // --------------------------------------------------------------------
  640. /**
  641. * Displays the fields to create a record (form view)
  642. *
  643. * @access public
  644. * @param string The name of a field, or fields separated by colon to display in the form (optional)
  645. * @param string Determines whether to redirect the page after save or not
  646. * @return void
  647. */
  648. function create($field = NULL, $redirect = TRUE)
  649. {
  650. $id = NULL;
  651. // check that the action even exists and if not, show a 404
  652. if ( ! $this->fuel->auth->module_has_action('save'))
  653. {
  654. show_404();
  655. }
  656. // check permissions
  657. if ( ! $this->fuel->auth->has_permission($this->module_obj->permission, 'create'))
  658. {
  659. show_error(lang('error_no_permissions', fuel_url()));
  660. }
  661. $inline = $this->fuel->admin->is_inline();
  662. if (isset($_POST[$this->model->key_field()])) // check for dupes
  663. {
  664. if ($id = $this->_process_create() AND !has_errors())
  665. {
  666. if ($inline === TRUE)
  667. {
  668. $url = fuel_uri($this->module_uri.'/inline_edit/'.$id.'/'.$field, TRUE);
  669. }
  670. else
  671. {
  672. $url = fuel_uri($this->module_uri.'/edit/'.$id.'/'.$field, TRUE);
  673. }
  674. // save any tab states
  675. $this->_save_tab_state($id);
  676. if ($redirect)
  677. {
  678. if ( ! $this->fuel->admin->has_notification(Fuel_admin::NOTIFICATION_SUCCESS))
  679. {
  680. $this->fuel->admin->set_notification(lang('data_saved'), Fuel_admin::NOTIFICATION_SUCCESS);
  681. }
  682. redirect($url);
  683. }
  684. }
  685. }
  686. $shell_vars = $this->_shell_vars($id);
  687. $get = (array) $this->input->get(NULL, TRUE);
  688. $post = (array) $this->input->post(NULL, TRUE);
  689. $passed_init_vars = array_filter(array_merge($get, $post));
  690. $form_vars = $this->_form_vars($id, $passed_init_vars, $field, $inline);
  691. $vars = array_merge($shell_vars, $form_vars);
  692. $vars['action'] = 'create';
  693. $vars['related_items'] = $this->model->related_items(array());
  694. $crumbs = array($this->module_uri => $this->module_name, lang('action_create'));
  695. $this->fuel->admin->set_titlebar($crumbs);
  696. $this->fuel->admin->set_inline($inline);
  697. if ( ! empty($field) AND strpos($field, ':') === FALSE)
  698. {
  699. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT_NO_ACTION);
  700. }
  701. else if ($inline === TRUE)
  702. {
  703. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT);
  704. }
  705. $vars['actions'] = $this->load->module_view(FUEL_FOLDER, '_blocks/module_inline_actions', $vars, TRUE);
  706. $this->fuel->admin->render($this->views['create_edit'], $vars, '', FUEL_FOLDER);
  707. return $id;
  708. }
  709. // --------------------------------------------------------------------
  710. /**
  711. * The same as the create method but does not show the left menu
  712. *
  713. * @access public
  714. * @param string The name of a field, or fields separated by colon to display in the form (optional)
  715. * @param string Determines whether to redirect the page after save or not
  716. * @return void
  717. */
  718. function inline_create($field = NULL)
  719. {
  720. $this->fuel->admin->set_inline(TRUE);
  721. $this->create($field);
  722. }
  723. // --------------------------------------------------------------------
  724. /**
  725. * Duplicates a record. Similar to edit but without the record ID attached.
  726. *
  727. * @access public
  728. * @return void
  729. */
  730. function duplicate()
  731. {
  732. $_POST[$this->model->key_field()] = 'dup';
  733. $this->create();
  734. }
  735. protected function _process_create()
  736. {
  737. // reset dup id
  738. if ($_POST[$this->model->key_field()] == 'dup')
  739. {
  740. $_POST[$this->model->key_field()] = '';
  741. // alter duplicate information if there is a hook
  742. $_POST = $this->model->on_duplicate($_POST);
  743. $this->load->library('form_builder');
  744. $fb = new Form_builder();
  745. $fb->load_custom_fields(APPPATH.'config/custom_fields.php');
  746. $fields = $this->model->form_fields($_POST);
  747. $fb->set_fields($fields);
  748. $fb->post_process_field_values();// manipulates the $_POST values directly
  749. }
  750. else
  751. {
  752. $this->model->on_before_post($this->input->post());
  753. $posted = $this->_process();
  754. // set publish status to no if you do not have the ability to publish
  755. if ( ! $this->fuel->auth->has_permission($this->permission, 'publish') AND ! $this->fuel->auth->has_permission($this->permission, 'activate'))
  756. {
  757. $posted['published'] = 'no';
  758. $posted['active'] = 'no';
  759. }
  760. $model = $this->model;
  761. // run before_create hook
  762. $this->_run_hook('before_create', $posted);
  763. // run before_save hook
  764. $this->_run_hook('before_save', $posted);
  765. // save the data
  766. $id = $this->model->save($posted);
  767. if (empty($id))
  768. {
  769. add_error(lang('error_invalid_record'));
  770. return FALSE;
  771. }
  772. // add id value to the posted array
  773. if ( ! is_array($this->model->key_field()))
  774. {
  775. $posted[$this->model->key_field()] = $id;
  776. // replace any {id} placeholder values
  777. foreach ($posted as $key => $val)
  778. {
  779. if (is_string($val))
  780. {
  781. $posted[$key] = str_replace('{'.$this->model->key_field().'}', $id, $val);
  782. }
  783. }
  784. }
  785. // process $_FILES
  786. if ( ! $this->_process_uploads($posted))
  787. {
  788. return FALSE;
  789. }
  790. $this->model->on_after_post($posted);
  791. if (!$this->model->is_valid())
  792. {
  793. add_errors($this->model->get_errors());
  794. }
  795. else
  796. {
  797. // archive data
  798. $archive_data = $this->model->cleaned_data();
  799. $archive_data[$this->model->key_field()] = $id;
  800. if ($this->archivable) $this->model->archive($id, $archive_data);
  801. $data = $this->model->find_one_array(array($this->model->table_name().'.'.$this->model->key_field() => $id));
  802. // run after_create hook
  803. $this->_run_hook('after_create', $data);
  804. // run after_save hook
  805. $this->_run_hook('after_save', $data);
  806. if ( ! empty($data))
  807. {
  808. $msg_data = $this->model->display_name($data);
  809. $msg = lang('module_edited', $this->module_name, $msg_data);
  810. $this->fuel->logs->write($msg);
  811. $this->_clear_cache();
  812. return $id;
  813. }
  814. }
  815. }
  816. }
  817. // --------------------------------------------------------------------
  818. /**
  819. * Displays the fields to edit a record (form view)
  820. *
  821. * @access public
  822. * @param int The ID value of the record to edit
  823. * @param string The name of a field, or fields separated by colon to display in the form (optional)
  824. * @param string Determines whether to redirect the page after save or not
  825. * @return void
  826. */
  827. function edit($id = NULL, $field = NULL, $redirect = TRUE)
  828. {
  829. // check that the action even exists and if not, show a 404
  830. if ( ! $this->fuel->auth->module_has_action('save') AND $this->displayonly === FALSE)
  831. {
  832. show_404();
  833. }
  834. // check permissions
  835. if ( ! $this->fuel->auth->has_permission($this->module_obj->permission, 'edit') AND ! $this->fuel->auth->has_permission($this->module_obj->permission, 'create'))
  836. {
  837. show_error(lang('error_no_permissions', fuel_url()));
  838. }
  839. $inline = $this->fuel->admin->is_inline();
  840. if ($this->input->post($this->model->key_field()))
  841. {
  842. if ($this->_process_edit($id) AND !has_errors())
  843. {
  844. if ($inline === TRUE)
  845. {
  846. $url = fuel_uri($this->module_uri.'/inline_edit/'.$id.'/'.$field, TRUE);
  847. }
  848. else
  849. {
  850. $url = fuel_uri($this->module_uri.'/edit/'.$id.'/'.$field, TRUE);
  851. }
  852. if ($redirect)
  853. {
  854. if ( ! $this->fuel->admin->has_notification(Fuel_admin::NOTIFICATION_SUCCESS))
  855. {
  856. $this->fuel->admin->set_notification(lang('data_saved'), Fuel_admin::NOTIFICATION_SUCCESS);
  857. }
  858. redirect($url);
  859. }
  860. }
  861. }
  862. //$vars = $this->_form($id);
  863. $data = $this->_saved_data($id);
  864. if (empty($data))
  865. {
  866. show_error(lang('error_invalid_record'));
  867. }
  868. $action = ( ! empty($data[$this->model->key_field()])) ? 'edit' : 'create';
  869. // check model first for preview path method
  870. if (method_exists($this->model, 'preview_path'))
  871. {
  872. $this->preview_path = $this->model->preview_path($data, $this->preview_path);
  873. }
  874. else
  875. {
  876. // otherwise, substitute data values into preview path
  877. $this->preview_path = $this->module_obj->url($data);
  878. }
  879. $shell_vars = $this->_shell_vars($id, $action, $data);
  880. $form_vars = $this->_form_vars($id, $data, $field, $inline);
  881. $vars = array_merge($shell_vars, $form_vars);
  882. $vars['data'] = $data;
  883. $vars['action'] = $action;
  884. $vars['related_items'] = $this->model->related_items($data);
  885. // active or publish fields
  886. if (isset($data['published']))
  887. {
  888. $vars['publish'] = ( ! empty($data['published']) AND is_true_val($data['published'])) ? 'unpublish' : 'publish';
  889. }
  890. if (isset($data['active']))
  891. {
  892. $vars['activate'] = ( ! empty($data['active']) AND is_true_val($data['active'])) ? 'deactivate' : 'activate';
  893. }
  894. if ( ! empty($field) AND strpos($field, ':') === FALSE)
  895. {
  896. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT_NO_ACTION);
  897. }
  898. else if ($inline === TRUE)
  899. {
  900. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT);
  901. }
  902. $crumbs = array($this->module_uri => $this->module_name);
  903. $msg_data = $this->model->display_name($data);
  904. if ( ! empty($msg_data))
  905. {
  906. $crumbs[''] = character_limiter(strip_tags($msg_data), 100);
  907. }
  908. $this->fuel->admin->set_titlebar($crumbs);
  909. $vars['actions'] = $this->load->module_view(FUEL_FOLDER, '_blocks/module_create_edit_actions', $vars, TRUE);
  910. $this->fuel->admin->render($this->views['create_edit'], $vars, '', FUEL_FOLDER);
  911. // do this after rendering so it doesn't render current page'
  912. if ( ! empty($msg_data) AND $inline !== TRUE)
  913. {
  914. $this->fuel->admin->add_recent_page($this->uri->uri_string(), $this->module_name.': '.$msg_data, $this->module);
  915. }
  916. }
  917. // --------------------------------------------------------------------
  918. /**
  919. * The same as the edit method but does not show the left menu
  920. *
  921. * @access public
  922. * @param int The ID value of the record to edit
  923. * @param string The name of a field, or fields separated by colon to display in the form (optional)
  924. * @return void
  925. */
  926. function inline_edit($id = NULL, $field = NULL)
  927. {
  928. if (empty($id))
  929. {
  930. show_404();
  931. }
  932. $this->fuel->admin->set_inline(TRUE);
  933. $this->edit($id, $field);
  934. }
  935. // --------------------------------------------------------------------
  936. /**
  937. * Processes the form data to save
  938. *
  939. * @access protected
  940. * @param int The ID value of the record to edit
  941. * @return boolean
  942. */
  943. protected function _process_edit($id)
  944. {
  945. $this->model->on_before_post($this->input->post());
  946. $posted = $this->_process();
  947. // run before_edit hook
  948. $this->_run_hook('before_edit', $posted);
  949. // run before_save hook
  950. $this->_run_hook('before_save', $posted);
  951. if ($this->model->save($posted))
  952. {
  953. // process $_FILES...
  954. if ( ! $this->_process_uploads($posted))
  955. {
  956. return FALSE;
  957. }
  958. $this->model->on_after_post($posted);
  959. if ( ! $this->model->is_valid())
  960. {
  961. add_errors($this->model->get_errors());
  962. }
  963. else
  964. {
  965. // archive data
  966. $archive_data = $this->model->cleaned_data();
  967. if ($this->archivable) $this->model->archive($id, $archive_data);
  968. $data = $this->model->find_one_array(array($this->model->table_name().'.'.$this->model->key_field() => $id));
  969. // run after_edit hook
  970. $this->_run_hook('after_edit', $data);
  971. // run after_save hook
  972. $this->_run_hook('after_save', $data);
  973. $msg_data = $this->model->display_name($data);
  974. $msg = lang('module_edited', $this->module_name, $msg_data);
  975. $this->fuel->logs->write($msg);
  976. $this->_clear_cache();
  977. return TRUE;
  978. }
  979. }
  980. return FALSE;
  981. }
  982. // --------------------------------------------------------------------
  983. /**
  984. * Sanitizes the input based on the module's settings
  985. *
  986. * @access protected
  987. * @param array The array of posted data to sanitize
  988. * @return array
  989. */
  990. protected function _sanitize($data)
  991. {
  992. $posted = $data;
  993. if ( ! empty($this->sanitize_input))
  994. {
  995. // functions that are valid for sanitizing
  996. $valid_funcs = $this->fuel->config('module_sanitize_funcs');
  997. if ($this->sanitize_input === TRUE)
  998. {
  999. foreach($data as $key => $val)
  1000. {
  1001. if ( ! empty($val))
  1002. {
  1003. $posted[$key] = xss_clean($val);
  1004. }
  1005. }
  1006. }
  1007. else
  1008. {
  1009. // force to array to normalize
  1010. $sanitize_input = (array) $this->sanitize_input;
  1011. if (is_array($data))
  1012. {
  1013. foreach($data as $key => $post)
  1014. {
  1015. if (is_array($post))
  1016. {
  1017. $posted[$key] = $this->_sanitize($data[$key]);
  1018. }
  1019. else
  1020. {
  1021. // loop through sanitization functions
  1022. foreach($sanitize_input as $func)
  1023. {
  1024. $func = (isset($valid_funcs[$func])) ? $valid_funcs[$func] : FALSE;
  1025. if ($func)
  1026. {
  1027. $posted[$key] = $func($posted[$key]);
  1028. }
  1029. }
  1030. }
  1031. }
  1032. }
  1033. else
  1034. {
  1035. // loop through sanitization functions
  1036. foreach($sanitize_input as $key => $val)
  1037. {
  1038. $func = (isset($valid_funcs[$val])) ? $valid_funcs[$val] : FALSE;
  1039. if ($func)
  1040. {
  1041. $posted = $func($posted);
  1042. }
  1043. }
  1044. }
  1045. }
  1046. }
  1047. return $posted;
  1048. }
  1049. // --------------------------------------------------------------------
  1050. /**
  1051. * Returns an array of shell variables to apply to the main area of the page
  1052. *
  1053. * @access protected
  1054. * @param int The ID value of the record to edit
  1055. * @param string The name of the action to apply to the main form element
  1056. * @param array An array of data information
  1057. * @return array
  1058. */
  1059. protected function _shell_vars($id = NULL, $action = 'create', $data = array())
  1060. {
  1061. $model = $this->model;
  1062. $this->js_controller_params['method'] = 'add_edit';
  1063. $this->js_controller_params['linked_fields'] = $this->model->linked_fields;
  1064. // other variables
  1065. if (method_exists($this->model, 'vars'))
  1066. {
  1067. $model_vars = $this->model->vars($data);
  1068. $this->load->vars($model_vars);
  1069. }
  1070. $vars['id'] = $id;
  1071. $vars['versions'] = ($this->displayonly === FALSE AND $this->archivable) ? $this->fuel_archives_model->options_list($id, $this->model->table_name()) : array();
  1072. $vars['others'] = $this->model->get_others($this->display_field, $id);
  1073. $vars['action'] = $action;
  1074. $vars['notifications'] = $this->load->module_view(FUEL_FOLDER, '_blocks/notifications', $vars, TRUE);
  1075. return $vars;
  1076. }
  1077. // --------------------------------------------------------------------
  1078. /**
  1079. * Returns an array of saved data based on the id value passed
  1080. *
  1081. * @access protected
  1082. * @param int The ID value of the record to edit
  1083. * @return array
  1084. */
  1085. protected function _saved_data($id)
  1086. {
  1087. if (empty($id)) return array();
  1088. $edit_method = $this->edit_method;
  1089. if ($edit_method != 'find_one_array')
  1090. {
  1091. $saved = $this->model->$edit_method($id);
  1092. }
  1093. else
  1094. {
  1095. $saved = $this->model->$edit_method(array($this->model->table_name().'.'.$this->model->key_field() => $id));
  1096. }
  1097. return $saved;
  1098. }
  1099. // separated to make it easier in subclasses to use the form without rendering the page
  1100. protected function _form_vars($id = NULL, $values = array(), $field = NULL, $inline = FALSE)
  1101. {
  1102. $this->load->library('form_builder');
  1103. // load custom fields
  1104. $this->form_builder->load_custom_fields(APPPATH.'config/custom_fields.php');
  1105. $model = $this->model;
  1106. $this->js_controller_params['method'] = 'add_edit';
  1107. $action = (!empty($values[$this->model->key_field()])) ? 'edit' : 'create';
  1108. // create fields... start with the table info and go from there
  1109. $fields = (!empty($values)) ? $this->model->form_fields($values) : $this->model->form_fields($_POST);
  1110. // if it's an object, then extract
  1111. if ($fields instanceof Base_model_fields)
  1112. {
  1113. $fields = $fields->get_fields();
  1114. }
  1115. // if field parameter is set, then we just display a single field
  1116. if ( ! empty($field) AND ! is_numeric($field))
  1117. {
  1118. // added per pierlo in Forum (http://www.getfuelcms.com/forums/discussion/673/fuel_helper-fuel_edit-markers)
  1119. $columns = explode(':', $field);
  1120. // special case if you use the word required
  1121. if (in_array('required', $columns))
  1122. {
  1123. $columns = array_merge($columns, $this->model->required);
  1124. }
  1125. // set them to hidden... just in case model hooks require the values to be passed on save
  1126. foreach($fields as $k => $f)
  1127. {
  1128. if ( ! in_array($k, $columns))
  1129. {
  1130. $fields[$k]['type'] = 'hidden';
  1131. }
  1132. if (count($columns) <= 1)
  1133. {
  1134. $fields[$k]['display_label'] = FALSE;
  1135. $fields[$k]['required'] = FALSE;
  1136. }
  1137. }
  1138. }
  1139. // set published/active to hidden since setting this is an buttton/action instead of a form field
  1140. $form = '';
  1141. if (is_array($fields))
  1142. {
  1143. $field_values = ( ! empty($_POST)) ? $_POST : $values;
  1144. $published_active = array(
  1145. 'publish' => 'published',
  1146. 'active' => 'activate'
  1147. );
  1148. foreach($published_active as $k => $v)
  1149. {
  1150. if ( ! $this->fuel->auth->has_permission($this->permission, $k))
  1151. {
  1152. unset($fields[$v]);
  1153. }
  1154. if (isset($fields[$v]) AND !empty($values[$v]))
  1155. {
  1156. $fields['published']['value'] = $values[$v];
  1157. }
  1158. }
  1159. $this->form_builder->set_validator($this->model->get_validation());
  1160. // add hidden field with the module name for convenience
  1161. $common_fields = $this->_common_fields($field_values);
  1162. $fields = array_merge($fields, $common_fields);
  1163. $fields['__fuel_inline_action__'] = array('type' => 'hidden');
  1164. $fields['__fuel_inline_action__']['class'] = '__fuel_inline_action__';
  1165. $fields['__fuel_inline_action__']['value'] = (empty($id)) ? 'create' : 'edit';
  1166. $fields['__fuel_inline__'] = array('type' => 'hidden');
  1167. $fields['__fuel_inline__']['value'] = ($inline) ? 1 : 0;
  1168. $this->form_builder->submit_value = lang('btn_save');
  1169. $this->form_builder->question_keys = array();
  1170. $this->form_builder->use_form_tag = FALSE;
  1171. if ($this->model->has_auto_increment())
  1172. {
  1173. $this->form_builder->hidden = (array) $this->model->key_field();
  1174. }
  1175. if ($this->config->item('date_format'))
  1176. {
  1177. $this->form_builder->date_format = $this->config->item('date_format');
  1178. }
  1179. if ($inline)
  1180. {
  1181. $this->form_builder->cancel_value = lang('viewpage_close');
  1182. }
  1183. else
  1184. {
  1185. $this->form_builder->cancel_value = lang('btn_cancel');
  1186. }
  1187. $this->form_builder->set_fields($fields);
  1188. $this->form_builder->display_errors = FALSE;
  1189. $this->form_builder->set_field_values($field_values);
  1190. // we will set this in the BaseFuelController.js file so that the jqx page variable is available upon execution of any form field js
  1191. //$this->form_builder->auto_execute_js = FALSE;
  1192. if (!isset($fields['__FORM_BUILDER__'], $fields['__FORM_BUILDER__']['displayonly']))
  1193. {
  1194. $this->form_builder->displayonly = $this->displayonly;
  1195. }
  1196. $this->_prep_csrf();
  1197. $form = $this->form_builder->render();
  1198. }
  1199. $action_uri = (!empty($id)) ? $action.'/'.$id.'/'.$field : $action.'/'.$field;
  1200. $vars['form_action'] = ($inline) ? $this->module_uri.'/inline_'.$action_uri.query_str() : $this->module_uri.'/'.$action_uri.query_str();
  1201. $vars['form'] = $form;
  1202. $vars['data'] = $values;
  1203. $vars['error'] = $this->model->get_errors();
  1204. $vars['notifications'] = $this->load->module_view(FUEL_FOLDER, '_blocks/notifications', $vars, TRUE);
  1205. $vars['instructions'] = (empty($field)) ? $this->instructions : '';
  1206. $vars['field'] = (!empty($field));
  1207. return $vars;
  1208. }
  1209. protected function _process()
  1210. {
  1211. $this->load->helper('security');
  1212. $this->load->library('form_builder');
  1213. // XSS key check
  1214. if (!$this->_is_valid_csrf())
  1215. {
  1216. add_error(lang('error_saving'));
  1217. }
  1218. $this->_orig_post = $_POST;
  1219. // filter placeholder $_POST values
  1220. $callback = function($matches){
  1221. if (isset($_POST[$matches["2"]]))
  1222. {
  1223. $str = $matches[1].$_POST[$matches["2"]].$matches[3];
  1224. }
  1225. else
  1226. {
  1227. $str = $matches[0];
  1228. }
  1229. return $str;
  1230. };
  1231. // first loop through and create simple non-namespaced $_POST values if they don't exist for convenience'
  1232. foreach($_POST as $key => $val)
  1233. {
  1234. $key_parts = explode('--', $key);
  1235. $tmp_key = end($key_parts);
  1236. $_POST[$tmp_key] = $val;
  1237. }
  1238. // now loop through and do any substitution
  1239. foreach($_POST as $key => $val)
  1240. {
  1241. if (is_string($val))
  1242. {
  1243. $_POST[$key] = preg_replace_callback('#(.*)\{(.+)\}(.*)#U', $callback, $val);
  1244. }
  1245. }
  1246. // set boolean fields
  1247. if ( ! empty($this->model->boolean_fields) AND is_array($this->model->boolean_fields))
  1248. {
  1249. foreach($this->model->boolean_fields as $val)
  1250. {
  1251. $_POST[$val] = (isset($_POST[$val])) ? $_POST[$val] : 0;
  1252. }
  1253. }
  1254. // if no permission to publish, then we revoke
  1255. if ( ! $this->fuel->auth->has_permission($this->permission, 'publish'))
  1256. {
  1257. unset($_POST['published']);
  1258. }
  1259. // set key_field if it is not id
  1260. if ( ! empty($_POST['id']) AND $this->model->key_field() != 'id')
  1261. {
  1262. $_POST[$this->model->key_field()] = $_POST['id'];
  1263. }
  1264. // run any form field post processing hooks
  1265. $this->load->library('form_builder');
  1266. // use a new instance to prevent problems when duplicating
  1267. $fb = new Form_builder();
  1268. $fb->load_custom_fields(APPPATH.'config/custom_fields.php');
  1269. // $fields = $this->model->form_fields($_POST);
  1270. $fields = $this->_block_processing($this->model->form_fields(), $_POST);
  1271. $fb->set_fields($fields);
  1272. $fb->post_process_field_values();// manipulates the $_POST values directly
  1273. // sanitize input if set in module configuration
  1274. $posted = $this->_sanitize($_POST);
  1275. return $posted;
  1276. }
  1277. public function _block_processing($fields, $posted)
  1278. {
  1279. // grab the fields array if using the form fields class
  1280. if (is_object($fields) && ($fields instanceof Base_model_fields)) {
  1281. $fields = $fields->get_fields();
  1282. }
  1283. // add in block fields
  1284. foreach($fields as $key => $val)
  1285. {
  1286. // check blocks for post processing of variables
  1287. if (isset($val['type']) AND $val['type'] == 'block' AND isset($posted[$key]['block_name']))
  1288. {
  1289. $block_layout = $this->fuel->layouts->get($posted[$key]['block_name'], 'block');
  1290. if ($block_layout)
  1291. {
  1292. $block_fields = $block_layout->fields();
  1293. $fields = array_merge($fields, $block_fields);
  1294. }
  1295. }
  1296. // check for template layouts that may have nested fields... this is really ugly
  1297. if ( ! empty($val['fields']) AND is_array($val['fields']))
  1298. {
  1299. //$fields = array_merge($fields, $val['fields']);
  1300. foreach($val['fields'] as $k => $v)
  1301. {
  1302. if (isset($v['type']) AND $v['type'] == 'block' AND isset($posted[$key]))
  1303. {
  1304. if (is_array($posted[$key]) AND is_int(key($posted[$key])))
  1305. {
  1306. foreach($posted[$key] as $a => $b)
  1307. {
  1308. if (is_array($b))
  1309. {
  1310. foreach($b as $c => $d)
  1311. {
  1312. if (isset($d['block_name']))
  1313. {
  1314. $block_layout = $this->fuel->layouts->get($d['block_name'], 'block');
  1315. if ($block_layout)
  1316. {
  1317. $block_fields = $block_layout->fields();
  1318. // now switch out the key to allow it to trigger the post_process_callback...
  1319. foreach($block_fields as $e => $f)
  1320. {
  1321. $block_fields[$e]['subkey'] = $k;
  1322. $block_fields[$e]['key'] = $key;
  1323. }
  1324. $fields = array_merge($fields, $block_fields);
  1325. }
  1326. }
  1327. }
  1328. }
  1329. }
  1330. }
  1331. }
  1332. }
  1333. }
  1334. }
  1335. return $fields;
  1336. }
  1337. function form($id = NULL, $field = NULL)
  1338. {
  1339. $saved = $this->_saved_data($id);
  1340. $vars = $this->_form_vars($id, $saved, $field);
  1341. $this->load->module_view(FUEL_FOLDER, '_layouts/module_form', $vars);
  1342. }
  1343. function delete($id = NULL)
  1344. {
  1345. // check that the action even exists and if not, show a 404
  1346. if ( ! $this->fuel->auth->module_has_action('delete')) show_404();
  1347. if ( ! $this->fuel->auth->has_permission($this->permission, 'delete'))
  1348. {
  1349. show_error(lang('error_no_permissions', fuel_url()));
  1350. }
  1351. $inline = $this->fuel->admin->is_inline();
  1352. if ( ! empty($_POST['id']))
  1353. {
  1354. $posted = explode('|', $this->input->post('id', TRUE));
  1355. // run before_delete hook
  1356. $this->_run_hook('before_delete', $posted);
  1357. // Flags
  1358. $any_success = $any_failure = FALSE;
  1359. foreach ($posted as $id)
  1360. {
  1361. if ($this->model->delete(array($this->model->table_name().'.'.$this->model->key_field() => $id)))
  1362. {
  1363. $any_success = TRUE;
  1364. }
  1365. else
  1366. {
  1367. $any_failure = TRUE;
  1368. }
  1369. }
  1370. // run after_delete hook
  1371. $this->_run_hook('after_delete', $posted);
  1372. $this->_clear_cache();
  1373. if (count($posted) > 1)
  1374. {
  1375. $this->fuel->logs->write(lang('module_multiple_deleted', $this->module));
  1376. }
  1377. else
  1378. {
  1379. $this->fuel->logs->write(lang('module_deleted', count($posted), $this->module));
  1380. }
  1381. if ($inline)
  1382. {
  1383. $vars['title'] = '';
  1384. $vars['id'] = '';
  1385. $vars['back_action'] = '';
  1386. $this->fuel->admin->render('modules/module_close_modal', $vars, '', FUEL_FOLDER);
  1387. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT_TITLEBAR);
  1388. $this->fuel->admin->render($this->views['delete'], $vars, '', FUEL_FOLDER);
  1389. }
  1390. else
  1391. {
  1392. // set a success delete message
  1393. if ($any_success)
  1394. {
  1395. if ( ! $this->session->flashdata('success'))
  1396. {
  1397. $this->fuel->admin->set_notification(lang('data_deleted'), Fuel_admin::NOTIFICATION_SUCCESS);
  1398. }
  1399. }
  1400. // set an error delete message
  1401. if ($any_failure)
  1402. {
  1403. // first try to get an error added in model by $this->add_error('...')
  1404. $msg = $this->model->get_validation()->get_last_error();
  1405. // if there is none like that, lets use default message
  1406. if (is_null($msg)) $msg = lang('data_not_deleted');
  1407. $this->fuel->admin->set_notification($msg, Fuel_admin::NOTIFICATION_ERROR);
  1408. }
  1409. $url = fuel_uri($this->module_uri);
  1410. redirect($url);
  1411. }
  1412. }
  1413. else
  1414. {
  1415. $this->js_controller_params['method'] = 'deleteItem';
  1416. $vars = array();
  1417. if ( ! empty($_POST['delete']) AND is_array($_POST['delete']))
  1418. {
  1419. $data = array();
  1420. foreach($this->input->post('delete') as $key => $val)
  1421. {
  1422. $d = $this->model->find_by_key($key, 'array');
  1423. if ( ! empty($d)) $data[] = $d[$this->display_field];
  1424. }
  1425. $vars['id'] = implode('|', array_keys($_POST['delete']));
  1426. $vars['title'] = implode(', ', $data);
  1427. }
  1428. else
  1429. {
  1430. $data = $this->model->find_by_key($id, 'array');
  1431. $vars['id'] = $id;
  1432. $vars['title'] = $this->model->display_name($data);
  1433. }
  1434. if (empty($data)) show_404();
  1435. $vars['error'] = $this->model->get_errors();
  1436. $crumbs = array($this->module_uri => $this->module_name);
  1437. $crumbs[''] = character_limiter(strip_tags(lang('action_delete').' '.$vars['title']), 100);
  1438. $this->fuel->admin->set_titlebar($crumbs);
  1439. if ($inline)
  1440. {
  1441. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_COMPACT_NO_ACTION);
  1442. $vars['back_action'] = fuel_url($this->module_uri.'/inline_edit/'.$id);
  1443. }
  1444. else
  1445. {
  1446. $this->fuel->admin->set_display_mode(Fuel_admin::DISPLAY_NO_ACTION);
  1447. $vars['back_action'] = fuel_url($this->module_uri.'/');
  1448. }
  1449. $action_uri = 'de…

Large files files are truncated, but you can click here to view the full file