PageRenderTime 37ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/bors/form_save.php

https://bitbucket.org/Balancer/bors-core
PHP | 442 lines | 357 code | 71 blank | 14 comment | 96 complexity | 248217a26bd2958d0ed089b365633133 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. <?php
  2. //передать также: 'subaction'
  3. function bors_form_save($obj)
  4. {
  5. if(($post_js = @$_GET['javascript_post_append']))
  6. session_array_append('javascript_post_append', $post_js);
  7. if(!empty($_GET['act']))
  8. {
  9. if($_GET['act'] == 'skip_all')
  10. return false;
  11. if(!empty($_GET['object']))
  12. $obj = bors_load_uri($_GET['object']);
  13. if(method_exists($obj, 'action_target'))
  14. $obj = $obj->action_target();
  15. if(!$obj->access())
  16. return bors_message(ec("Не заданы режимы доступа класса ").get_class($obj)."; access_engine=".$obj->access_engine());
  17. if(!$obj->access()->can_action($_GET['act'], $_GET))
  18. {
  19. // jquery::load();
  20. $sorry = _("Извините, у Вас недостаточный уровень доступа для операций с этим ресурсом");
  21. $info = _("Служебная информация");
  22. $message = "<div class=\"alert alert-error\">{$sorry} ({$obj->titled_link()} -> {$obj->access()} -> can_action())</div>
  23. <div class=\"accordion\" id=\"sysinfoacc\">
  24. <div class=\"accordion-group\">
  25. <div class=\"accordion-heading\">
  26. <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#sysinfoacc\" href=\"#sysinfodata\">
  27. $info
  28. </a>
  29. </div>
  30. <div id=\"sysinfodata\" class=\"accordion-body collapse\">
  31. <div class=\"accordion-inner\">
  32. object class = ".get_class($obj).",<br/>
  33. access class = ".get_class($obj->access()).",<br/>
  34. access method = can_action(".$_GET['act'].");<br/>
  35. <pre>".bors_debug::trace(0, false)."
  36. </pre></div>
  37. </div>
  38. </div>
  39. </div>
  40. ";
  41. echo twitter_bootstrap::raw_message(array(
  42. 'this' => bors_load('bors_pages_fake', array(
  43. 'title' => ec('Ошибка прав доступа'),
  44. 'body' => $message,
  45. )),
  46. ));
  47. return true;
  48. }
  49. if(method_exists($obj, $method = "on_action_{$_GET['act']}"))
  50. {
  51. $result = $obj->$method($_GET);
  52. if($result === true)
  53. return true;
  54. }
  55. }
  56. if(method_exists($obj, 'on_action'))
  57. {
  58. //TODO: придумать, как унифицировать с классом-сейвером
  59. $form = bors_load(@$_GET['form_class_name'], @$_GET['form_object_id']);
  60. if(!empty($_GET['saver_prepare_classes']))
  61. {
  62. foreach(explode(',', $_GET['saver_prepare_classes']) as $cn)
  63. if(true === call_user_func(array($cn, 'saver_prepare'), $_GET))
  64. return true;
  65. }
  66. if(method_exists($obj, 'action_target'))
  67. $obj = $obj->action_target();
  68. if(!$obj->access())
  69. return bors_message(ec("Не заданы режимы доступа класса ").get_class($obj)."; access_engine=".$obj->access_engine());
  70. if(!$obj->access()->can_action(NULL, $_GET))
  71. return bors_message(ec("[0] Извините, Вы не можете производить операции с этим ресурсом (class=".get_class($obj).", access=".get_class($obj->access()).", method=can_action)"));
  72. $result = $obj->on_action($_GET);
  73. if($result === true)
  74. return true;
  75. }
  76. $class_name = @$_GET['class_name'];
  77. $form_class_name = @$_GET['form_class_name'];
  78. if(
  79. ($class_name && $class_name != 'NULL')
  80. || ($form_class_name && $form_class_name != 'NULL'))
  81. {
  82. if($class_name)
  83. $tmp = new $class_name(NULL);
  84. elseif($form_class_name)
  85. $tmp = new $form_class_name(NULL);
  86. else
  87. $tmp = NULL;
  88. if($form_saver_class = object_property($tmp, 'form_saver_class'))
  89. return object_load($form_saver_class)->save($obj, $_GET, $_FILES);
  90. elseif($form_saver_class = config('form_saver.class_name'))
  91. return object_load($form_saver_class)->save($obj, $_GET, $_FILES);
  92. $objects_common_data = array();
  93. $objects_data = array();
  94. $files_as_array = true;
  95. foreach($_FILES as $name => $params)
  96. {
  97. foreach($params as $key => $value)
  98. {
  99. if(is_array($value))
  100. {
  101. foreach($value as $idx => $val2)
  102. {
  103. $objects_data[$idx]['uploaded_file'][$key] = $val2;
  104. $objects_data[$idx]['uploaded_file']['upload_name'] = $name;
  105. }
  106. }
  107. else
  108. {
  109. $files_as_array = false;
  110. $objects_common_data['uploaded_file'][$key] = $value;
  111. $objects_common_data['uploaded_file']['upload_name'] = $name;
  112. }
  113. }
  114. if(!$files_as_array)
  115. $objects_data[]['uploaded_file'] = $objects_common_data['uploaded_file'];
  116. }
  117. if(empty($_GET['checkboxes_list']))
  118. $checkboxes_list = array();
  119. else
  120. $checkboxes_list = explode(',', $_GET['checkboxes_list']);
  121. if(!empty($_GET['checkboxes']))
  122. {
  123. foreach(explode(',', $_GET['checkboxes']) as $cbn)
  124. {
  125. $cbn = str_replace('[]', '', $cbn);
  126. if(empty($_GET[$cbn]))
  127. $_GET[$cbn] = 0;
  128. }
  129. unset($_GET['checkboxes']);
  130. }
  131. foreach($_GET as $key => $value)
  132. {
  133. if(is_array($value) && !in_array($key, $checkboxes_list))
  134. {
  135. foreach($value as $idx => $val2)
  136. $objects_data[$idx][$key] = $val2;
  137. }
  138. else
  139. $objects_common_data[$key] = $value;
  140. }
  141. $form = $obj;
  142. if($objects_data)
  143. {
  144. $first = true;
  145. $total = count($objects_data);
  146. $count = 0;
  147. foreach($objects_data as $idx => $data)
  148. {
  149. $last = (++$count == $total);
  150. $data = array_merge($objects_common_data, $data);
  151. $result = bors_form_save_object($data['class_name'], @$data['object_id'], $data, $first, $last);
  152. if($result === true || is_object($result))
  153. $form = $result;
  154. if(true === $result)
  155. break;
  156. $first = false;
  157. }
  158. }
  159. else
  160. $form = bors_form_save_object($_GET['class_name'], @$_GET['object_id'], $objects_common_data, true, true);
  161. if($form === true)
  162. return true;
  163. if($form->has_changed())
  164. {
  165. if($post_message = pop_session_var('post_message'))
  166. {
  167. $link_url = bors_form_parse_vars(pop_session_var('post_message_link_url'), $form);
  168. $post_message = bors_form_parse_vars($post_message, $form);
  169. return bors_message($post_message, array(
  170. 'title' => ec('Данные сохранены'),
  171. 'link_text' => pop_session_var('post_message_link_text'),
  172. 'link_url' => $link_url,
  173. 'data' => array(
  174. 'target_admin_url' => $form->admin_url(1),
  175. )
  176. ));
  177. }
  178. if(!empty($_GET['go_on_update']))
  179. $_GET['go'] = $_GET['go_on_update'];
  180. }
  181. if(!empty($_GET['go']))
  182. {
  183. if($_GET['go'] == "newpage")
  184. return go($form->url());
  185. if($_GET['go'] == "newpage_admin")
  186. return go($form->admin_url());
  187. if($_GET['go'] == "newpage_edit_parent" || $_GET['go'] == "admin_parent")
  188. {
  189. $p = object_load($form->admin_url());
  190. if($p)
  191. {
  192. $p = $p->parents();
  193. return go($p[0]);
  194. }
  195. return go($form->url());
  196. }
  197. if($form)
  198. {
  199. $_GET['go'] = str_replace('%OBJECT_ID%', $form->id(), $_GET['go']);
  200. $_GET['go'] = str_replace('%OBJECT_URL%', $form->url(), $_GET['go']);
  201. }
  202. require_once('inc/navigation.php');
  203. return go($_GET['go']);
  204. }
  205. }
  206. return false;
  207. }
  208. function bors_form_save_object($class_name, $id, &$data, $first, $last)
  209. {
  210. if($field = @$data['multiple_check_field'])
  211. if(empty($data[$field]))
  212. return;
  213. if($id)
  214. {
  215. $object = object_load($class_name, $id);
  216. if(!$object)
  217. $object = object_new($class_name, $id);
  218. }
  219. else
  220. $object = object_new($class_name);
  221. if(!$object)
  222. return bors_message(ec("Не могу сохранить объект ")."{$class_name}({$id})");
  223. if($first)
  224. {
  225. $processed = $object->pre_action($data);
  226. if($processed === true)
  227. return true;
  228. if(!$object->access())
  229. return bors_message(ec("Не заданы режимы доступа класса ").get_class($object)."; access_engine=".$object->access_engine());
  230. if(!$object->access()->can_action(@$data['act'], $data))
  231. return bors_message(ec("[2fs] Извините, Вы не можете производить операции с этим ресурсом<br/><small>(class=".get_class($object).", access=".($object->access_engine())."/".get_class($object->access()).", method=can_action)</small>"));
  232. if(empty($data['subaction']))
  233. $method = '';
  234. else
  235. $method = '_'.addslashes($data['subaction']);
  236. // echo "? - $object->$method()";
  237. if(method_exists($object, $method = 'on_action'.$method))
  238. if($object->$method($data))
  239. return true;
  240. }
  241. if(($ret = $object->check_data($data)))
  242. return $ret;
  243. foreach($data as $key => $val)
  244. {
  245. if(!$val || !preg_match("!^file_(\w+)_delete_do$!", $key, $m))
  246. continue;
  247. $method = "remove_{$m[1]}_file";
  248. $object->$method($data);
  249. }
  250. if($file_data = @$data['uploaded_file'])
  251. {
  252. if($file_data['tmp_name'])
  253. $object->{'upload_'.$file_data['upload_name'].'_file'}($file_data, $data);
  254. elseif(@$file_data['name'])
  255. bors_exit(ec("Ошибка загрузки изображения ").$file_data['name']);
  256. }
  257. // echo "Set fields for $object: ".print_d($data, true).", last=$last{}<br/>"; exit();
  258. if($first)
  259. $object->pre_set($data);
  260. //TODO: костыль для bors_admin_image_append
  261. // Для исправной работы старых кривых ссылоки вида http://balancer.ru/tools/search/result/?q=%D1%82%D1%8D%D0%BC2%D1%83&w=a&s=r&class_name=bors_tools_search
  262. // Проверка: bors_tools_search
  263. if(method_exists($object, 'skip_save') && $object->skip_save())
  264. {
  265. if(!$object->set_fields($data, true))
  266. return true;
  267. }
  268. else
  269. {
  270. if(!$object->set_fields($data, true))//array_intersect_key($data, bors_lib_orm::all_field_names($object, false)), true))
  271. return true;
  272. }
  273. if($last && $object->has_changed())
  274. {
  275. $object->set_modify_time(time());
  276. $object->set_last_editor_id(bors()->user_id());
  277. $object->set_last_editor_ip(bors()->client()->ip());
  278. $object->set_last_editor_ua(bors()->client()->agent());
  279. if($object->id()) // post_set() вызывается только для уже существующих объектов.
  280. $object->post_set($data);
  281. }
  282. if(!$object->id() && method_exists($object, 'new_instance'))
  283. {
  284. $object->new_instance($data);
  285. $object->on_new_instance($data);
  286. $was_new = true;
  287. }
  288. else
  289. $was_new = false;
  290. if(method_exists($object, 'post_save'))
  291. $object->post_save($data);
  292. $_GET['go'] = defval($data, 'go', @$_GET['go']);
  293. $_GET['go_on_update'] = defval($data, 'go_on_update', @$_GET['go_on_update']);
  294. if(!empty($data['bind_to']) && preg_match('!^(\w+)://(\d+)!', $data['bind_to'], $m))
  295. $object->add_cross($m[1], $m[2], intval(@$data['bind_order']));
  296. if($data['form_class_name'] != $data['class_name'])
  297. {
  298. if(!$object->id() && !(method_exists($object, 'skip_save') && $object->skip_save())) //TODO: костыль для bors_admin_image_append
  299. {
  300. if($x = $object->empty_id_handler())
  301. return $x;
  302. else
  303. return bors_throw(ec('Пустой id нового объекта ').$object->class_name().ec('. Возможно нужно использовать function replace_on_new_instance() { return true; }'));
  304. }
  305. }
  306. // echo "Final id: {$object->id()}<br />";
  307. // bors()->changed_save();
  308. if($object->has_changed())
  309. add_session_message(ec('Данные успешно сохранены')/*.print_r(bors()->changed_objects(), true)*/, array('type' => 'success'));
  310. // echo session_message(array('type' => 'success'));
  311. // exit( '?');
  312. if($was_new)
  313. $object->b2_post_new($data);
  314. else
  315. $object->b2_post_update($data);
  316. return $object;
  317. }
  318. function bors_form_errors($data, $conditions = array())
  319. {
  320. set_session_form_data($data);
  321. foreach($conditions as $error_condition => $fail_message)
  322. {
  323. if(is_numeric($error_condition) && !is_array($fail_message))
  324. {
  325. $error_condition = $fail_message;
  326. $fail_message = NULL;
  327. }
  328. $error_cond = @trim($error_condition);
  329. if(is_callable($error_condition))
  330. {
  331. $error_cond = call_user_func($callback, $data);
  332. }
  333. elseif(is_array($fail_message))
  334. {
  335. $fields = array($fail_message[0]);
  336. $error_cond = $fail_message[1];
  337. $fail_message = $fail_message[2];
  338. }
  339. elseif(preg_match('/^!(\w+)$/', $error_cond, $m))
  340. {
  341. $fields = array($m[1]);
  342. $error_cond = empty($data[$m[1]]);
  343. if(!$fail_message && !empty($data['class_name']))
  344. {
  345. // var_dump($data);
  346. $f = bors_lib_orm::parse_property($data['class_name'], $m[1]);
  347. // var_dump($f); exit();
  348. $fail_message = ec('Не заполнено поле «').defval($f, 'title', $m[1]).ec('»');
  349. }
  350. }
  351. elseif(preg_match('/^(\w+)\s*!=\s*(\w+)$/', $error_cond, $m))
  352. {
  353. $fields = array($m[1], $m[2]);
  354. $error_cond = @$data[$m[1]] != @$data[$m[2]];
  355. }
  356. else
  357. throw new Exception("Unknown check_form_data condition string: '$error_condition' => '$fail_message'");
  358. if($error_cond)
  359. {
  360. set_session_var('error_fields', join(',', $fields));
  361. return $fail_message;
  362. }
  363. }
  364. return NULL;
  365. }
  366. function bors_form_parse_vars($text, $object)
  367. {
  368. $text = str_replace('{$target_admin_url}', $object->admin()->url(), $text);
  369. $text = str_replace('$target_admin_url', $object->admin()->url(), $text);
  370. return $text;
  371. }