feeds_ui.admin.inc

  1. cis7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  2. cle7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  3. ecd7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  4. elmsmedia7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  5. harmony7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  6. icor7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  7. meedjum_blog7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
  8. mooc7 sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc

Contains all page callbacks, forms and theming functions for Feeds administrative pages.

Functions

Namesort descending Description
feeds_ui_create_form Create a new configuration.
feeds_ui_create_form_submit Submit handler for feeds_build_create_form().
feeds_ui_create_form_validate Validation handler for feeds_build_create_form().
feeds_ui_delete_form Delete configuration form.
feeds_ui_delete_form_submit Submit handler for feeds_ui_delete_form().
feeds_ui_edit_help Introductory help for admin/structure/feeds/%feeds_importer page
feeds_ui_edit_page Edit feed configuration.
feeds_ui_export_form Export a feed configuration.
feeds_ui_importer_machine_name_exists Validation callback for the importer machine name field.
feeds_ui_mapping_form Edit mapping.
feeds_ui_mapping_form_add_submit Submit handler for add button on feeds_ui_mapping_form().
feeds_ui_mapping_form_add_validate Validation for source and target selection.
feeds_ui_mapping_form_multistep_submit Submit callback for a per mapper configuration form. Switches between edit and summary mode.
feeds_ui_mapping_form_submit Submit handler for save button on feeds_ui_mapping_form().
feeds_ui_mapping_help Help text for mapping.
feeds_ui_mapping_settings_form Per mapper configuration form that is a part of feeds_ui_mapping_form().
feeds_ui_mapping_settings_form_callback AJAX callback that returns the whole feeds_ui_mapping_form().
feeds_ui_mapping_settings_optional_unique_form Per mapping settings form callback. Lets the user choose if a target is as unique or not.
feeds_ui_mapping_settings_optional_unique_summary Per mapping settings summary callback. Shows whether a mapping is used as unique or not.
feeds_ui_overview_form Build overview of available configurations.
feeds_ui_overview_form_submit Submit handler for feeds_ui_overview_form().
feeds_ui_plugin_form Build a form of plugins to pick from.
feeds_ui_plugin_form_submit Submit handler for feeds_ui_plugin_form().
theme_feeds_ui_container Render a simple container. A container can have a title, a description and one or more actions. Recursive.
theme_feeds_ui_edit_page Theme feeds_ui_edit_page().
theme_feeds_ui_mapping_form Theme function for feeds_ui_mapping_form().
theme_feeds_ui_overview_form Theme feeds_ui_overview_form().
theme_feeds_ui_plugin_form Theme feeds_ui_plugin_form().
_feeds_ui_format_options Walk the result of FeedsParser::getMappingSources() or FeedsProcessor::getMappingTargets() and format them into a Form API options array.

File

