PageRenderTime 58ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/system/expressionengine/modules/safecracker/libraries/safecracker_lib.php

https://bitbucket.org/studiobreakfast/sync
PHP | 2941 lines | 1986 code | 509 blank | 446 comment | 355 complexity | 3094cd04c9f30ab50f02ad212d6b7c97 MD5 | raw file

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

  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * ExpressionEngine - by EllisLab
  4. *
  5. * @package ExpressionEngine
  6. * @author EllisLab Dev Team,
  7. * - Original Development by Barrett Newton -- http://barrettnewton.com
  8. * @copyright Copyright (c) 2003 - 2012, EllisLab, Inc.
  9. * @license http://expressionengine.com/user_guide/license.html
  10. * @link http://expressionengine.com
  11. * @since Version 2.0
  12. * @filesource
  13. */
  14. // ------------------------------------------------------------------------
  15. /**
  16. * ExpressionEngine SafeCracker Module Library
  17. *
  18. * @package ExpressionEngine
  19. * @subpackage Libraries
  20. * @category Modules
  21. * @author EllisLab Dev Team
  22. * @link http://expressionengine.com
  23. */
  24. class Safecracker_lib
  25. {
  26. public $initialized = FALSE;
  27. public $form_error = FALSE;
  28. public $site_id;
  29. public $categories;
  30. public $channel;
  31. public $checkboxes;
  32. public $custom_field_conditional_names;
  33. public $custom_fields;
  34. public $custom_option_fields;
  35. public $date_fields;
  36. public $datepicker;
  37. public $default_fields;
  38. public $edit;
  39. public $entry;
  40. public $error_handling;
  41. public $errors;
  42. public $field_errors;
  43. public $file;
  44. public $file_fields;
  45. public $form_validation_methods;
  46. public $head;
  47. public $json;
  48. public $logged_out_member_id;
  49. public $logged_out_group_id;
  50. public $native_option_fields;
  51. public $native_variables;
  52. public $option_fields;
  53. public $parse_variables;
  54. public $pre_save;
  55. public $preserve_checkboxes;
  56. public $post_error_callbacks;
  57. public $require_save_call;
  58. public $settings;
  59. public $skip_xss_fieldtypes;
  60. public $skip_xss_field_ids;
  61. public $statuses;
  62. public $show_fields;
  63. public $title_fields;
  64. public $valid_callbacks;
  65. public $lang, $api_channel_fields, $form_validation;
  66. /**
  67. * constructor
  68. *
  69. * @return void
  70. */
  71. public function __construct()
  72. {
  73. $this->EE =& get_instance();
  74. //set a global object
  75. $this->EE->safecracker = $this;
  76. }
  77. // --------------------------------------------------------------------
  78. /**
  79. * Creates the entry form
  80. *
  81. * @return string
  82. */
  83. public function entry_form()
  84. {
  85. //can't be used in a form action
  86. if ( ! isset($this->EE->TMPL))
  87. {
  88. return '';
  89. }
  90. $this->EE->lang->loadfile('safecracker');
  91. if ( ! isset($this->EE->extensions->extensions['form_declaration_modify_data'][10]['Safecracker_ext']))
  92. {
  93. return $this->EE->output->show_user_error(FALSE, lang('safecracker_extension_not_installed'));
  94. }
  95. // -------------------------------------------
  96. // 'safecracker_entry_form_tagdata_start' hook.
  97. // - Developers, if you want to modify the $this object remember
  98. // to use a reference on func call.
  99. //
  100. if ($this->EE->extensions->active_hook('safecracker_entry_form_absolute_start') === TRUE)
  101. {
  102. $this->EE->extensions->call('safecracker_entry_form_absolute_start');
  103. if ($this->EE->extensions->end_script === TRUE) return;
  104. }
  105. $this->fetch_site($this->EE->TMPL->fetch_param('site'));
  106. $this->initialize(empty($this->form_error));
  107. $this->EE->load->helper('form');
  108. $this->EE->router->set_class('cp');
  109. $this->EE->load->library('cp');
  110. $this->EE->router->set_class('ee');
  111. $this->EE->load->library('javascript');
  112. $this->EE->load->library('api');
  113. $this->EE->load->library('form_validation');
  114. $this->EE->api->instantiate('channel_fields');
  115. $this->load_channel_standalone();
  116. $this->EE->lang->loadfile('content');
  117. $this->EE->lang->loadfile('upload');
  118. $this->EE->javascript->output('if (typeof SafeCracker == "undefined" || ! SafeCracker) { var SafeCracker = {markItUpFields:{}};}');
  119. // Figure out what channel we're working with
  120. $this->fetch_channel($this->EE->TMPL->fetch_param('channel_id'), $this->EE->TMPL->fetch_param('channel'));
  121. if ( ! $this->channel)
  122. {
  123. return $this->EE->output->show_user_error('submission', lang('safecracker_no_channel'));
  124. }
  125. //get the entry data, if an entry was specified
  126. $this->fetch_entry($this->EE->TMPL->fetch_param('entry_id'), $this->EE->TMPL->fetch_param('url_title'));
  127. // Whoa there big conditional, what's going on here?
  128. // We want to make sure no one's being tricky here and supplying
  129. // an invalid entry_id or url_title via a segment, so we need to
  130. // check to see if either exists and if it does make sure that the
  131. // passed in version is the same as what we find in the database.
  132. // If they are different (most likely it wasn't found in the
  133. // database) then don't show them the form
  134. if (
  135. ($this->EE->TMPL->fetch_param('entry_id') != '' AND
  136. $this->entry('entry_id') != $this->EE->TMPL->fetch_param('entry_id')) OR
  137. ($this->EE->TMPL->fetch_param('url_title') != '' AND
  138. $this->entry('url_title') != $this->EE->TMPL->fetch_param('url_title'))
  139. )
  140. {
  141. if ($this->EE->TMPL->no_results())
  142. {
  143. return $this->EE->TMPL->no_results();
  144. }
  145. return $this->EE->output->show_user_error(FALSE, lang('safecracker_require_entry'));
  146. }
  147. // @added rev 57
  148. if ( ! $this->entry('entry_id') && $this->bool_string($this->EE->TMPL->fetch_param('require_entry')))
  149. {
  150. if ($this->EE->TMPL->no_results())
  151. {
  152. return $this->EE->TMPL->no_results();
  153. }
  154. return $this->EE->output->show_user_error(FALSE, lang('safecracker_require_entry'));
  155. }
  156. if ($this->entry('entry_id') && ! $this->form_error)
  157. {
  158. $this->edit = TRUE;
  159. }
  160. // @added rev 57
  161. if ($this->edit && $this->bool_string($this->EE->TMPL->fetch_param('author_only')) && $this->entry('author_id') != $this->EE->session->userdata('member_id'))
  162. {
  163. return $this->EE->output->show_user_error(FALSE, lang('safecracker_author_only'));
  164. }
  165. if (is_array($this->entry('category')))
  166. {
  167. $this->entry['categories'] = $this->entry('category');
  168. }
  169. //add hidden field data
  170. $this->form_hidden(
  171. array(
  172. 'ACT' => $this->EE->functions->fetch_action_id('Safecracker', 'submit_entry'),
  173. 'site_id' => $this->site_id,
  174. 'return' => ($this->EE->TMPL->fetch_param('return_'.$this->EE->session->userdata('group_id'))) ? $this->EE->TMPL->fetch_param('return_'.$this->EE->session->userdata('group_id')) : $this->EE->TMPL->fetch_param('return'),
  175. 'json' => $this->bool_string($this->EE->TMPL->fetch_param('json')) ? 1 : FALSE,
  176. 'dynamic_title' => ($this->EE->TMPL->fetch_param('dynamic_title')) ? base64_encode($this->EE->TMPL->fetch_param('dynamic_title')) : FALSE,
  177. 'error_handling' => ($this->EE->TMPL->fetch_param('error_handling')) ? $this->EE->TMPL->fetch_param('error_handling') : FALSE,
  178. 'preserve_checkboxes' => ($this->EE->TMPL->fetch_param('preserve_checkboxes')) ? $this->EE->TMPL->fetch_param('preserve_checkboxes') : FALSE,
  179. 'secure_return' => $this->bool_string($this->EE->TMPL->fetch_param('secure_return')) ? 1 : FALSE,
  180. 'allow_comments' => $this->bool_string($this->EE->TMPL->fetch_param('allow_comments'), $this->channel['comment_system_enabled']) == 'y' ? 'y' : 'n'
  181. )
  182. );
  183. unset($this->EE->TMPL->tagparams['allow_comments']);
  184. //add form attributes
  185. $this->form_attribute(
  186. array(
  187. 'onsubmit' => $this->EE->TMPL->fetch_param('onsubmit'),
  188. 'name' => $this->EE->TMPL->fetch_param('name'),
  189. 'class' => $this->EE->TMPL->fetch_param('class'),
  190. 'id' => $this->EE->TMPL->fetch_param('id')
  191. )
  192. );
  193. if ($this->EE->TMPL->fetch_param('datepicker'))
  194. {
  195. $this->datepicker = $this->bool_string($this->EE->TMPL->fetch_param('datepicker'), $this->datepicker);
  196. }
  197. if ($this->datepicker)
  198. {
  199. $this->EE->javascript->output('$.datepicker.setDefaults({dateFormat:$.datepicker.W3C+EE.date_obj_time});');
  200. }
  201. foreach ($this->EE->TMPL->tagparams as $key => $value)
  202. {
  203. if (preg_match('/^rules:(.+)/', $key, $match))
  204. {
  205. $this->form_hidden('rules['.$match[1].']', $this->encrypt_input($value));
  206. }
  207. }
  208. //decide which fields to show, based on pipe delimited list of field id's and/or field short names
  209. if ($this->EE->TMPL->fetch_param('show_fields'))
  210. {
  211. if (preg_match('/not (.*)/', $this->EE->TMPL->fetch_param('show_fields'), $match))
  212. {
  213. foreach ($this->custom_fields as $field_name => $field)
  214. {
  215. $this->show_fields[] = $field_name;
  216. }
  217. foreach (explode('|', $match[1]) as $field_name)
  218. {
  219. if (is_numeric($field_name))
  220. {
  221. $field_name = $this->get_field_name($field_name);
  222. }
  223. $index = ($field_name !== FALSE) ? array_search($field_name, $this->show_fields) : FALSE;
  224. if ($index !== FALSE)
  225. {
  226. unset($this->show_fields[$index]);
  227. }
  228. }
  229. }
  230. else
  231. {
  232. foreach (explode('|', $this->EE->TMPL->fetch_param('show_fields')) as $field_name)
  233. {
  234. if (is_numeric($field_name))
  235. {
  236. $field_name = $this->get_field_name($field_name);
  237. }
  238. if ($field_name)
  239. {
  240. $this->show_fields[] = $field_name;
  241. }
  242. }
  243. }
  244. }
  245. // -------------------------------------------
  246. // 'safecracker_entry_form_tagdata_start' hook.
  247. // - Developers, if you want to modify the $this object remember
  248. // to use a reference on func call.
  249. //
  250. if ($this->EE->extensions->active_hook('safecracker_entry_form_tagdata_start') === TRUE)
  251. {
  252. $this->EE->TMPL->tagdata = $this->EE->extensions->call('safecracker_entry_form_tagdata_start', $this->EE->TMPL->tagdata, $this);
  253. if ($this->EE->extensions->end_script === TRUE) return;
  254. }
  255. // build custom field variables
  256. $custom_field_variables = array();
  257. foreach ($this->custom_fields as $field_name => $field)
  258. {
  259. /*
  260. if ($this->EE->TMPL->fetch_param($field_name))
  261. {
  262. $this->form_hidden($field_name, $this->EE->TMPL->fetch_param($field_name));
  263. }
  264. */
  265. // standard vars/conditionals
  266. $custom_field_variables_row = array(
  267. 'required' => ($field['field_required'] == 'n') ? 0 : 1,
  268. 'text_direction' => $field['field_text_direction'],
  269. 'field_data' => $this->entry($field_name),
  270. 'rows' => $field['field_ta_rows'],
  271. 'maxlength' => $field['field_maxl'],
  272. 'formatting_buttons' => '',
  273. 'field_show_formatting_btns' => (isset($field['field_show_formatting_btns']) && $field['field_show_formatting_btns'] == 'y') ? 1 : 0,
  274. 'textinput' => 0,
  275. 'pulldown' => 0,
  276. 'checkbox' => 0,
  277. 'relationship' => 0,
  278. 'multiselect' => 0,
  279. 'date' => 0,
  280. 'radio' => 0,
  281. 'display_field' => '',
  282. 'options' => $this->get_field_options($field_name),
  283. 'error' => ( ! empty($this->field_errors[$field['field_name']])) ? lang($this->field_errors[$field['field_name']]) : ''
  284. );
  285. $custom_field_variables_row = array_merge($field, $custom_field_variables_row);
  286. $fieldtypes = $this->EE->api_channel_fields->fetch_installed_fieldtypes();
  287. //add a negative conditional based on fieldtype
  288. foreach ($fieldtypes as $type => $fieldtype)
  289. {
  290. $custom_field_variables_row[$type] = 0;
  291. }
  292. // fieldtype conditionals
  293. foreach ($this->custom_fields as $f_name => $f)
  294. {
  295. $custom_field_variables_row[$f['field_type']] = $custom_field_variables_row[$f_name] = ($field['field_type'] == $f['field_type']) ? 1 : 0;
  296. }
  297. if (array_key_exists($field['field_type'], $this->custom_field_conditional_names))
  298. {
  299. $custom_field_variables_row[$this->custom_field_conditional_names[$field['field_type']]] = 1;
  300. }
  301. if ($field['field_type'] == 'date')
  302. {
  303. if ($this->datepicker)
  304. {
  305. $default_date = (($this->entry($field_name)) ? $this->entry($field_name) : $this->EE->localize->now) * 1000;
  306. $this->EE->javascript->output('
  307. $(\'input[name="'.$field_name.'"]\').datepicker({
  308. constrainInput: false,
  309. defaultDate: new Date('.$default_date.')
  310. });
  311. ');
  312. }
  313. $custom_field_variables_row['field_data'] = $this->EE->localize->set_human_time($this->entry($field_name));
  314. }
  315. $custom_field_variables[$field_name] = $custom_field_variables_row;
  316. }
  317. // parse custom fields loop
  318. if (preg_match('/'.LD.'custom_fields'.RD.'(.*)'.LD.'\/custom_fields'.RD.'/s', $this->EE->TMPL->tagdata, $match))
  319. {
  320. $custom_field_output = '';
  321. $tagdata = $match[1];
  322. $formatting_buttons = (strpos($tagdata, LD.'formatting_buttons'.RD) !== FALSE);
  323. foreach ($custom_field_variables as $field_name => $custom_field_variables_row)
  324. {
  325. if ($this->show_fields && ! in_array($field_name, $this->show_fields))
  326. {
  327. continue;
  328. }
  329. if ($formatting_buttons && $custom_field_variables_row['field_show_formatting_btns'])
  330. {
  331. $this->markitup = TRUE;
  332. $this->EE->javascript->output('SafeCracker.markItUpFields["'.$field_name.'"] = '.$custom_field_variables_row['field_id'].';');
  333. }
  334. $temp = $tagdata;
  335. //parse conditionals
  336. //$temp = $this->swap_conditionals($temp, $custom_field_variables_row);
  337. $embed_vars = $this->EE->TMPL->embed_vars;
  338. $this->EE->TMPL->embed_vars = array_merge($this->EE->TMPL->embed_vars, $custom_field_variables_row);
  339. $temp = $this->EE->TMPL->advanced_conditionals($temp);
  340. $this->EE->TMPL->embed_vars = $embed_vars;
  341. if (strpos($temp, LD.'display_field'.RD) !== FALSE)
  342. {
  343. $custom_field_variables_row['display_field'] = $this->display_field($field_name);
  344. if ($custom_field_variables_row['field_type'] == 'file')
  345. {
  346. $custom_field_variables_row['display_field'] = '<div class="publish_field">'.$custom_field_variables_row['display_field'].'</div>';
  347. }
  348. }
  349. foreach ($custom_field_variables_row as $key => $value)
  350. {
  351. if (is_array($value))
  352. {
  353. $temp = $this->swap_var_pair($key, $value, $temp);
  354. }
  355. // don't use our conditionals as vars
  356. else if ( ! is_int($value))
  357. {
  358. $temp = $this->EE->TMPL->swap_var_single($key, $value, $temp);
  359. }
  360. }
  361. if ($custom_field_variables_row['field_type'] === 'catchall')
  362. {
  363. $temp = $this->replace_tag($field_name, $this->entry($field_name), array(), $temp);
  364. }
  365. $custom_field_output .= $temp;
  366. }
  367. $this->EE->TMPL->tagdata = str_replace($match[0], $custom_field_output, $this->EE->TMPL->tagdata);
  368. }
  369. if ( ! empty($this->markitup))
  370. {
  371. $this->EE->javascript->output('$.each(SafeCracker.markItUpFields,function(a){$("#"+a).markItUp(mySettings);});');
  372. }
  373. // We'll store all checkbox fieldnames in here, so that in case one
  374. // has preserve_checkboxes set to "yes" but still needs to edit
  375. // checkboxes that have the potential to be blank, the field can be
  376. // updated while preserving the checkboxes that aren't on screen
  377. $checkbox_fields = array();
  378. foreach ($this->EE->TMPL->var_pair as $tag_pair_open => $tagparams)
  379. {
  380. $tag_name = current(preg_split('/\s/', $tag_pair_open));
  381. if ($tag_name == 'categories')
  382. {
  383. $this->EE->TMPL->tagdata = $this->swap_var_pair($tag_pair_open, $this->categories($tagparams), $this->EE->TMPL->tagdata, $tag_name, ! empty($tagparams['backspace']) ? $tagparams['backspace'] : FALSE);
  384. //$this->parse_variables['categories'] = $this->categories($tagparams);
  385. }
  386. else if ($tag_name == 'statuses')
  387. {
  388. $this->fetch_statuses();
  389. $this->parse_variables['statuses'] = $this->statuses;
  390. }
  391. //custom field pair parsing with replace_tag
  392. else if (isset($this->custom_fields[$tag_name]))
  393. {
  394. if (preg_match_all('/'.LD.preg_quote($tag_pair_open).RD.'(.*)'.LD.'\/'.$tag_name.RD.'/s', $this->EE->TMPL->tagdata, $matches))
  395. {
  396. foreach ($matches[1] as $match_index => $var_pair_tagdata)
  397. {
  398. $this->EE->TMPL->tagdata = str_replace($matches[0][$match_index], $this->replace_tag($tag_name, $this->entry($tag_name), $tagparams, $var_pair_tagdata), $this->EE->TMPL->tagdata);
  399. }
  400. }
  401. }
  402. //options:field_name tag pair parsing
  403. else if (preg_match('/^options:(.*)/', $tag_name, $match) && in_array($this->get_field_type($match[1]), $this->option_fields))
  404. {
  405. $checkbox_fields[] = $match[1];
  406. $this->parse_variables[$match[0]] = (isset($custom_field_variables[$match[1]]['options'])) ? $custom_field_variables[$match[1]]['options'] : '';
  407. }
  408. //parse category menu
  409. else if ($tag_name == 'category_menu')
  410. {
  411. $this->channel_standalone->_category_tree_form($this->channel('cat_group'), 'edit', '', $this->entry('categories'));
  412. $this->parse_variables['category_menu'] = array(array('select_options' => implode("\n", $this->channel_standalone->categories)));
  413. }
  414. //parse status menu
  415. else if ($tag_name = 'status_menu')
  416. {
  417. $this->fetch_statuses();
  418. $select_options = '';
  419. foreach ($this->statuses as $status)
  420. {
  421. $status['selected'] = ($this->entry('status') == $status['status']) ? ' selected="selected"' : '';
  422. $status['checked'] = ($this->entry('status') == $status['status']) ? ' checked="checked"' : '';
  423. $status['name'] = (in_array($status['status'], array('open', 'closed'))) ? lang($status['status']) : $status['status'];
  424. $select_options .= '<option value="'.$status['status'].'"'.$status['selected'].'>'.$status['name'].'</option>'."\n";
  425. }
  426. $this->parse_variables['status_menu'] = array(array('select_options' => $select_options));
  427. }
  428. }
  429. $this->form_hidden('checkbox_fields', implode('|', $checkbox_fields));
  430. //edit form
  431. if ($this->entry)
  432. {
  433. //not necessary for edit forms
  434. $this->EE->TMPL->tagparams['use_live_url'] = 'no';
  435. $expiration_date = ($this->entry('expiration_date')) ? $this->entry('expiration_date')*1000 : $this->EE->localize->now*1000;
  436. $comment_expiration_date = ($this->entry('comment_expiration_date')) ? $this->entry('comment_expiration_date')*1000 : $this->EE->localize->now*1000;
  437. if ($this->datepicker)
  438. {
  439. if (strpos($this->EE->TMPL->tagdata, 'entry_date') !== FALSE)
  440. {
  441. $this->EE->javascript->output('$("input[name=entry_date]").datepicker({defaultDate: new Date('.($this->entry('entry_date')*1000).')});');
  442. }
  443. if (strpos($this->EE->TMPL->tagdata, 'expiration_date') !== FALSE)
  444. {
  445. $this->EE->javascript->output('$("input[name=expiration_date]").datepicker({defaultDate: new Date('.$expiration_date.')});');
  446. }
  447. if (strpos($this->EE->TMPL->tagdata, 'comment_expiration_date') !== FALSE)
  448. {
  449. $this->EE->javascript->output('$("input[name=comment_expiration_date]").datepicker({defaultDate: new Date('.$comment_expiration_date.')});');
  450. }
  451. }
  452. foreach ($this->EE->TMPL->var_single as $key)
  453. {
  454. if ($this->entry($key) !== FALSE)
  455. {
  456. if (in_array($key, $this->date_fields) || $this->get_field_type($key) == 'date')
  457. {
  458. $this->parse_variables[$key] = ($this->entry($key)) ? $this->EE->localize->set_human_time($this->entry($key)) : '';
  459. }
  460. elseif (in_array($key, $this->checkboxes))
  461. {
  462. $this->parse_variables[$key] = ($this->entry($key) == 'y') ? 'checked="checked"' : '';
  463. }
  464. else
  465. {
  466. $this->parse_variables[$key] = form_prep($this->entry($key), $key);
  467. }
  468. }
  469. else if (preg_match('/entry_id_path=([\042\047])?([^\042\047]*)[\042\047]?/', $key, $match))
  470. {
  471. $this->parse_variables[$match[0]] = $this->EE->functions->create_url($match[2].'/'.$this->entry('entry_id'));
  472. }
  473. else if (preg_match('/(url_title_path|title_permalink)=[\042\047]?([^\042\047]*)[\042\047]?/', $key, $match))
  474. {
  475. $this->parse_variables[$match[0]] = $this->EE->functions->create_url($match[2].'/'.$this->entry('url_title'));
  476. }
  477. // use fieldtype display_field method
  478. else if (preg_match('/^field:(.*)$/', $key, $match))
  479. {
  480. $this->parse_variables[$match[0]] = (array_key_exists($match[1], $this->custom_fields)) ? $this->display_field($match[1]) : '';
  481. }
  482. else if (preg_match('/^label:(.*)$/', $key, $match))
  483. {
  484. $this->parse_variables[$match[0]] = (array_key_exists($match[1], $this->custom_fields)) ? $this->custom_fields[$match[1]]['field_label'] : '';
  485. }
  486. else if (preg_match('/^selected_option:(.*?)(:label)?$/', $key, $match) && in_array($this->get_field_type($match[1]), $this->option_fields))
  487. {
  488. $options = (isset($custom_field_variables[$match[1]]['options'])) ? $custom_field_variables[$match[1]]['options'] : array();
  489. $selected_option = '';
  490. foreach ($options as $option)
  491. {
  492. if ($option['option_value'] == $this->entry($match[1]))
  493. {
  494. $selected_option = ( ! empty($match[2])) ? $option['option_name'] : $option['option_value'];
  495. }
  496. }
  497. $this->parse_variables[$match[0]] = $selected_option;
  498. }
  499. else if (preg_match('/^instructions:(.*)$/', $key, $match))
  500. {
  501. $this->parse_variables[$match[0]] = (array_key_exists($match[1], $this->custom_fields)) ? $this->custom_fields[$match[1]]['field_instructions'] : '';
  502. }
  503. else if (preg_match('/^error:(.*)$/', $key, $match))
  504. {
  505. $this->parse_variables[$match[0]] = ( ! empty($this->field_errors[$match[1]])) ? $this->field_errors[$match[1]] : '';
  506. }
  507. }
  508. $this->form_hidden(
  509. array(
  510. 'entry_id' => $this->entry('entry_id'),
  511. 'unique_url_title' => ($this->bool_string($this->EE->TMPL->fetch_param('unique_url_title'))) ? '1' : '',
  512. 'author_id'=> $this->entry('author_id')
  513. )
  514. );
  515. }
  516. elseif ($this->channel('channel_id'))
  517. {
  518. $this->parse_variables['entry_date'] = $this->EE->localize->set_human_time();
  519. if ($this->datepicker)
  520. {
  521. $this->EE->javascript->output('$.datepicker.setDefaults({defaultDate: new Date('.($this->EE->localize->now*1000).')});');
  522. if (strpos($this->EE->TMPL->tagdata, 'entry_date') !== FALSE)
  523. {
  524. $this->EE->javascript->output('$("input[name=entry_date]").datepicker();');
  525. }
  526. if (strpos($this->EE->TMPL->tagdata, 'expiration_date') !== FALSE)
  527. {
  528. $this->EE->javascript->output('$("input[name=expiration_date]").datepicker();');
  529. }
  530. if (strpos($this->EE->TMPL->tagdata, 'comment_expiration_date') !== FALSE)
  531. {
  532. $this->EE->javascript->output('$("input[name=comment_expiration_date]").datepicker();');
  533. }
  534. }
  535. foreach ($this->custom_fields as $field)
  536. {
  537. foreach ($this->EE->TMPL->var_pair as $tag_pair_open => $tagparams)
  538. {
  539. $tag_name = current(preg_split('/\s/', $tag_pair_open));
  540. if ($tag_name == $field['field_name'])
  541. {
  542. //special parsing here for catchall fieldtype, pls keep this in
  543. if ($field['field_type'] === 'catchall')
  544. {
  545. if (preg_match_all('/'.LD.$tag_pair_open.RD.'(.*)'.LD.'\/'.$field['field_name'].RD.'/s', $this->EE->TMPL->tagdata, $matches))
  546. {
  547. foreach ($matches[1] as $match_index => $var_pair_tagdata)
  548. {
  549. if (preg_match_all('/'.LD.'([^\s]*)'.RD.'(.*)'.LD.'\/'.'\1'.RD.'/s', $var_pair_tagdata, $submatches))
  550. {
  551. foreach ($submatches[2] as $submatch_index => $sub_var_pair_tagdata)
  552. {
  553. $var_pair_tagdata = str_replace($submatches[0][$submatch_index], $sub_var_pair_tagdata, $var_pair_tagdata);
  554. }
  555. }
  556. $var_pair_tagdata = preg_replace('/'.LD.'([^\s]*)'.RD.'/s', '', $var_pair_tagdata);
  557. $this->EE->TMPL->tagdata = str_replace($matches[0][$match_index], $var_pair_tagdata, $this->EE->TMPL->tagdata);
  558. }
  559. }
  560. }
  561. else
  562. {
  563. $this->parse_variables[$field['field_name']] = '';
  564. }
  565. }
  566. else if ($tag_name == 'options:'.$field['field_name'] && in_array($this->get_field_type($field['field_name']), $this->option_fields))
  567. {
  568. $this->parse_variables['options:'.$field['field_name']] = (isset($custom_field_variables[$field['field_name']]['options'])) ? $custom_field_variables[$field['field_name']]['options'] : '';
  569. }
  570. }
  571. $this->parse_variables[$field['field_name']] = '';
  572. $this->parse_variables['label:'.$field['field_name']] = $field['field_label'];
  573. $this->parse_variables['selected_option:'.$field['field_name'].':label'] = '';
  574. $this->parse_variables['selected_option:'.$field['field_name']] = '';
  575. $this->parse_variables['label:'.$field['field_name']] = $field['field_label'];
  576. $this->parse_variables['instructions:'.$field['field_name']] = $field['field_instructions'];
  577. $this->parse_variables['error:'.$field['field_name']] = ( ! empty($this->field_errors[$field['field_name']])) ? $this->field_errors[$field['field_name']] : '';
  578. //let's not needlessly call this, otherwise we could get duplicate fields rendering
  579. if (strpos($this->EE->TMPL->tagdata, LD.'field:'.$field['field_name'].RD) !== FALSE)
  580. {
  581. $this->parse_variables['field:'.$field['field_name']] = (array_key_exists($field['field_name'], $this->custom_fields)) ? $this->display_field($field['field_name']) : '';
  582. }
  583. }
  584. }
  585. foreach ($this->title_fields as $field)
  586. {
  587. if (isset($this->EE->TMPL->var_single['error:'.$field]))
  588. {
  589. $this->parse_variables['error:'.$field] = ( ! empty($this->field_errors[$field])) ? $this->field_errors[$field] : '';
  590. }
  591. }
  592. // Add global errors
  593. if (count($this->errors) === 0)
  594. {
  595. $this->parse_variables['global_errors'] = array(array());
  596. }
  597. else
  598. {
  599. $this->parse_variables['global_errors'] = array();
  600. foreach ($this->errors as $error)
  601. {
  602. $this->parse_variables['global_errors'][] = array('error' => $error);
  603. }
  604. }
  605. $this->parse_variables['global_errors:count'] = count($this->errors);
  606. // Add field errors
  607. if (count($this->field_errors) === 0)
  608. {
  609. $this->parse_variables['field_errors'] = array(array());
  610. }
  611. else
  612. {
  613. $this->parse_variables['field_errors'] = array();
  614. foreach ($this->field_errors as $field => $error)
  615. {
  616. $this->parse_variables['field_errors'][] = array('field' => $field, 'error' => $error);
  617. }
  618. }
  619. $this->parse_variables['field_errors:count'] = count($this->field_errors);
  620. // Add field errors to conditional parsing
  621. $conditional_errors = $this->parse_variables;
  622. if ( ! empty($conditional_errors['field_errors'][0]))
  623. {
  624. foreach ($conditional_errors['field_errors'] as $error)
  625. {
  626. $conditional_errors['error:' . $error['field']] = $error['error'];
  627. }
  628. unset($conditional_errors['field_errors']);
  629. }
  630. //load member data for logged out member
  631. $this->fetch_logged_out_member($this->EE->TMPL->fetch_param('logged_out_member_id'));
  632. // Parse captcha conditional
  633. $captcha_conditional = array(
  634. 'captcha' => ($this->channel('channel_id') && $this->logged_out_member_id && ! empty($this->settings['require_captcha'][$this->EE->config->item('site_id')][$this->channel('channel_id')]))
  635. );
  636. // Parse conditionals
  637. // $this->parse_variables['error:title'] = TRUE;
  638. $this->EE->TMPL->tagdata = $this->EE->functions->prep_conditionals(
  639. $this->EE->TMPL->tagdata,
  640. array_merge($conditional_errors, $captcha_conditional)
  641. );
  642. // Make sure {captcha_word} is blank
  643. $this->EE->TMPL->tagdata = $this->EE->TMPL->swap_var_single('captcha_word', '', $this->EE->TMPL->tagdata);
  644. // Replace {captcha} with actual captcha
  645. $this->EE->TMPL->tagdata = $this->EE->TMPL->swap_var_single('captcha', $this->EE->functions->create_captcha(), $this->EE->TMPL->tagdata);
  646. // Parse the variables
  647. if ($this->parse_variables)
  648. {
  649. $this->EE->TMPL->tagdata = $this->EE->TMPL->parse_variables($this->EE->TMPL->tagdata, array($this->parse_variables));
  650. }
  651. if ($this->file)
  652. {
  653. $this->EE->session->cache['safecracker']['enctype'] = 'enctype="multipart/form-data"';
  654. }
  655. //add encrypted member_id to form
  656. if ($this->EE->TMPL->fetch_param('logged_out_member_id') && $this->logged_out_member_id)
  657. {
  658. $this->form_hidden('logged_out_member_id', $this->encrypt_input($this->logged_out_member_id));
  659. }
  660. //add class to form
  661. if ($this->EE->TMPL->fetch_param('class'))
  662. {
  663. $this->EE->TMPL->tagparams['form_class'] = $this->EE->TMPL->fetch_param('class');
  664. }
  665. $this->load_session_override();
  666. //set group-based return url
  667. $this->form_hidden('return', ($this->EE->TMPL->fetch_param('return_'.$this->EE->session->userdata['group_id'])) ? $this->EE->TMPL->fetch_param('return_'.$this->EE->session->userdata['group_id']) : $this->EE->TMPL->fetch_param('return'));
  668. //get rid of the saef_javascript variable, we don't want that parsing in channel_standalone
  669. if (($array_search = array_search('saef_javascript', $this->EE->TMPL->var_single)) !== FALSE)
  670. {
  671. unset($this->EE->TMPL->var_single[$array_search]);
  672. }
  673. $this->EE->session->cache['safecracker']['form_declaration'] = TRUE;
  674. //temporarily set the site_id for cross-site saef
  675. $current_site_id = $this->EE->config->item('site_id');
  676. $this->EE->config->set_item('site_id', $this->site_id);
  677. $include_jquery = $this->EE->TMPL->fetch_param('include_jquery');
  678. //force include to no, for channel_standalone parsing
  679. $this->EE->TMPL->tagparams['include_jquery'] = 'no';
  680. $return = $this->channel_standalone->entry_form(TRUE, $this->EE->functions->cached_captcha);
  681. $this->EE->config->set_item('site_id', $current_site_id);
  682. if (isset($this->EE->session->cache['safecracker']['channel_standalone_output_js']))
  683. {
  684. $this->head .= '<script type="text/javascript" charset="utf-8">// <![CDATA[ '."\n";
  685. foreach ($this->EE->session->cache['safecracker']['channel_standalone_output_js']['json'] as $key => $value)
  686. {
  687. if ($key == 'EE')
  688. {
  689. $value['XID'] = '{XID_HASH}';
  690. $this->head .= 'if (typeof EE == "undefined" || ! EE) { '."\n".'var EE = '.$this->EE->javascript->generate_json($value, TRUE).';}'."\n";
  691. }
  692. else
  693. {
  694. $this->head .= $key.' = '.$this->EE->javascript->generate_json($value, TRUE).';'."\n";
  695. }
  696. $first = FALSE;
  697. }
  698. $this->head .= "\n".' // ]]>'."\n".'</script>';
  699. }
  700. $js_defaults = array(
  701. 'ui' => array('core', 'widget', 'button', 'dialog'),
  702. 'plugin' => array('scrollable', 'scrollable.navigator', 'markitup', 'thickbox'),
  703. );
  704. if (version_compare(APP_VER, '2.1.3', '>'))
  705. {
  706. $js_defaults['plugin'][] = 'toolbox.expose';
  707. $js_defaults['plugin'][] = 'overlay';
  708. $js_defaults['plugin'][] = 'tmpl';
  709. }
  710. if ($this->datepicker)
  711. {
  712. $js_defaults['ui'][] = 'datepicker';
  713. }
  714. foreach ($js_defaults as $type => $files)
  715. {
  716. foreach ($files as $file)
  717. {
  718. if ( ! isset($this->EE->cp->js_files[$type]))
  719. {
  720. $this->EE->cp->js_files[$type] = array();
  721. }
  722. else if (is_string($this->EE->cp->js_files[$type]))
  723. {
  724. $this->EE->cp->js_files[$type] = explode(',', $this->EE->cp->js_files[$type]);
  725. }
  726. if ( ! in_array($file, $this->EE->cp->js_files[$type]))
  727. {
  728. $this->EE->cp->js_files[$type][] = $file;
  729. }
  730. }
  731. }
  732. $ui = array(
  733. 'core' => FALSE,
  734. 'widget' => array('core'),
  735. 'mouse' => array('core', 'widget'),
  736. 'position' => array('core'),
  737. 'draggable' => array('core', 'widget', 'mouse'),
  738. 'droppable' => array('core', 'widget', 'mouse', 'draggable'),
  739. 'resizable' => array('core', 'widget', 'mouse'),
  740. 'selectable' => array('core', 'widget', 'mouse'),
  741. 'sortable' => array('core', 'widget', 'mouse'),
  742. 'accordion' => array('core', 'widget'),
  743. 'autocomplete' => array('core'),
  744. 'button' => array('core', 'widget', 'position'),
  745. 'dialog' => array('core', 'widget', 'mouse', 'position', 'draggable', 'resizable', 'button'),
  746. 'slider' => array('core', 'widget', 'mouse'),
  747. 'tabs' => array('core', 'widget'),
  748. 'datepicker' => array('core'),
  749. 'progressbar' => array('core', 'widget'),
  750. 'effects' => array('core'),
  751. );
  752. foreach ($this->EE->cp->js_files as $type => $files)
  753. {
  754. //let's get the order right
  755. if ($type == 'ui')
  756. {
  757. $temp = array();
  758. foreach ($files as $file)
  759. {
  760. $temp[] = $file;
  761. if (is_array($ui[$file]))
  762. {
  763. $temp = array_merge($ui[$file], $temp);
  764. }
  765. }
  766. $files = array();
  767. foreach (array_keys($ui) as $file)
  768. {
  769. if (in_array($file, $temp))
  770. {
  771. $files[] = $file;
  772. }
  773. }
  774. }
  775. if (empty($files))
  776. {
  777. unset($this->EE->cp->js_files[$type]);
  778. }
  779. else
  780. {
  781. $mtime[] = $this->EE->cp->_get_js_mtime($type, $files);
  782. $this->EE->cp->js_files[$type] = implode(',', $files);
  783. }
  784. }
  785. if (empty($mtime))
  786. {
  787. $mtime = array($this->EE->localize->now);
  788. }
  789. $use_live_url = ($this->bool_string($this->EE->TMPL->fetch_param('use_live_url'), TRUE)) ? '&use_live_url=y' : '';
  790. $include_jquery = ($this->bool_string($include_jquery, TRUE)) ? '&include_jquery=y' : '';
  791. // RTE Selector parameter?
  792. $rte_selector = $this->EE->TMPL->fetch_param('rte_selector');
  793. if ($rte_selector)
  794. {
  795. // toolset id specified?
  796. $rte_toolset_id = (int)$this->EE->TMPL->fetch_param('rte_toolset_id');
  797. $js_url = $this->EE->functions->fetch_site_index().QUERY_MARKER
  798. .'ACT='.$this->EE->functions->fetch_action_id('Rte', 'get_js')
  799. .'&toolset_id='.$rte_toolset_id
  800. .'&selector='.urlencode($rte_selector)
  801. .'&include=jquery_ui';
  802. $this->head .= '<script type="text/javascript" src="'.$js_url.'"></script>'."\n";
  803. }
  804. $this->head .= '<script type="text/javascript" charset="utf-8" src="'.$this->EE->functions->fetch_site_index().QUERY_MARKER.'ACT='.$this->EE->functions->fetch_action_id('Safecracker', 'combo_loader').'&'.str_replace('%2C', ',', http_build_query($this->EE->cp->js_files)).'&v='.max($mtime).$use_live_url.$include_jquery.'"></script>'."\n";
  805. //add fieldtype styles
  806. foreach ($this->EE->cp->its_all_in_your_head as $item)
  807. {
  808. $this->head .= $item."\n";
  809. }
  810. //add fieldtype scripts
  811. foreach ($this->EE->cp->footer_item as $item)
  812. {
  813. $this->head .= $item."\n";
  814. }
  815. $this->unload_session_override();
  816. //add loaded JS
  817. $this->EE->javascript->compile();
  818. if ( ! empty($this->EE->jquery->jquery_code_for_compile))
  819. {
  820. $script = '$(document).ready(function() {' . "\n";
  821. $script .= implode('', $this->EE->jquery->jquery_code_for_compile);
  822. $script .= '});';
  823. $script = preg_replace('/\s*eeSpell\.init\(\);\s*/', '', $script);
  824. $this->head .= $this->EE->javascript->inline($script);
  825. $this->EE->jquery->jquery_code_for_compile = array();
  826. }
  827. //if (isset($this->EE->load->_ci_cached_vars['script_foot']))
  828. //{
  829. //$script = $this->EE->load->_ci_cached_vars['script_foot'];
  830. //$script = preg_replace('/\s*eeSpell\.init\(\);\s*/', '', $script);
  831. //$this->head .= $script;
  832. //}
  833. //add datepicker class
  834. if ($this->datepicker)
  835. {
  836. $date_fmt = $this->EE->session->userdata('time_format');
  837. $date_fmt = $date_fmt ? $date_fmt : $this->EE->config->item('time_format');
  838. $this->head .= '<style type="text/css">.hasDatepicker{background:#fff url('.$this->EE->config->item('theme_folder_url').'cp_themes/default/images/calendar_bg.gif) no-repeat 98% 2px;background-repeat:no-repeat;background-position:99%;}</style>';
  839. $this->head .= trim('
  840. <script type="text/javascript">
  841. $.createDatepickerTime=function(){
  842. date = new Date();
  843. hours = date.getHours();
  844. minutes = date.getMinutes();
  845. suffix = "";
  846. format = "'.$date_fmt.'";
  847. if (minutes < 10) {
  848. minutes = "0" + minutes;
  849. }
  850. if (format == "us") {
  851. if (hours > 12) {
  852. hours -= 12;
  853. suffix = " PM";
  854. } else if (hours == 12) {
  855. suffix = " PM";
  856. } else {
  857. suffix = " AM";
  858. }
  859. }
  860. return " \'" + hours + ":" + minutes + suffix + "\'";
  861. }
  862. EE.date_obj_time = $.createDatepickerTime();
  863. </script>');
  864. }
  865. //make head appear by default
  866. if (preg_match('/'.LD.'safecracker_head'.RD.'/', $return))
  867. {
  868. $return = $this->EE->TMPL->swap_var_single('safecracker_head', $this->head, $return);
  869. }
  870. // Head should only be there if the param is there and there is a valid member_id
  871. else if (
  872. $this->bool_string($this->EE->TMPL->fetch_param('safecracker_head'), TRUE) AND
  873. ($this->logged_out_member_id OR $this->EE->session->userdata('member_id'))
  874. )
  875. {
  876. $return .= $this->head;
  877. }
  878. //added in 1.0.3
  879. if ($this->bool_string($this->EE->TMPL->fetch_param('secure_action')))
  880. {
  881. $return = preg_replace('/(<form.*?action=")http:/', '\\1https:', $return);
  882. }
  883. $return = $this->EE->functions->insert_action_ids($return);
  884. // -------------------------------------------
  885. // 'safecracker_entry_form_tagdata_end' hook.
  886. // - Developers, if you want to modify the $this object remember
  887. // to use a reference on func call.
  888. //
  889. if ($this->EE->extensions->active_hook('safecracker_entry_form_tagdata_end') === TRUE)
  890. {
  891. $return = $this->EE->extensions->call('safecracker_entry_form_tagdata_end', $return, $this);
  892. if ($this->EE->extensions->end_script === TRUE) return;
  893. }
  894. return $return;
  895. }
  896. // --------------------------------------------------------------------
  897. /**
  898. * Creates or edits an entry
  899. *
  900. * @return void
  901. */
  902. public function submit_entry()
  903. {
  904. $this->initialize();
  905. $this->fetch_site(FALSE, $this->EE->input->post('site_id', TRUE));
  906. $this->fetch_channel($this->EE->input->post('channel_id', TRUE));
  907. $this->EE->load->helper(array('url', 'form'));
  908. $this->EE->load->library('api');
  909. $this->EE->api->instantiate('channel_fields');
  910. $this->EE->load->library('filemanager');
  911. $this->EE->load->library('form_validation');
  912. $this->EE->load->library('localize');
  913. $this->EE->load->model(array('field_model', 'tools_model'));
  914. $this->EE->filemanager->_initialize(array());
  915. $this->EE->lang->loadfile('content');
  916. $this->EE->lang->loadfile('form_validation');
  917. $this->EE->lang->loadfile('safecracker');
  918. $this->EE->router->set_class('cp');
  919. $this->EE->load->library('cp');
  920. $this->EE->router->set_class('ee');
  921. $rules = $this->EE->input->post('rules');
  922. //just to prevent any errors
  923. if ( ! defined('BASE'))
  924. {
  925. $s = ($this->EE->config->item('admin_session_type') != 'c') ? $this->EE->session->userdata('session_id') : 0;
  926. define('BASE', SELF.'?S='.$s.'&amp;D=cp');
  927. }
  928. $this->json = $this->EE->input->post('json');
  929. $this->error_handling = $this->EE->input->post('error_handling');
  930. // -------------------------------------------
  931. // 'safecracker_submit_entry_start' hook.
  932. // - Developers, if you want to modify the $this object remember
  933. // to use a reference on func call.
  934. //
  935. if ($this->EE->extensions->active_hook('safecracker_submit_entry_start') === TRUE)
  936. {
  937. $this->EE->extensions->call('safecracker_submit_entry_start', $this);
  938. if ($this->EE->extensions->end_script === TRUE) return;
  939. }
  940. $logged_out_member_id = FALSE;
  941. if ( ! $this->EE->session->userdata('member_id') && $this->EE->input->post('logged_out_member_id'))
  942. {
  943. if ($logged_out_member_id = $this->decrypt_input($this->EE->input->post('logged_out_member_id')))
  944. {
  945. $this->fetch_logged_out_member($logged_out_member_id);
  946. }
  947. }
  948. else if ($this->channel('channel_id') && ! $this->EE->session->userdata('member_id') && ! empty($this->settings['logged_out_member_id'][$this->EE->config->item('site_id')][$this->channel('channel_id')]))
  949. {
  950. $this->fetch_logged_out_member($this->settings['logged_out_member_id'][$this->EE->config->item('site_id')][$this->channel('channel_id')]);
  951. }
  952. //captcha check
  953. if ($this->channel('channel_id') && ! empty($this->logged_out_member_id) && ! empty($this->settings['require_captcha'][$this->EE->config->item('site_id')][$this->EE->input->post('channel_id', TRUE)]))
  954. {
  955. if ( ! $this->EE->input->post('captcha'))
  956. {
  957. $this->errors[] = lang('captcha_required');
  958. }
  959. $this->EE->db->where('word', $this->EE->input->post('captcha', TRUE));
  960. $this->EE->db->where('ip_address', $this->EE->input->ip_address());
  961. $this->EE->db->where('date > ', '(UNIX_TIMESTAMP()-7200)', FALSE);
  962. if ( ! $this->EE->db->count_all_results('captcha'))
  963. {
  964. $this->errors[] = lang('captcha_incorrect');
  965. }
  966. $this->EE->db->where('word', $this->EE->input->post('captcha', TRUE));
  967. $this->EE->db->where('ip_address', $this->EE->input->ip_address());
  968. $this->EE->db->where('date < ', '(UNIX_TIMESTAMP()-7200)', FALSE);
  969. $this->EE->db->delete('captcha');
  970. }
  971. //is an edit form?
  972. if ($this->EE->input->post('entry_id'))
  973. {
  974. $this->edit = TRUE;
  975. $this->fetch_entry($this->EE->input->post('entry_id', TRUE));
  976. if ($this->EE->input->post('category') === FALSE && $this->entry('categories'))
  977. {
  978. $_POST['category'] = $this->entry('categories');
  979. }
  980. }
  981. else
  982. {
  983. if ($this->EE->input->post('unique_url_title', TRUE))
  984. {
  985. $_POST['url_title'] = uniqid($this->EE->input->post('url_title', TRUE) ? $this->EE->input->post('url_title', TRUE) : url_title($this->EE->input->post('title', TRUE)), TRUE);
  986. }
  987. $this->entry['dst_enabled'] = $this->EE->input->post('dst_enabled');
  988. }
  989. $this->preserve_checkboxes = $this->bool_string($this->EE->input->post('preserve_checkboxes'), FALSE);
  990. // If any checkbox fields are missing from the POST array,
  991. // add them in as blank values for form validation to catch
  992. foreach (explode('|', $_POST['checkbox_fields']) as $checkbox)
  993. {
  994. if ( ! isset($_POST[$checkbox]))
  995. {
  996. $_POST[$checkbox] = '';
  997. }
  998. }
  999. foreach ($this->custom_fields as $i => $field)
  1000. {
  1001. $isset = (isset($_POST['field_id_'.$field['field_id']]) || isset($_POST[$field['field_name']]) || (((isset($_FILES['field_id_'.$field['field_id']]) && $_FILES['field_id_'.$field['field_id']]['error'] != 4) || (isset($_FILES[$field['field_name']]) && $_FILES[$field['field_name']]['error'] != 4)) && in_array($field['field_type'], $this->file_fields)));
  1002. // If file exists, add it to the POST array for validation
  1003. if (isset($_FILES[$field['field_name']]['name']))
  1004. {
  1005. $_POST[$field['field_name']] = $_FILES[$field['field_name']]['name'];
  1006. }
  1007. $this->custom_fields[$i]['isset'] = $isset;
  1008. if ( ! $this->edit || $isset)
  1009. {
  1010. $field_rules = array();
  1011. if ( ! empty($rules[$field['field_name']]))
  1012. {
  1013. if (($rules_decrypted = $this->decrypt_input($rules[$field['field_name']])) === FALSE)
  1014. {
  1015. $this->EE->output->show_user_error(FALSE, lang('form_decryption_failed'));
  1016. }
  1017. $field_rules = explode('|', $rules_decrypted);
  1018. }
  1019. if ( ! in_array('call_field_validation['.$field['field_id'].']', $field_rules))
  1020. {
  1021. array_unshift($field_rules, 'call_field_validation['.$field['field_id'].']');
  1022. }
  1023. if ($field['field_required'] == 'y' && ! in_array('required', $field_rules))
  1024. {
  1025. array_unshift($field_rules, 'required');
  1026. }
  1027. $this->EE->form_validation->set_rules($field['field_name'], $field['field_label'], implode('|', $field_rules));
  1028. }
  1029. else
  1030. {
  1031. if ($field['field_type'] == 'date')
  1032. {
  1033. $_POST['field_id_'.$field['field_id']] = $_POST[$field['field_name']] = $this->EE->localize->set_human_time($this->entry($field['field_name']));
  1034. }
  1035. else if ($field['field_required'] == 'y')
  1036. {
  1037. //add a dummy value to be removed later
  1038. //to get around _check_data_for_errors, a redundant check
  1039. $_POST['field_id_'.$field['field_id']] = '1';
  1040. }
  1041. }
  1042. //$this->EE->form_validation->set_rules($field['field_name'], $field['field_label'], implode('|', $field_rules));
  1043. foreach ($_POST as $key => $value)
  1044. {
  1045. //change field_name'd POSTed keys to field_id's
  1046. if ($key == $field['field_name'])
  1047. {
  1048. //@TODO what to do about xss_clean and "naughty" html
  1049. //for now you can crack open this file and manually add fields_ids and/or field types to the respective arrays
  1050. //to prevent xss_clean
  1051. //i had some people complain about not being able to submit <object>'s
  1052. $xss_clean = ( ! in_array($field['field_id'], $this->skip_xss_field_ids) && ! in_array($field['field_type'], $this->skip_xss_fieldtypes));
  1053. $_POST['field_id_'.$field['field_id']] = $this->EE->input->post($key, $xss_clean);
  1054. //auto set format if not POSTed
  1055. $fmt = $field['field_fmt'];
  1056. if ($this->EE->input->post('field_ft_'.$field['field_id']) !== FALSE)
  1057. {
  1058. $fmt = $this->EE->input->post('field_ft_'.$field['field_id'], TRUE);
  1059. }
  1060. elseif ($this->EE->input->post($field['field_name'].'_ft') !== FALSE)
  1061. {
  1062. $fmt = $this->EE->input->post($field['field_name'].'_ft', TRUE);
  1063. }
  1064. $_POST['field_ft_'.$field['field_id']] = $fmt;
  1065. }
  1066. else if (preg_match('/^'.$field['field_name'].'_(.+)/', $key, $match))
  1067. {
  1068. //also change utility POST fields, ie my_field_field_directory to field_id_X_directory
  1069. $_POST['field_id_'.$field['field_id'].'_'.$match[1]] = $this->EE->input->post($key, TRUE);
  1070. }
  1071. }
  1072. if (in_array($field['field_type'], $this->file_fields) || $field['field_type'] == 'matrix')
  1073. {
  1074. //change field_name'd POSTed files to field_id's
  1075. foreach ($_FILES as $key => $value)
  1076. {
  1077. if ($key == $field['field_name'])
  1078. {
  1079. $_FILES['field_id_'.$field['field_id']] = $value;
  1080. unset($_FILES[$key]);
  1081. // Check to see if a file was actually selected
  1082. if ($_POST[$field['field_name']] === 'NULL')
  1083. {
  1084. if ( ! empty($_POST[$field['field_name'].'_existing']))
  1085. {
  1086. $_POST[$field['field_name']] = $_POST[$field['field_name'].'_existing'];
  1087. }
  1088. else if ( ! empty($_POST[$field['field_name'].'_hidden']))
  1089. {
  1090. $_POST[$field['field_name']] = $_POST[$field['field_name'].'_hidden'];
  1091. }
  1092. else
  1093. {
  1094. $_POST[$field['field_name']] = '';
  1095. }
  1096. }
  1097. }
  1098. else if (preg_match('/^'.$field['field_name'].'_(.+)/', $key, $match))
  1099. {
  1100. $_FILES['field_id_'.$field['field_id'].'_'.$match[1]] = $value;
  1101. unset($_FILES[$key]);
  1102. }
  1103. }
  1104. }
  1105. }
  1106. foreach ($this->title_fields as $field)
  1107. {
  1108. if (isset($this->default_fields[$field]))
  1109. {
  1110. $this->EE->api_channel_fields->set_settings($field, $this->default_fields[$field]);
  1111. $this->EE->form_validation->set_rules($field, $this->default_fields[$field]['field_label'], $this->default_fields[$field]['rules']);
  1112. }
  1113. if ($this->EE->input->post($field) !== FALSE)
  1114. {
  1115. $_POST[$field] = $this->EE->input->post($field, TRUE);
  1116. }
  1117. else
  1118. {
  1119. if ($field == 'entry_date')
  1120. {
  1121. if ($this->entry($field))
  1122. {
  1123. $_POST[$field] = $this->EE->localize->set_human_time($this->entry($field));
  1124. }
  1125. else
  1126. {
  1127. $_POST[$field] = $this->EE->localize->set_human_time($this->EE->localize->now);
  1128. }
  1129. }
  1130. else
  1131. {
  1132. if ($this->entry($field) !== FALSE)
  1133. {
  1134. if ( ! in_array($field, $this->checkboxes) || $this->preserve_checkboxes)
  1135. {
  1136. $_POST[$field] = $this->entry($field);
  1137. }
  1138. }
  1139. }
  1140. }
  1141. }
  1142. //don't override status on edit, only on publish
  1143. if ( ! $this->edit && ! empty($this->settings['override_status'][$this->EE->config->item('site_id')][$this->EE->input->post('channel_id')]))
  1144. {
  1145. $_POST['status'] = $this->settings['override_status'][$this->EE->config->item('site_id')][$this->EE->input->post('channel_id')];
  1146. }
  1147. $_POST['ping_servers'] = (is_array($this->EE->input->post('ping'))) ? $this->EE->input->post('ping', TRUE) : array();
  1148. $_POST['ping_errors'] = FALSE;
  1149. $_POST['revision_post'] = $_POST;
  1150. $this->load_session_override();
  1151. //added for EE2.1.2
  1152. $this->EE->api->instantiate(array('channel_categories'));
  1153. $this->EE->load->library('api/api_sc_channel_entries');
  1154. foreach ($this->form_validation_methods as $method)
  1155. {
  1156. $this->EE->form_validation->set_message($method, lang('safecracker_'.$method));
  1157. }
  1158. if ($this->EE->input->post('dynamic_title'))
  1159. {
  1160. $dynamic_title = base64_decode($this->EE->input->post('dynamic_title'));
  1161. foreach ($_POST as $key => $value)
  1162. {
  1163. if (is_string($value) && strstr($dynamic_title, '['.$key.']') !== FALSE)
  1164. {
  1165. $dynamic_title = str_replace('['.$key.']', $value, $dynamic_title);
  1166. }
  1167. }
  1168. $_POST['title'] = $dynamic_title;
  1169. }
  1170. foreach ($this->EE->api_channel_fields->settings as $field_id => $settings)
  1171. {
  1172. $settings['field_name'] = 'field_id_'.$field_id;
  1173. if (isset($settings['field_settings']))
  1174. {
  1175. $settings = array_merge($settings, $this->unserialize($settings['field_settings'], TRUE));
  1176. }
  1177. $this->EE->api_channel_fields->settings[$field_id] = $this->EE->session->cache['safecracker']['field_settings'][$field_id] = $settings;
  1178. }
  1179. //moved to before custom field processing,
  1180. //since we are now using the call_field_validation rule
  1181. if ( ! $this->EE->form_validation->run())
  1182. {
  1183. $this->field_errors = $this->EE->form_validation->_error_array;
  1184. }
  1185. if ( ! $this->EE->security->check_xid($this->EE->input->post('XID')))
  1186. {
  1187. $this->EE->functions->redirect(stripslashes($this->EE->input->post('RET')));
  1188. }
  1189. if (empty($this->field_errors) && empty($this->errors))
  1190. {
  1191. //temporarily change site_id for cross-site forms
  1192. //channel_entries api doesn't allow you to specifically set site_id
  1193. $current_site_id = $this->EE->config->item('site_id');
  1194. $this->EE->config->set_item('site_id', $this->site_id);
  1195. if (in_array($this->channel('channel_id'), $this->EE->functions->fetch_assigned_channels()))
  1196. {
  1197. if ($this->entry('entry_id'))
  1198. {
  1199. $submit = $this->EE->api_sc_channel_entries->update_entry($this->entry('entry_id'), $_POST);
  1200. }
  1201. else
  1202. {
  1203. $submit = $this->EE->api_sc_channel_entries->submit_new_entry($this->channel('channel_id'), $_POST);
  1204. }
  1205. if ( ! $submit)
  1206. {
  1207. $this->errors = $this->EE->api_sc_channel_entries->errors;
  1208. }
  1209. }
  1210. else
  1211. {
  1212. $this->errors[] = lang('unauthorized_for_this_channel');
  1213. }
  1214. $this->EE->config->set_item('site_id', $current_site_id);
  1215. $this->clear_entry();
  1216. //load the just created entry into memory
  1217. $this->fetch_entry($this->EE->api_sc_channel_entries->entry_id);
  1218. }
  1219. $this->unload_session_override();
  1220. // -------------------------------------------
  1221. // 'safecracker_submit_entry_end' hook.
  1222. // - Developers, if you want to modify the $this object remember
  1223. // to use a reference on func call.
  1224. //
  1225. if ($thi

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