PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Adapto/Handler/Export.php

http://github.com/egeniq/adapto
PHP | 581 lines | 395 code | 73 blank | 113 comment | 75 complexity | e39c22efa3b9a537a7d8ae6db86c1bf0 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Adapto Toolkit.
  4. * Detailed copyright and licensing information can be found
  5. * in the doc/COPYRIGHT and doc/LICENSE files which should be
  6. * included in the distribution.
  7. *
  8. * @package adapto
  9. * @subpackage handlers
  10. *
  11. * @copyright (c)2004 Ivo Jansch
  12. * @copyright (c)2004 Ibuildings.nl BV
  13. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  14. *
  15. */
  16. /**
  17. * Handler for the 'import' action of an entity. The import action is a
  18. * generic tool for importing CSV files into a table.
  19. *
  20. * @author ijansch
  21. * @package adapto
  22. * @subpackage handlers
  23. *
  24. */
  25. class Adapto_Handler_Export extends Adapto_ActionHandler
  26. {
  27. /**
  28. * The action handler.
  29. */
  30. function action_export()
  31. {
  32. global $Adapto_VARS;
  33. // Intercept partial call
  34. if (!empty($this->m_partial)) {
  35. $this->partial($this->m_partial);
  36. return;
  37. }
  38. // Intercept delete call
  39. if (array_key_exists('dodelete', $this->m_postvars) && ctype_digit($this->m_postvars['dodelete'])) {
  40. if (array_key_exists('confirmed', $this->m_postvars) && $this->m_postvars['confirmed'] == 'true') {
  41. $this->deleteSelection($this->m_postvars['dodelete']);
  42. }
  43. }
  44. //need to keep the postdata after a AF_LARGE selection in the allfield
  45. if (!isset($this->m_postvars["phase"]) && isset($Adapto_VARS['atkformdata']))
  46. foreach ($Adapto_VARS['atkformdata'] as $key => $value)
  47. $this->m_postvars[$key] = $value;
  48. //need to keep the selected item after an exporterror
  49. $phase = atkArrayNvl($this->m_postvars, "phase", "init");
  50. if (!in_array($phase, array("init", "process")))
  51. $phase = "init";
  52. switch ($phase) {
  53. case "init":
  54. $this->doInit();
  55. break;
  56. case "process":
  57. $this->doProcess();
  58. break;
  59. }
  60. return true;
  61. }
  62. /**
  63. * This function shows a form to configure the .csv
  64. */
  65. function doInit()
  66. {
  67. $content = $this->_getInitHtml();
  68. $page = &$this->getPage();
  69. $page
  70. ->register_scriptcode(
  71. "
  72. function toggleSelectionName( fieldval )
  73. {
  74. if( fieldval == undefined )
  75. {
  76. fieldval = $( 'export_selection_options' ).value;
  77. }
  78. new Ajax.Updater('export_attributes', '" . partial_url($this->m_postvars['atkentitytype'], 'export', 'export')
  79. . "exportvalue='+fieldval+'&' );
  80. if( fieldval != 'none' )
  81. {
  82. if( fieldval != 'new' )
  83. {
  84. new Ajax.Updater('selection_interact', '" . partial_url($this->m_postvars['atkentitytype'], 'export', 'selection_interact')
  85. . "exportvalue='+fieldval+'&' );
  86. new Ajax.Updater('export_name', '" . partial_url($this->m_postvars['atkentitytype'], 'export', 'selection_name')
  87. . "exportvalue='+fieldval+'&' );
  88. $( 'selection_interact' ).style.display='';
  89. $( 'export_name' ).style.display='';
  90. $( 'export_save_button' ).style.display='';
  91. }
  92. else
  93. {
  94. $( 'selection_interact' ).style.display='none';
  95. $( 'export_name' ).style.display='';
  96. $( 'export_selection_name' ).value='';
  97. $( 'export_selection_options' ).selectedIndex=0;
  98. $( 'export_save_button' ).style.display='none';
  99. }
  100. }
  101. else
  102. {
  103. $( 'export_name' ).style.display='none';
  104. $( 'selection_interact' ).style.display='none';
  105. $( 'export_save_button' ).style.display='none';
  106. $( 'export_selection_name' ).value='';
  107. }
  108. }");
  109. $page
  110. ->register_scriptcode(
  111. "
  112. function confirm_delete()
  113. {
  114. public where_to = confirm('" . atktext('confirm_delete') // defaulted to public
  115. . "');
  116. public dodelete = $( 'export_selection_options' ).value; // defaulted to public
  117. if (where_to == true)
  118. {
  119. window.location= \"" . dispatch_url($this->m_postvars['atkentitytype'], 'export', array('confirmed' => 'true'))
  120. . "&dodelete=\"+dodelete;
  121. }
  122. }");
  123. $page->addContent($this->m_entity->genericPage("export", $content));
  124. return true;
  125. }
  126. /**
  127. * Handle partial request
  128. *
  129. * @return string
  130. */
  131. public function partial_export()
  132. {
  133. $value = array_key_exists('exportvalue', $this->m_postvars) ? $this->m_postvars['exportvalue'] : null;
  134. return $this->getAttributeSelect($value);
  135. }
  136. /**
  137. * Partial fetches and displays the name of the selected value
  138. *
  139. * @return string
  140. */
  141. public function partial_selection_name()
  142. {
  143. $selected = array_key_exists('exportvalue', $this->m_postvars) ? $this->m_postvars['exportvalue'] : null;
  144. $value = '';
  145. if ($selected) {
  146. $db = atkGetDb();
  147. $rows = $db->getRows('SELECT name FROM Adapto_exportcriteria WHERE id = ' . (int) $selected);
  148. if (count($rows) == 1) {
  149. $value = htmlentities($rows[0]['name']);
  150. }
  151. }
  152. return '<td>' . atktext("export_selections_name", "atk")
  153. . ': </td><td align="left"><input type="text" size="40" name="export_selection_name" id="export_selection_name" value="' . $value
  154. . '"></td>
  155. <input type="hidden" name="exportvalue" value="' . $this->m_postvars['exportvalue'] . '" />';
  156. }
  157. /**
  158. * Partial displays a interaction possibilities with an export selection
  159. *
  160. * @return string
  161. */
  162. public function partial_selection_interact()
  163. {
  164. $selected = array_key_exists('exportvalue', $this->m_postvars) ? $this->m_postvars['exportvalue'] : null;
  165. $theme = Adapto_ClassLoader::getInstance('Adapto_Ui_Theme');
  166. $img_delete = $theme->iconPath('delete', 'recordlist');
  167. $url_delete = dispatch_url($this->m_entity->m_module . '.' . $this->m_entity->m_type, 'export', array('dodelete' => $selected));
  168. if ($selected) {
  169. $result = '<a href="' . $url_delete . '" title="' . atktext('delete_selection') . '" onclick="confirm_delete();"><img src="' . $img_delete
  170. . '" alt="' . atktext('delete_selection') . '" border="0" /></a>';
  171. return $result;
  172. }
  173. }
  174. /**
  175. * Gets the HTML for the initial mode of the exporthandler
  176. * @return String The HTML for the screen
  177. */
  178. function _getInitHtml()
  179. {
  180. $action = dispatch_url($this->m_entity->m_module . '.' . $this->m_entity->m_type, "export");
  181. $params = array();
  182. $params["formstart"] = '<form name="entryform" enctype="multipart/form-data" action="' . $action . '" method="post">';
  183. $params["formstart"] .= session_form();
  184. $params["formstart"] .= '<input type="hidden" name="phase" value="process"/>';
  185. $params["buttons"][] = '<input class="btn" type="submit" value="' . atkText("export", "atk") . '"/>';
  186. $params["buttons"][] = '<input id="export_save_button" style="display:none;" value="' . atktext("save_export_selection", "atk")
  187. . '" name="save_export" class="btn" type="submit" /> ';
  188. $params["buttons"][] = atkButton(atktext("back", "atk"), "", SESSION_BACK, true);
  189. $params["content"] = atkText("export_config_explanation", "atk", $this->m_entity->m_type) . '<br/><br/>';
  190. $params["content"] .= $this->_getOptions();
  191. $params["formend"] = '</form>';
  192. return Adapto_ClassLoader::getInstance("atk.ui.atkui")->renderAction("export", $params, $this->m_entity->m_module);
  193. }
  194. /**
  195. * This function checks if there is enough information to export the date
  196. * else it wil shows a form to set how the file wil be exported
  197. */
  198. function doProcess()
  199. {
  200. // Update selection
  201. if (array_key_exists('exportvalue', $this->m_postvars) && array_key_exists('save_export', $this->m_postvars)
  202. && '' != $this->m_postvars['export_selection_name']) {
  203. $this->updateSelection();
  204. $this->getEntity()->redirect(dispatch_url($this->getEntity(), 'export'));
  205. }
  206. // Save selection
  207. if (array_key_exists('export_selection_options', $this->m_postvars) && array_key_exists('export_selection_name', $this->m_postvars)
  208. && 'none' == $this->m_postvars['export_selection_options'] && '' != $this->m_postvars['export_selection_name']) {
  209. $this->saveSelection();
  210. }
  211. // Export CVS
  212. if (!array_key_exists('save_export', $this->m_postvars)) {
  213. return $this->doExport();
  214. }
  215. }
  216. /**
  217. * Get the options for the export
  218. *
  219. * @return unknown
  220. */
  221. function _getOptions()
  222. {
  223. $content = '<table border="0" width="100%">';
  224. // enable extended export options
  225. if (true === Adapto_Config::getGlobal('enable_export_save_selection')) {
  226. $content .= '<tr><td>' . atktext("export_selections", "atk") . ': </td><td align="left">' . $this->getExportSelectionDropdown()
  227. . '&nbsp;&nbsp;&nbsp;<a href="javascript:void(0);" onclick="toggleSelectionName(\'new\');return false;">' . atktext('new', 'atk')
  228. . '</a></td></tr>';
  229. $content .= '<tr><td>&nbsp;</td><td align="left"><div id="selection_interact"></div></td></tr>';
  230. $content .= '<tr id="export_name" style="display:none;"><td>' . atktext("export_selections_name", "atk")
  231. . ': </td><td align="left"><input type="text" size="40" id="export_selection_name" name="export_selection_name" value=""></td></tr>';
  232. }
  233. $content .= '<tr><td>' . atktext("delimiter", "atk") . ': </td><td><input type="text" size="2" name="delimiter" value=";"></td></tr>';
  234. $content .= '<tr><td>' . atktext("enclosure", "atk") . ': </td><td><input type="text" size="2" name="enclosure" value="&quot;"></td></tr>';
  235. $content .= '<tr><td valign="top">' . atktext("export_selectcolumns", "atk") . ': </td><td><div id="export_attributes">' . $this->getAttributeSelect()
  236. . '</div></td></tr>';
  237. $content .= '<tr><td>';
  238. $content .= atktext("export_generatetitlerow") . ': </td><td><input type="checkbox" name="generatetitlerow" class="atkcheckbox" value="1" />';
  239. $content .= '</td></tr>';
  240. $content .= '</table><br /><br />';
  241. return $content;
  242. }
  243. /**
  244. * Build the dropdown field to add the exportselections
  245. *
  246. * @return string
  247. */
  248. private function getExportSelectionDropdown()
  249. {
  250. $html = '
  251. <select name="export_selection_options" id="export_selection_options" onchange="javascript:toggleSelectionName( );return false;" >
  252. <option value="none">' . atktext('none', 'atk');
  253. $options = $this->getExportSelections();
  254. if (count($options)) {
  255. foreach ($options AS $option) {
  256. $html .= '
  257. <option value="' . $option['id'] . '">' . htmlentities($option['name']) . '</option>';
  258. }
  259. }
  260. $html .= '</select>';
  261. return $html;
  262. }
  263. /**
  264. * Store selectiondetails in the database
  265. *
  266. * @return null
  267. */
  268. private function saveSelection()
  269. {
  270. $db = atkGetDb();
  271. $id = $db->nextid('exportcriteria');
  272. $user_id = 0;
  273. if ('none' !== strtolower(Adapto_Config::getGlobal('authentication'))) {
  274. $user = atkGetUser();
  275. $user_id = array_key_exists(Adapto_Config::getGlobal('auth_userpk'), $user) ? $user[Adapto_Config::getGlobal('auth_userpk')] : 0;
  276. }
  277. // first check if the combination of entity, name and user_id doesn't already exist
  278. $rows = $db
  279. ->getRows(
  280. "SELECT id FROM Adapto_exportcriteria
  281. WHERE entitytype = '" . $this->m_postvars['atkentitytype'] . "'
  282. AND name = '" . $this->m_postvars['export_selection_name'] . "'
  283. AND user_id = " . $user_id);
  284. if (count($rows)) {
  285. return;
  286. }
  287. $query = 'INSERT INTO Adapto_exportcriteria ( id, entitytype, name, criteria, user_id )
  288. VALUES ( ' . $id . ', "' . $this->m_postvars['atkentitytype'] . '", "' . $db->escapeSQL($this->m_postvars['export_selection_name'])
  289. . '",
  290. "' . addslashes(serialize($this->m_postvars)) . '", ' . $user_id . ' )';
  291. $db->query($query);
  292. }
  293. /**
  294. * Update selectiondetails in the database
  295. *
  296. * @return null
  297. */
  298. private function updateSelection()
  299. {
  300. $db = atkGetDb();
  301. $user_id = 0;
  302. if ('none' !== strtolower(Adapto_Config::getGlobal('authentication'))) {
  303. $user = atkGetUser();
  304. $user_id = array_key_exists(Adapto_Config::getGlobal('auth_userpk'), $user) ? $user[Adapto_Config::getGlobal('auth_userpk')] : 0;
  305. }
  306. // first check if the combination of entity, name and user_id doesn't already exist
  307. $rows = $db
  308. ->getRows(
  309. "SELECT id FROM Adapto_exportcriteria
  310. WHERE entitytype = '" . $this->m_postvars['atkentitytype'] . "'
  311. AND name = '" . $this->m_postvars['export_selection_name'] . "'
  312. AND user_id = " . $user_id . "
  313. AND id <> " . (int) $this->m_postvars['exportvalue']);
  314. if (count($rows)) {
  315. return;
  316. }
  317. $query = 'UPDATE
  318. Adapto_exportcriteria
  319. SET
  320. name = "' . $db->escapeSQL($this->m_postvars['export_selection_name']) . '",
  321. criteria = "' . addslashes(serialize($this->m_postvars)) . '"
  322. WHERE
  323. id = ' . (int) $this->m_postvars['exportvalue'];
  324. $db->query($query);
  325. }
  326. /**
  327. * Delete record
  328. *
  329. * @param integer $id
  330. */
  331. private function deleteSelection($id)
  332. {
  333. $db = atkGetDb();
  334. $db->query('DELETE FROM atk_exportcriteria WHERE id = ' . (int) $id);
  335. }
  336. /**
  337. * Determine the export selections that should be displayed
  338. *
  339. * @return array
  340. */
  341. protected function getExportSelections()
  342. {
  343. $where = ' entitytype = "' . $this->m_postvars['atkentitytype'] . '"';
  344. if ('none' !== strtolower(Adapto_Config::getGlobal('authentication'))) {
  345. $user = atkGetUser();
  346. if ('administrator' !== strtolower($user['name'])) {
  347. $where .= ' AND user_id IN( 0, ' . (int) $user[Adapto_Config::getGlobal('auth_userpk')] . ' )';
  348. }
  349. }
  350. $db = atkGetDb();
  351. return $db->getRows($query = 'SELECT id, name FROM Adapto_exportcriteria WHERE ' . $where . ' ORDER BY name');
  352. }
  353. /**
  354. * Get all attributes to select for the export
  355. *
  356. * @return String HTML code with checkboxes for each attribute to select
  357. */
  358. function getAttributeSelect()
  359. {
  360. $cols = 5;
  361. $atts = $this->getUsableAttributes();
  362. $content = "";
  363. foreach ($atts as $tab => $group) {
  364. $content .= '<TABLE style="border: 1px solid #d8d8d8; width: 90%">';
  365. if ($tab != 'default') {
  366. $content .= '<TR><TD colspan="' . $cols . '"><div style="background-color: #ccc; color: #00366E; font-weight: bold">'
  367. . atktext(array("tab_$tab", $tab), $this->m_entity->m_module, $this->m_entity->m_type) . '</div></TD></TR><TR>';
  368. }
  369. $idx = 0;
  370. foreach ($group as $item) {
  371. if ($item['checked'])
  372. $checked = 'CHECKED';
  373. else
  374. $checked = '';
  375. $content .= '<TD align="left" width="' . (90 / $cols) . '%"><LABEL><INPUT type="checkbox" name="export_' . $item['name']
  376. . '" class="atkcheckbox" value="export_' . $item['name'] . '" ' . $checked . '>' . $item['text'] . '</LABEL></TD>';
  377. $idx++;
  378. if ($idx % $cols == 0) {
  379. $content .= '</TR><TR>';
  380. }
  381. }
  382. while ($idx % $cols != 0) {
  383. $content .= '<TD width="' . (90 / $cols) . '%">&nbsp;</TD>';
  384. $idx++;
  385. }
  386. $content .= "</TR></TABLE><BR/>";
  387. }
  388. return $content;
  389. }
  390. /**
  391. * Gives all the attributes that can be used for the import
  392. * @return array the attributes
  393. */
  394. function getUsableAttributes()
  395. {
  396. $selected = $value == 'new' ? false : true;
  397. $criteria = array();
  398. if (!in_array($value, array('new', 'none', ''))) {
  399. $db = atkGetDb();
  400. $rows = $db->getRows('SELECT * FROM Adapto_exportcriteria WHERE id = ' . (int) $value);
  401. $criteria = unserialize($rows[0]['criteria']);
  402. }
  403. $atts = array();
  404. $attriblist = $this->invoke('getExportAttributes');
  405. foreach ($attriblist as $key => $value) {
  406. $flags = $value->m_flags;
  407. $class = strtolower(get_class($value));
  408. if ($value->hasFlag(AF_AUTOKEY) || $value->hasFlag(AF_HIDE_VIEW) || !(strpos($class, "dummy") === FALSE) || !(strpos($class, "image") === FALSE)
  409. || !(strpos($class, 'tabbedpane') === FALSE))
  410. continue;
  411. if (method_exists($this->m_entity, "getExportAttributeGroup")) {
  412. $group = $this->m_entity->getExportAttributeGroup($value->m_name);
  413. } else {
  414. $group = $value->m_tabs[0];
  415. }
  416. if (in_array($group, $atts)) {
  417. $atts[$group] = array();
  418. }
  419. // selected options based on a new selection, or no selection
  420. if (empty($criteria)) {
  421. $atts[$group][] = array('name' => $key, 'text' => $value->label(), 'checked' => $selected == true ? !$value->hasFlag(AF_HIDE_LIST) : false);
  422. }
  423. // selected options based on a selection from DB
  424. else {
  425. $atts[$group][] = array('name' => $key, 'text' => $value->label(), 'checked' => in_array('export_' . $key, $criteria) ? true : false);
  426. }
  427. }
  428. return $atts;
  429. }
  430. /**
  431. * Return all attributes that can be exported
  432. *
  433. * @return array Array with attribs that needs to be exported
  434. */
  435. function getExportAttributes()
  436. {
  437. $attribs = $this->m_entity->getAttributes();
  438. if (is_null($attribs)) {
  439. return array();
  440. } else {
  441. return $attribs;
  442. }
  443. }
  444. /**
  445. * the real import function
  446. * import the uploaded csv file for real
  447. */
  448. function doExport()
  449. {
  450. $enclosure = $this->m_postvars["enclosure"];
  451. $delimiter = $this->m_postvars["delimiter"];
  452. $source = $this->m_postvars;
  453. $list_includes = array();
  454. foreach ($source as $name => $value) {
  455. $pos = strpos($name, 'export_');
  456. if (is_integer($pos) and $pos == 0)
  457. $list_includes[] = substr($name, strlen('export_'));
  458. }
  459. global $g_sessionData;
  460. $session_back = $g_sessionData["default"]["stack"][atkStackID()][atkLevel() - 1];
  461. $atkorderby = $session_back['atkorderby'];
  462. $entity = &$this->m_entity;
  463. $entity_bk = $entity;
  464. $num_atts = count($entity_bk->m_attribList);
  465. $atts = &$entity_bk->m_attribList;
  466. foreach ($atts as $name => $object) {
  467. $att = &$entity_bk->getAttribute($name);
  468. if (in_array($name, $list_includes) && $att->hasFlag(AF_HIDE_LIST))
  469. $att->removeFlag(AF_HIDE_LIST);
  470. elseif (!in_array($name, $list_includes))
  471. $att->addFlag(AF_HIDE_LIST);
  472. }
  473. if (!is_array($actions)) {
  474. $actions = $entity->defaultActions("export");
  475. }
  476. $rl = &Adapto_ClassLoader::create("atk.recordlist.atkcustomrecordlist");
  477. $flags = ($entity_bk->hasFlag(EF_MRA) ? RL_MRA : 0) | ($entity_bk->hasFlag(EF_MRPA) ? RL_MRPA : 0) | ($entity_bk->hasFlag(EF_LOCK) ? RL_LOCK : 0);
  478. $entity_bk->m_postvars = $session_back;
  479. if (isset($session_back['atkdg']['admin']['atksearch']))
  480. $entity_bk->m_postvars['atksearch'] = $session_back['atkdg']['admin']['atksearch'];
  481. if (isset($session_back['atkdg']['admin']['atksearchmode']))
  482. $entity_bk->m_postvars['atksearchmode'] = $session_back['atkdg']['admin']['atksearchmode'];
  483. $atkfilter = atkArrayNvl($source, 'atkfilter', "");
  484. $recordset = $entity_bk
  485. ->selectDb($session_back['atkselector'] . ($session_back['atkselector'] != '' && $atkfilter != '' ? ' AND ' : '') . $atkfilter, $atkorderby,
  486. "", "", $list_includes, "export");
  487. if (method_exists($this->m_entity, "assignExportData"))
  488. $this->m_entity->assignExportData($list_includes, $recordset);
  489. $recordset_new = array();
  490. foreach ($recordset as $row) {
  491. foreach ($row as $name => $value) {
  492. if (in_array($name, $list_includes)) {
  493. $value = str_replace("\r\n", "\\n", $value);
  494. $value = str_replace("\n", "\\n", $value);
  495. $value = str_replace("\t", "\\t", $value);
  496. $row[$name] = $value;
  497. }
  498. }
  499. $recordset_new[] = $row;
  500. }
  501. $rl
  502. ->render($entity_bk, $recordset_new, "", $enclosure, $enclosure . $delimiter, "\r\n", 1, "", "", array('filename' => 'export_' . $entity->m_type),
  503. "csv", $source['generatetitlerow'], true);
  504. return true;
  505. }
  506. }
  507. ?>