sites/all/modules/ulmus/feeds/feeds_ui/feeds_ui.admin.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Contains all page callbacks, forms and theming functions for Feeds
  5. * administrative pages.
  6. */
  7. /**
  8. * Introductory help for admin/structure/feeds/%feeds_importer page
  9. */
  10. function feeds_ui_edit_help() {
  11. return t('
  12. <p>
  13. You can create as many Feeds importer configurations as you would like to. Each can have a distinct purpose like letting your users aggregate RSS feeds or importing a CSV file for content migration. Here are a couple of things that are important to understand in order to get started with Feeds:
  14. </p>
  15. <ul>
  16. <li>
  17. Every importer configuration consists of basic settings, a fetcher, a parser and a processor and their settings.
  18. </li>
  19. <li>
  20. The <strong>basic settings</strong> define the general behavior of the importer. <strong>Fetchers</strong> are responsible for loading data, <strong>parsers</strong> for organizing it and <strong>processors</strong> for "doing stuff" with it, usually storing it.
  21. </li>
  22. <li>
  23. In Basic settings, you can <strong>attach an importer configuration to a content type</strong>. This is useful when many imports of a kind should be created, for example in an RSS aggregation scenario. If you don\'t attach a configuration to a content type, you can use it on the !import page.
  24. </li>
  25. <li>
  26. Imports can be <strong>scheduled periodically</strong> - see the periodic import select box in the Basic settings.
  27. </li>
  28. <li>
  29. Processors can have <strong>mappings</strong> in addition to settings. Mappings allow you to define what elements of a data feed should be mapped to what content fields on a granular level. For instance, you can specify that a feed item\'s author should be mapped to a node\'s body.
  30. </li>
  31. </ul>
  32. ', array('!import' => l(t('Import'), 'import')));
  33. }
  34. /**
  35. * Help text for mapping.
  36. */
  37. function feeds_ui_mapping_help() {
  38. return t('
  39. <p>
  40. Define which elements of a single item of a feed (= <em>Sources</em>) map to which content pieces in Drupal (= <em>Targets</em>). Make sure that at least one definition has a <em>Unique target</em>. A unique target means that a value for a target can only occur once. E. g. only one item with the URL <em>http://example.com/content/1</em> can exist.
  41. </p>
  42. ');
  43. }
  44. /**
  45. * Build overview of available configurations.
  46. */
  47. function feeds_ui_overview_form($form, &$form_status) {
  48. $form = $form['enabled'] = $form['disabled'] = array();
  49. $form['#header'] = array(
  50. t('Name'),
  51. t('Description'),
  52. t('Attached to'),
  53. t('Status'),
  54. t('Operations'),
  55. t('Enabled'),
  56. );
  57. foreach (feeds_importer_load_all(TRUE) as $importer) {
  58. $importer_form = array();
  59. $importer_form['name']['#markup'] = check_plain($importer->config['name']);
  60. $importer_form['description']['#markup'] = check_plain($importer->config['description']);
  61. if (empty($importer->config['content_type'])) {
  62. $importer_form['attached']['#markup'] = '[none]';
  63. }
  64. else {
  65. if (!$importer->disabled) {
  66. $importer_form['attached']['#markup'] = l(node_type_get_name($importer->config['content_type']), 'node/add/' . str_replace('_', '-', $importer->config['content_type']));
  67. }
  68. else {
  69. $importer_form['attached']['#markup'] = check_plain(node_type_get_name($importer->config['content_type']));
  70. }
  71. }
  72. if ($importer->export_type == EXPORT_IN_CODE) {
  73. $status = t('Default');
  74. $edit = t('Override');
  75. $delete = '';
  76. }
  77. elseif ($importer->export_type == EXPORT_IN_DATABASE) {
  78. $status = t('Normal');
  79. $edit = t('Edit');
  80. $delete = t('Delete');
  81. }
  82. elseif ($importer->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
  83. $status = t('Overridden');
  84. $edit = t('Edit');
  85. $delete = t('Revert');
  86. }
  87. $importer_form['status'] = array(
  88. '#markup' => $status,
  89. );
  90. if (!$importer->disabled) {
  91. $importer_form['operations'] = array(
  92. '#markup' =>
  93. l($edit, 'admin/structure/feeds/' . $importer->id) . ' | ' .
  94. l(t('Export'), 'admin/structure/feeds/' . $importer->id . '/export') . ' | ' .
  95. l(t('Clone'), 'admin/structure/feeds/' . $importer->id . '/clone') .
  96. (empty($delete) ? '' : ' | ' . l($delete, 'admin/structure/feeds/' . $importer->id . '/delete')),
  97. );
  98. }
  99. else {
  100. $importer_form['operations']['#markup'] = '&nbsp;';
  101. }
  102. $importer_form[$importer->id] = array(
  103. '#type' => 'checkbox',
  104. '#default_value' => !$importer->disabled,
  105. '#attributes' => array('class' => array('feeds-ui-trigger-submit')),
  106. );
  107. if ($importer->disabled) {
  108. $form['disabled'][$importer->id] = $importer_form;
  109. }
  110. else {
  111. $form['enabled'][$importer->id] = $importer_form;
  112. }
  113. }
  114. $form['submit'] = array(
  115. '#type' => 'submit',
  116. '#value' => t('Save'),
  117. '#attributes' => array('class' => array('feeds-ui-hidden-submit')),
  118. );
  119. return $form;
  120. }
  121. /**
  122. * Submit handler for feeds_ui_overview_form().
  123. */
  124. function feeds_ui_overview_form_submit($form, &$form_state) {
  125. $disabled = array();
  126. foreach (feeds_importer_load_all(TRUE) as $importer) {
  127. $disabled[$importer->id] = !$form_state['values'][$importer->id];
  128. }
  129. variable_set('default_feeds_importer', $disabled);
  130. feeds_cache_clear();
  131. }
  132. /**
  133. * Create a new configuration.
  134. *
  135. * @param $form_state
  136. * Form API form state array.
  137. * @param $from_importer
  138. * FeedsImporter object. If given, form will create a new importer as a copy
  139. * of $from_importer.
  140. */
  141. function feeds_ui_create_form($form, &$form_state, $from_importer = NULL) {
  142. $form['#attached']['js'][] = drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js';
  143. $form['#from_importer'] = $from_importer;
  144. $form['name'] = array(
  145. '#type' => 'textfield',
  146. '#title' => t('Name'),
  147. '#description' => t('A natural name for this configuration. Example: RSS Feed. You can always change this name later.'),
  148. '#required' => TRUE,
  149. '#maxlength' => 128,
  150. );
  151. $form['id'] = array(
  152. '#type' => 'machine_name',
  153. '#required' => TRUE,
  154. '#maxlength' => 128,
  155. '#machine_name' => array(
  156. 'exists' => 'feeds_ui_importer_machine_name_exists',
  157. ),
  158. );
  159. $form['description'] = array(
  160. '#type' => 'textfield',
  161. '#title' => t('Description'),
  162. '#description' => t('A description of this configuration.'),
  163. );
  164. $form['submit'] = array(
  165. '#type' => 'submit',
  166. '#value' => t('Create'),
  167. );
  168. return $form;
  169. }
  170. /**
  171. * Validation callback for the importer machine name field.
  172. */
  173. function feeds_ui_importer_machine_name_exists($id) {
  174. if ($id == 'create') {
  175. // Create is a reserved path for the add importer form.
  176. return TRUE;
  177. }
  178. ctools_include('export');
  179. if (ctools_export_load_object('feeds_importer', 'conditions', array('id' => $id))) {
  180. return TRUE;
  181. }
  182. }
  183. /**
  184. * Validation handler for feeds_build_create_form().
  185. */
  186. function feeds_ui_create_form_validate($form, &$form_state) {
  187. if (!empty($form_state['values']['id'])) {
  188. $importer = feeds_importer($form_state['values']['id']);
  189. $importer->configFormValidate($form_state['values']);
  190. }
  191. }
  192. /**
  193. * Submit handler for feeds_build_create_form().
  194. */
  195. function feeds_ui_create_form_submit($form, &$form_state) {
  196. // Create feed.
  197. $importer = feeds_importer($form_state['values']['id']);
  198. // If from_importer is given, copy its configuration.
  199. if (!empty($form['#from_importer'])) {
  200. $importer->copy($form['#from_importer']);
  201. }
  202. // In any case, we want to set this configuration's title and description.
  203. $importer->addConfig($form_state['values']);
  204. $importer->save();
  205. // Set a message and redirect to settings form.
  206. if (empty($form['#from_importer'])) {
  207. drupal_set_message(t('Your configuration has been created with default settings. If they do not fit your use case you can adjust them here.'));
  208. }
  209. else {
  210. drupal_set_message(t('A clone of the @name configuration has been created.', array('@name' => $form['#from_importer']->config['name'])));
  211. }
  212. $form_state['redirect'] = 'admin/structure/feeds/' . $importer->id;
  213. feeds_cache_clear();
  214. }
  215. /**
  216. * Delete configuration form.
  217. */
  218. function feeds_ui_delete_form($form, &$form_state, $importer) {
  219. $form['#importer'] = $importer->id;
  220. if ($importer->export_type & EXPORT_IN_CODE) {
  221. $title = t('Would you really like to revert the importer @importer?', array('@importer' => $importer->config['name']));
  222. $button_label = t('Revert');
  223. }
  224. else {
  225. $title = t('Would you really like to delete the importer @importer?', array('@importer' => $importer->config['name']));
  226. $button_label = t('Delete');
  227. }
  228. return confirm_form(
  229. $form,
  230. $title,
  231. 'admin/structure/feeds',
  232. t('This action cannot be undone.'),
  233. $button_label
  234. );
  235. }
  236. /**
  237. * Submit handler for feeds_ui_delete_form().
  238. */
  239. function feeds_ui_delete_form_submit($form, &$form_state) {
  240. $form_state['redirect'] = 'admin/structure/feeds';
  241. // Remove importer.
  242. feeds_importer($form['#importer'])->delete();
  243. // Clear cache, deleting a configuration may have an affect on menu tree.
  244. feeds_cache_clear();
  245. }
  246. /**
  247. * Export a feed configuration.
  248. */
  249. function feeds_ui_export_form($form, &$form_state, $importer) {
  250. $code = feeds_export($importer->id);
  251. $form['export'] = array(
  252. '#title' => t('Export feed configuration'),
  253. '#type' => 'textarea',
  254. '#value' => $code,
  255. '#rows' => substr_count($code, "\n"),
  256. );
  257. return $form;
  258. }
  259. /**
  260. * Edit feed configuration.
  261. */
  262. function feeds_ui_edit_page($importer, $active = 'help', $plugin_key = '') {
  263. // Get plugins and configuration.
  264. $plugins = FeedsPlugin::all();
  265. $config = $importer->config;
  266. // Base path for changing the active container.
  267. $path = 'admin/structure/feeds/' . $importer->id;
  268. $active_container = array(
  269. 'class' => array('active-container'),
  270. 'actions' => array(l(t('Help'), $path)),
  271. );
  272. switch ($active) {
  273. case 'help':
  274. $active_container['title'] = t('Getting started');
  275. $active_container['body'] = '<div class="help feeds-admin-ui">' . feeds_ui_edit_help() . '</div>';
  276. unset($active_container['actions']);
  277. break;
  278. case 'fetcher':
  279. case 'parser':
  280. case 'processor':
  281. $active_container['title'] = t('Select a !plugin_type', array('!plugin_type' => $active));
  282. $active_container['body'] = drupal_get_form('feeds_ui_plugin_form', $importer, $active);
  283. break;
  284. case 'settings':
  285. drupal_add_js(drupal_get_path('module', 'ctools') . '/js/dependent.js');
  286. ctools_include('dependent');
  287. if (empty($plugin_key)) {
  288. $active_container['title'] = t('Basic settings');
  289. $active_container['body'] = feeds_get_form($importer, 'configForm');
  290. }
  291. // feeds_plugin() returns a correct result because feed has been
  292. // instantiated previously.
  293. elseif (in_array($plugin_key, array_keys($plugins)) && $plugin = feeds_plugin($plugin_key, $importer->id)) {
  294. $active_container['title'] = t('Settings for !plugin', array('!plugin' => $plugins[$plugin_key]['name']));
  295. $active_container['body'] = feeds_get_form($plugin, 'configForm');
  296. }
  297. break;
  298. case 'mapping':
  299. $active_container['title'] = t('Mapping for !processor', array('!processor' => $plugins[$config['processor']['plugin_key']]['name']));
  300. $active_container['body'] = drupal_get_form('feeds_ui_mapping_form', $importer);
  301. break;
  302. }
  303. // Build config info.
  304. $config_info = $info = array();
  305. $info['class'] = array('config-set');
  306. // Basic information.
  307. $items = array();
  308. $items[] = t('Attached to: @type', array('@type' => $importer->config['content_type'] ? node_type_get_name($importer->config['content_type']) : t('[none]')));
  309. if ($importer->config['import_period'] == FEEDS_SCHEDULE_NEVER) {
  310. $import_period = t('off');
  311. }
  312. elseif ($importer->config['import_period'] == 0) {
  313. $import_period = t('as often as possible');
  314. }
  315. else {
  316. $import_period = t('every !interval', array('!interval' => format_interval($importer->config['import_period'])));
  317. }
  318. $items[] = t('Periodic import: !import_period', array('!import_period' => $import_period));
  319. $items[] = $importer->config['import_on_create'] ? t('Import on submission') : t('Do not import on submission');
  320. $info['title'] = t('Basic settings');
  321. $info['body'] = array(
  322. array(
  323. 'body' => theme('item_list', array('items' => $items)),
  324. 'actions' => array(l(t('Settings'), $path . '/settings')),
  325. ),
  326. );
  327. $config_info[] = $info;
  328. // Fetcher.
  329. $fetcher = $plugins[$config['fetcher']['plugin_key']];
  330. $actions = array();
  331. if (feeds_get_form($importer->fetcher, 'configForm')) {
  332. $actions = array(l(t('Settings'), $path . '/settings/' . $config['fetcher']['plugin_key']));
  333. }
  334. $info['title'] = t('Fetcher');
  335. $info['body'] = array(
  336. array(
  337. 'title' => $fetcher['name'],
  338. 'body' => $fetcher['description'],
  339. 'actions' => $actions,
  340. ),
  341. );
  342. $info['actions'] = array(l(t('Change'), $path . '/fetcher'));
  343. $config_info[] = $info;
  344. // Parser.
  345. $parser = $plugins[$config['parser']['plugin_key']];
  346. $actions = array();
  347. if (feeds_get_form($importer->parser, 'configForm')) {
  348. $actions = array(l(t('Settings'), $path . '/settings/' . $config['parser']['plugin_key']));
  349. }
  350. $info['title'] = t('Parser');
  351. $info['body'] = array(
  352. array(
  353. 'title' => $parser['name'],
  354. 'body' => $parser['description'],
  355. 'actions' => $actions,
  356. )
  357. );
  358. $info['actions'] = array(l(t('Change'), $path . '/parser'));
  359. $config_info[] = $info;
  360. // Processor.
  361. $processor = $plugins[$config['processor']['plugin_key']];
  362. $actions = array();
  363. if (feeds_get_form($importer->processor, 'configForm')) {
  364. $actions[] = l(t('Settings'), $path . '/settings/' . $config['processor']['plugin_key']);
  365. }
  366. $actions[] = l(t('Mapping'), $path . '/mapping');
  367. $info['title'] = t('Processor');
  368. $info['body'] = array(
  369. array(
  370. 'title' => $processor['name'],
  371. 'body' => $processor['description'],
  372. 'actions' => $actions,
  373. )
  374. );
  375. $info['actions'] = array(l(t('Change'), $path . '/processor'));
  376. $config_info[] = $info;
  377. return theme('feeds_ui_edit_page', array(
  378. 'info' => $config_info,
  379. 'active' => $active_container,
  380. ));
  381. }
  382. /**
  383. * Build a form of plugins to pick from.
  384. *
  385. * @param $form_state
  386. * Form API form state array.
  387. * @param $importer
  388. * FeedsImporter object.
  389. * @param $type
  390. * Plugin type. One of 'fetcher', 'parser', 'processor'.
  391. *
  392. * @return
  393. * A Form API form definition.
  394. */
  395. function feeds_ui_plugin_form($form, &$form_state, $importer, $type) {
  396. $plugins = FeedsPlugin::byType($type);
  397. $form = array();
  398. $form['#importer'] = $importer->id;
  399. $form['#plugin_type'] = $type;
  400. foreach ($plugins as $key => $plugin) {
  401. $form['plugin_key'][$key] = array(
  402. '#type' => 'radio',
  403. '#parents' => array('plugin_key'),
  404. '#title' => check_plain($plugin['name']),
  405. '#description' => filter_xss(isset($plugin['help']) ? $plugin['help'] : $plugin['description']),
  406. '#return_value' => $key,
  407. '#default_value' => ($plugin['handler']['class'] == get_class($importer->$type)) ? $key : '',
  408. );
  409. }
  410. $form['submit'] = array(
  411. '#type' => 'submit',
  412. '#value' => t('Save'),
  413. '#attributes' => array('class' => array('feeds-ui-hidden-submit')),
  414. );
  415. return $form;
  416. }
  417. /**
  418. * Submit handler for feeds_ui_plugin_form().
  419. */
  420. function feeds_ui_plugin_form_submit($form, &$form_state) {
  421. // Set the plugin and save feed.
  422. $importer = feeds_importer($form['#importer']);
  423. $importer->setPlugin($form_state['values']['plugin_key']);
  424. $importer->save();
  425. drupal_set_message(t('Changed @type plugin.', array('@type' => $form['#plugin_type'])));
  426. }
  427. /**
  428. * Theme feeds_ui_plugin_form().
  429. */
  430. function theme_feeds_ui_plugin_form($variables) {
  431. $form = $variables['form'];
  432. drupal_add_js(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js');
  433. $output = '';
  434. foreach (element_children($form['plugin_key']) as $key) {
  435. // Assemble container, render form elements.
  436. $container = array(
  437. 'title' => $form['plugin_key'][$key]['#title'],
  438. 'body' => isset($form['plugin_key'][$key]['#description']) ? $form['plugin_key'][$key]['#description'] : '',
  439. );
  440. $form['plugin_key'][$key]['#title'] = t('Select');
  441. $form['plugin_key'][$key]['#attributes']['class'] = array('feeds-ui-radio-link');
  442. unset($form['plugin_key'][$key]['#description']);
  443. $container['actions'] = array(drupal_render($form['plugin_key'][$key]));
  444. $output .= theme('feeds_ui_container', array('container' => $container));
  445. }
  446. $output .= drupal_render_children($form);
  447. return $output;
  448. }
  449. /**
  450. * Edit mapping.
  451. *
  452. * @todo Completely merge this into config form handling. This is just a
  453. * shared form of configuration, most of the common functionality can live in
  454. * FeedsProcessor, a flag can tell whether mapping is supported or not.
  455. */
  456. function feeds_ui_mapping_form($form, &$form_state, $importer) {
  457. drupal_add_js(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js');
  458. $form = array();
  459. $form['#importer'] = $importer->id;
  460. $form['#mappings'] = $mappings = $importer->processor->getMappings();
  461. $form['help']['#markup'] = feeds_ui_mapping_help();
  462. $form['#prefix'] = '<div id="feeds-ui-mapping-form-wrapper">';
  463. $form['#suffix'] = '</div>';
  464. // Get mapping sources from parsers and targets from processor, format them
  465. // for output.
  466. // Some parsers do not define mapping sources but let them define on the fly.
  467. if ($sources = $importer->parser->getMappingSources()) {
  468. $source_options = _feeds_ui_format_options($sources);
  469. foreach ($sources as $k => $source) {
  470. $legend['sources'][$k]['name']['#markup'] = empty($source['name']) ? $k : $source['name'];
  471. $legend['sources'][$k]['description']['#markup'] = empty($source['description']) ? '' : $source['description'];
  472. }
  473. }
  474. else {
  475. $legend['sources']['#markup'] = t('This parser supports free source definitions. Enter the name of the source field in lower case into the Source text field above.');
  476. }
  477. $targets = $importer->processor->getMappingTargets();
  478. $target_options = _feeds_ui_format_options($targets);
  479. $legend['targets'] = array();
  480. foreach ($targets as $k => $target) {
  481. $legend['targets'][$k]['name']['#markup'] = empty($target['name']) ? $k : $target['name'];
  482. $legend['targets'][$k]['description']['#markup'] = empty($target['description']) ? '' : $target['description'];
  483. }
  484. // Legend explaining source and target elements.
  485. $form['legendset'] = array(
  486. '#type' => 'fieldset',
  487. '#title' => t('Legend'),
  488. '#collapsible' => TRUE,
  489. '#collapsed' => TRUE,
  490. '#tree' => TRUE,
  491. );
  492. $form['legendset']['legend'] = $legend;
  493. // Add config forms and remove flags to mappings.
  494. $form['config'] = $form['remove_flags'] = $form['mapping_weight'] = array(
  495. '#tree' => TRUE,
  496. );
  497. if (is_array($mappings)) {
  498. $delta = count($mappings) + 2;
  499. foreach ($mappings as $i => $mapping) {
  500. if (isset($targets[$mapping['target']])) {
  501. $form['config'][$i] = feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $targets[$mapping['target']]);
  502. }
  503. $form['remove_flags'][$i] = array(
  504. '#type' => 'checkbox',
  505. '#title' => t('Remove'),
  506. '#prefix' => '<div class="feeds-ui-checkbox-link">',
  507. '#suffix' => '</div>',
  508. );
  509. $form['mapping_weight'][$i] = array(
  510. '#type' => 'weight',
  511. '#title' => '',
  512. '#default_value' => $i,
  513. '#delta' => $delta,
  514. '#attributes' => array(
  515. 'class' => array(
  516. 'feeds-ui-mapping-weight'
  517. ),
  518. ),
  519. );
  520. }
  521. }
  522. if (isset($source_options)) {
  523. $form['source'] = array(
  524. '#type' => 'select',
  525. '#options' => array('' => t('Select a source')) + $source_options,
  526. );
  527. }
  528. else {
  529. $form['source'] = array(
  530. '#type' => 'textfield',
  531. '#size' => 20,
  532. '#default_value' => t('Name of source field'),
  533. '#attributes' => array('class' => array('hide-text-on-focus')),
  534. );
  535. }
  536. $form['target'] = array(
  537. '#type' => 'select',
  538. '#options' => array('' => t('Select a target')) + $target_options,
  539. );
  540. $form['add'] = array(
  541. '#type' => 'submit',
  542. '#value' => t('Add'),
  543. '#submit' => array('feeds_ui_mapping_form_add_submit'),
  544. '#validate' => array('feeds_ui_mapping_form_add_validate'),
  545. );
  546. $form['save'] = array(
  547. '#type' => 'submit',
  548. '#value' => t('Save'),
  549. '#attributes' => array('class' => array('feeds-ui-hidden-submit')),
  550. );
  551. return $form;
  552. }
  553. /**
  554. * Per mapper configuration form that is a part of feeds_ui_mapping_form().
  555. */
  556. function feeds_ui_mapping_settings_form($form, $form_state, $i, $mapping, $target) {
  557. $form_state += array(
  558. 'mapping_settings_edit' => NULL,
  559. 'mapping_settings' => array(),
  560. );
  561. $base_button = array(
  562. '#submit' => array('feeds_ui_mapping_form_multistep_submit'),
  563. '#ajax' => array(
  564. 'callback' => 'feeds_ui_mapping_settings_form_callback',
  565. 'wrapper' => 'feeds-ui-mapping-form-wrapper',
  566. 'effect' => 'fade',
  567. 'progress' => 'none',
  568. ),
  569. '#i' => $i,
  570. );
  571. if (isset($form_state['mapping_settings'][$i])) {
  572. $mapping = $form_state['mapping_settings'][$i] + $mapping;
  573. }
  574. if ($form_state['mapping_settings_edit'] === $i) {
  575. // Build the form.
  576. if (isset($target['form_callback'])) {
  577. $settings_form = call_user_func($target['form_callback'], $mapping, $target, $form, $form_state);
  578. }
  579. else {
  580. $settings_form = array();
  581. }
  582. // Merge in the optional unique form.
  583. $settings_form += feeds_ui_mapping_settings_optional_unique_form($mapping, $target, $form, $form_state);
  584. return array(
  585. '#type' => 'container',
  586. 'settings' => $settings_form,
  587. 'save_settings' => $base_button + array(
  588. '#type' => 'submit',
  589. '#name' => 'mapping_settings_update_' . $i,
  590. '#value' => t('Update'),
  591. '#op' => 'update',
  592. ),
  593. 'cancel_settings' => $base_button + array(
  594. '#type' => 'submit',
  595. '#name' => 'mapping_settings_cancel_' . $i,
  596. '#value' => t('Cancel'),
  597. '#op' => 'cancel',
  598. ),
  599. );
  600. }
  601. else {
  602. // Build the summary.
  603. if (isset($target['summary_callback'])) {
  604. $summary = call_user_func($target['summary_callback'], $mapping, $target, $form, $form_state);
  605. }
  606. else {
  607. $summary = '';
  608. }
  609. // Append the optional unique summary.
  610. if ($optional_unique_summary = feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state)) {
  611. $summary .= ' ' . $optional_unique_summary;
  612. }
  613. if ($summary) {
  614. return array(
  615. 'summary' => array(
  616. '#prefix' => '<div>',
  617. '#markup' => $summary,
  618. '#suffix' => '</div>',
  619. ),
  620. 'edit_settings' => $base_button + array(
  621. '#type' => 'image_button',
  622. '#name' => 'mapping_settings_edit_' . $i,
  623. '#src' => 'misc/configure.png',
  624. '#attributes' => array('alt' => t('Edit')),
  625. '#op' => 'edit',
  626. ),
  627. );
  628. }
  629. }
  630. }
  631. /**
  632. * Submit callback for a per mapper configuration form. Switches between edit
  633. * and summary mode.
  634. */
  635. function feeds_ui_mapping_form_multistep_submit($form, &$form_state) {
  636. $trigger = $form_state['triggering_element'];
  637. switch ($trigger['#op']) {
  638. case 'edit':
  639. $form_state['mapping_settings_edit'] = $trigger['#i'];
  640. break;
  641. case 'update':
  642. $values = $form_state['values']['config'][$trigger['#i']]['settings'];
  643. $form_state['mapping_settings'][$trigger['#i']] = $values;
  644. unset($form_state['mapping_settings_edit']);
  645. break;
  646. case 'cancel':
  647. unset($form_state['mapping_settings_edit']);
  648. break;
  649. }
  650. $form_state['rebuild'] = TRUE;
  651. }
  652. /**
  653. * AJAX callback that returns the whole feeds_ui_mapping_form().
  654. */
  655. function feeds_ui_mapping_settings_form_callback($form, $form_state) {
  656. return $form;
  657. }
  658. /**
  659. * Validation for source and target selection.
  660. */
  661. function feeds_ui_mapping_form_add_validate($form, &$form_state) {
  662. if ($form_state['values']['source'] == '') {
  663. form_set_error('source', t('You must select a mapping source.'));
  664. }
  665. if ($form_state['values']['target'] == '') {
  666. form_set_error('target', t('You must select a mapping target.'));
  667. }
  668. }
  669. /**
  670. * Submit handler for add button on feeds_ui_mapping_form().
  671. */
  672. function feeds_ui_mapping_form_add_submit($form, &$form_state) {
  673. $importer = feeds_importer($form['#importer']);
  674. try {
  675. $mappings = $form['#mappings'];
  676. $mappings[] = array(
  677. 'source' => $form_state['values']['source'],
  678. 'target' => $form_state['values']['target'],
  679. 'unique' => FALSE,
  680. );
  681. $importer->processor->addConfig(array('mappings' => $mappings));
  682. $importer->save();
  683. drupal_set_message(t('Mapping has been added.'));
  684. }
  685. catch (Exception $e) {
  686. drupal_set_message($e->getMessage(), 'error');
  687. }
  688. }
  689. /**
  690. * Submit handler for save button on feeds_ui_mapping_form().
  691. */
  692. function feeds_ui_mapping_form_submit($form, &$form_state) {
  693. $importer = feeds_importer($form['#importer']);
  694. $processor = $importer->processor;
  695. $form_state += array(
  696. 'mapping_settings' => array(),
  697. 'mapping_settings_edit' => NULL,
  698. );
  699. // If an item is in edit mode, prepare it for saving.
  700. if ($form_state['mapping_settings_edit'] !== NULL) {
  701. $values = $form_state['values']['config'][$form_state['mapping_settings_edit']]['settings'];
  702. $form_state['mapping_settings'][$form_state['mapping_settings_edit']] = $values;
  703. }
  704. // We may set some settings to mappings that we remove in the subsequent step,
  705. // that's fine.
  706. $mappings = $form['#mappings'];
  707. foreach ($form_state['mapping_settings'] as $k => $v) {
  708. $mappings[$k] = array(
  709. 'source' => $mappings[$k]['source'],
  710. 'target' => $mappings[$k]['target'],
  711. ) + $v;
  712. }
  713. if (!empty($form_state['values']['remove_flags'])) {
  714. $remove_flags = array_keys(array_filter($form_state['values']['remove_flags']));
  715. foreach ($remove_flags as $k) {
  716. unset($mappings[$k]);
  717. unset($form_state['values']['mapping_weight'][$k]);
  718. }
  719. }
  720. // Keep our keys clean.
  721. $mappings = array_values($mappings);
  722. if (!empty($mappings)) {
  723. array_multisort($form_state['values']['mapping_weight'], $mappings);
  724. }
  725. $processor->addConfig(array('mappings' => $mappings));
  726. $importer->save();
  727. drupal_set_message(t('Your changes have been saved.'));
  728. }
  729. /**
  730. * Walk the result of FeedsParser::getMappingSources() or
  731. * FeedsProcessor::getMappingTargets() and format them into
  732. * a Form API options array.
  733. */
  734. function _feeds_ui_format_options($options) {
  735. $result = array();
  736. foreach ($options as $k => $v) {
  737. if (is_array($v) && !empty($v['name'])) {
  738. $result[$k] = $v['name'];
  739. }
  740. elseif (is_array($v)) {
  741. $result[$k] = $k;
  742. }
  743. else {
  744. $result[$k] = $v;
  745. }
  746. }
  747. asort($result);
  748. return $result;
  749. }
  750. /**
  751. * Per mapping settings summary callback. Shows whether a mapping is used as
  752. * unique or not.
  753. */
  754. function feeds_ui_mapping_settings_optional_unique_summary($mapping, $target, $form, $form_state) {
  755. if (!empty($target['optional_unique'])) {
  756. if ($mapping['unique']) {
  757. return t('Used as <strong>unique</strong>.');
  758. }
  759. else {
  760. return t('Not used as unique.');
  761. }
  762. }
  763. }
  764. /**
  765. * Per mapping settings form callback. Lets the user choose if a target is as
  766. * unique or not.
  767. */
  768. function feeds_ui_mapping_settings_optional_unique_form($mapping, $target, $form, $form_state) {
  769. $settings_form = array();
  770. if (!empty($target['optional_unique'])) {
  771. $settings_form['unique'] = array(
  772. '#type' => 'checkbox',
  773. '#title' => t('Unique'),
  774. '#default_value' => !empty($mapping['unique']),
  775. );
  776. }
  777. return $settings_form;
  778. }
  779. /**
  780. * Theme feeds_ui_overview_form().
  781. */
  782. function theme_feeds_ui_overview_form($variables) {
  783. $form = $variables['form'];
  784. drupal_add_js(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.js');
  785. drupal_add_css(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.css');
  786. // Iterate through all importers and build a table.
  787. $rows = array();
  788. foreach (array('enabled', 'disabled') as $type) {
  789. if (isset($form[$type])) {
  790. foreach (element_children($form[$type]) as $id) {
  791. $row = array();
  792. foreach (element_children($form[$type][$id]) as $col) {
  793. $row[$col] = array(
  794. 'data' => drupal_render($form[$type][$id][$col]),
  795. 'class' => array($type),
  796. );
  797. }
  798. $rows[] = array(
  799. 'data' => $row,
  800. 'class' => array($type),
  801. );
  802. }
  803. }
  804. }
  805. $output = theme('table', array(
  806. 'header' => $form['#header'],
  807. 'rows' => $rows,
  808. 'attributes' => array('class' => array('feeds-admin-importers')),
  809. 'empty' => t('No importers available.'),
  810. ));
  811. if (!empty($rows)) {
  812. $output .= drupal_render_children($form);
  813. }
  814. return $output;
  815. }
  816. /**
  817. * Theme feeds_ui_edit_page().
  818. */
  819. function theme_feeds_ui_edit_page($variables) {
  820. $config_info = $variables['info'];
  821. $active_container = $variables['active'];
  822. drupal_add_css(drupal_get_path('module', 'feeds_ui') . '/feeds_ui.css');
  823. // Outer wrapper.
  824. $output = '<div class="feeds-settings clear-block">';
  825. // Build left bar.
  826. $output .= '<div class="left-bar">';
  827. foreach ($config_info as $info) {
  828. $output .= theme('feeds_ui_container', array('container' => $info));
  829. }
  830. $output .= '</div>';
  831. // Build configuration space.
  832. $output .= '<div class="configuration">';
  833. $output .= '<div class="configuration-squeeze">';
  834. $output .= theme('feeds_ui_container', array('container' => $active_container));
  835. $output .= '</div>';
  836. $output .= '</div>';
  837. $output .= '</div>'; // ''<div class="feeds-settings">';
  838. return $output;
  839. }
  840. /**
  841. * Render a simple container. A container can have a title, a description and
  842. * one or more actions. Recursive.
  843. *
  844. * @todo Replace with theme_fieldset or a wrapper to theme_fieldset?
  845. *
  846. * @param $variables
  847. * An array containing an array at 'container'.
  848. * A 'container' array may contain one or more of the following keys:
  849. * array(
  850. * 'title' => 'the title',
  851. * 'body' => 'the body of the container, may also be an array of more
  852. * containers or a renderable array.',
  853. * 'class' => array('the class of the container.'),
  854. * 'id' => 'the id of the container',
  855. * );
  856. */
  857. function theme_feeds_ui_container($variables) {
  858. $container = $variables['container'];
  859. $class = array_merge(array('feeds-container'), empty($container['class']) ? array('plain') : $container['class']);
  860. $id = empty($container['id']) ? '': ' id="' . $container['id'] . '"';
  861. $output = '<div class="' . implode(' ', $class) . '"' . $id . '>';
  862. if (isset($container['actions']) && count($container['actions'])) {
  863. $output .= '<ul class="container-actions">';
  864. foreach ($container['actions'] as $action) {
  865. $output .= '<li>' . $action . '</li>';
  866. }
  867. $output .= '</ul>';
  868. }
  869. if (!empty($container['title'])) {
  870. $output .= '<h4 class="feeds-container-title">';
  871. $output .= $container['title'];
  872. $output .= '</h4>';
  873. }
  874. if (!empty($container['body'])) {
  875. $output .= '<div class="feeds-container-body">';
  876. if (is_array($container['body'])) {
  877. if (isset($container['body']['#type'])) {
  878. $output .= drupal_render($container['body']);
  879. }
  880. else {
  881. foreach ($container['body'] as $c) {
  882. $output .= theme('feeds_ui_container', array('container' => $c));
  883. }
  884. }
  885. }
  886. else {
  887. $output .= $container['body'];
  888. }
  889. $output .= '</div>';
  890. }
  891. $output .= '</div>';
  892. return $output;
  893. }
  894. /**
  895. * Theme function for feeds_ui_mapping_form().
  896. */
  897. function theme_feeds_ui_mapping_form($variables) {
  898. $form = $variables['form'];
  899. // Build the actual mapping table.
  900. $header = array(
  901. t('Source'),
  902. t('Target'),
  903. t('Target configuration'),
  904. '&nbsp;',
  905. t('Weight'),
  906. );
  907. $rows = array();
  908. if (is_array($form['#mappings'])) {
  909. foreach ($form['#mappings'] as $i => $mapping) {
  910. // Some parsers do not define source options.
  911. $source = isset($form['source']['#options'][$mapping['source']]) ? $form['source']['#options'][$mapping['source']] : $mapping['source'];
  912. $target = isset($form['target']['#options'][$mapping['target']]) ? check_plain($form['target']['#options'][$mapping['target']]) : '<em>' . t('Missing') . '</em>';
  913. $rows[] = array(
  914. 'data' => array(
  915. check_plain($source),
  916. $target,
  917. drupal_render($form['config'][$i]),
  918. drupal_render($form['remove_flags'][$i]),
  919. drupal_render($form['mapping_weight'][$i]),
  920. ),
  921. 'class' => array('draggable', 'tabledrag-leaf'),
  922. );
  923. }
  924. }
  925. if (!count($rows)) {
  926. $rows[] = array(
  927. array(
  928. 'colspan' => 5,
  929. 'data' => t('No mappings defined.'),
  930. ),
  931. );
  932. }
  933. $rows[] = array(
  934. drupal_render($form['source']),
  935. drupal_render($form['target']),
  936. '',
  937. drupal_render($form['add']),
  938. '',
  939. );
  940. $output = '<div class="help feeds-admin-ui">' . drupal_render($form['help']) . '</div>';
  941. $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'feeds-ui-mapping-overview')));
  942. // Build the help table that explains available sources.
  943. $legend = '';
  944. $rows = array();
  945. foreach (element_children($form['legendset']['legend']['sources']) as $k) {
  946. $rows[] = array(
  947. check_plain(drupal_render($form['legendset']['legend']['sources'][$k]['name'])),
  948. check_plain(drupal_render($form['legendset']['legend']['sources'][$k]['description'])),
  949. );
  950. }
  951. if (count($rows)) {
  952. $legend .= '<h4>' . t('Sources') . '</h4>';
  953. $legend .= theme('table', array('header' => array(t('Name'), t('Description')), 'rows' => $rows));
  954. }
  955. // Build the help table that explains available targets.
  956. $rows = array();
  957. foreach (element_children($form['legendset']['legend']['targets']) as $k) {
  958. $rows[] = array(
  959. check_plain(drupal_render($form['legendset']['legend']['targets'][$k]['name'])),
  960. check_plain(drupal_render($form['legendset']['legend']['targets'][$k]['description'])),
  961. );
  962. }
  963. $legend .= '<h4>' . t('Targets') . '</h4>';
  964. $legend .= theme('table', array('header' => array(t('Name'), t('Description')), 'rows' => $rows));
  965. // Stick tables into collapsible fieldset.
  966. $form['legendset']['legend'] = array(
  967. '#markup' => '<div>' . $legend . '</div>',
  968. );
  969. $output .= drupal_render($form['legendset']);
  970. $output .= drupal_render_children($form);
  971. drupal_add_tabledrag('feeds-ui-mapping-overview', 'order', 'sibling', 'feeds-ui-mapping-weight');
  972. return $output;
  973. }
Error | ELMSLN API

Error

×

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/elmsln_community/api.elmsln.org/includes/common.inc:2791) in drupal_send_headers() (line 1499 of /var/www/html/elmsln_community/api.elmsln.org/includes/bootstrap.inc).
  • Error: Call to undefined function apc_delete() in DrupalAPCCache->clear() (line 289 of /var/www/html/elmsln_community/api.elmsln.org/sites/all/modules/apc/drupal_apc_cache.inc).
The website encountered an unexpected error. Please try again later.