From 33210e10f28b8886fff920078a570440da16837d Mon Sep 17 00:00:00 2001 From: Bachir Soussi Chiadmi Date: Mon, 13 May 2019 17:41:56 +0200 Subject: [PATCH] updated admin_menu, entity_translation, addressfield, addressfield_token, autocomplete_deluxe --- .../contrib/admin/admin_menu/README.txt | 214 +++-- .../admin_menu/admin_devel/admin_devel.info | 7 +- .../admin/admin_menu/admin_menu-rtl.css | 9 +- .../admin/admin_menu/admin_menu.admin.js | 12 +- .../admin/admin_menu/admin_menu.color.css | 3 +- .../contrib/admin/admin_menu/admin_menu.css | 14 +- .../contrib/admin/admin_menu/admin_menu.inc | 58 +- .../contrib/admin/admin_menu/admin_menu.info | 7 +- .../contrib/admin/admin_menu/admin_menu.js | 12 +- .../admin/admin_menu/admin_menu.map.inc | 9 +- .../admin/admin_menu/admin_menu.module | 39 +- .../admin/admin_menu/admin_menu.uid1.css | 1 - .../admin_menu_toolbar-rtl.css | 4 + .../admin_menu_toolbar/admin_menu_toolbar.css | 7 +- .../admin_menu_toolbar.info | 7 +- .../admin_menu_toolbar.install | 1 - .../admin_menu_toolbar.module | 1 - .../admin/admin_menu/tests/admin_menu.test | 67 +- ...entity_translation_export_import.admin.inc | 31 +- .../entity_translation_export_import.info | 6 +- .../addressfield_tokens.components.inc | 264 ++++-- .../addressfield_tokens.info | 23 +- .../addressfield_tokens.module | 197 +++-- .../addressfield_tokens.theme.inc | 24 +- .../addressfield_tokens.tokens.inc | 126 ++- .../addressfield.address_formats.inc | 39 +- .../addressfield.administrative_areas.inc | 228 +++-- .../addressfield.devel_generate.inc | 4 +- .../addressfield/addressfield.feeds.inc | 22 +- .../fields/addressfield/addressfield.info | 7 +- .../addressfield/addressfield.migrate.inc | 5 + .../fields/addressfield/addressfield.module | 42 +- .../addressfield/addressfield.tokens.inc | 42 +- .../example/addressfield_example.info | 7 +- .../address-hide-administrative-area.inc | 24 + .../plugins/format/address-hide-country.inc | 2 +- .../plugins/format/address-hide-locality.inc | 24 + .../addressfield/plugins/format/address.inc | 7 +- .../fields/autocomplete_deluxe/README.txt | 0 .../autocomplete_deluxe.api.php | 33 +- .../autocomplete_deluxe.css | 0 .../autocomplete_deluxe.info | 6 +- .../autocomplete_deluxe.js | 0 .../autocomplete_deluxe.module | 0 .../entity_translation/CHANGELOG.txt | 80 +- .../entity_translation/MAINTAINERS.txt | 16 +- .../entity_translation.admin.inc | 54 +- .../entity_translation.api.php | 14 + .../entity_translation.info | 10 +- .../entity_translation.install | 18 +- .../entity_translation.module | 124 ++- .../entity_translation.taxonomy.inc | 472 ++++++++++ .../entity_translation_i18n_menu.info | 7 +- .../entity_translation_i18n_menu.module | 2 +- .../entity_translation_i18n_menu.test | 31 +- .../entity_translation_upgrade.admin.inc | 10 +- .../entity_translation_upgrade.drush.inc | 117 +++ .../entity_translation_upgrade.info | 8 +- .../entity_translation_upgrade.test | 163 ++++ .../includes/translation.handler.inc | 188 ++-- .../includes/translation.handler_factory.inc | 5 +- .../tests/entity_translation.test | 823 +++++++++++++++++- .../tests/entity_translation_test.info | 8 +- .../tests/entity_translation_test.install | 31 + ...ntity_translation_handler_relationship.inc | 8 +- 65 files changed, 3124 insertions(+), 700 deletions(-) create mode 100644 sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar-rtl.css create mode 100644 sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-administrative-area.inc create mode 100644 sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-locality.inc mode change 100644 => 100755 sites/all/modules/contrib/fields/autocomplete_deluxe/README.txt mode change 100644 => 100755 sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.api.php mode change 100644 => 100755 sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.css mode change 100644 => 100755 sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js mode change 100644 => 100755 sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.module create mode 100644 sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.drush.inc create mode 100644 sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.test diff --git a/sites/all/modules/contrib/admin/admin_menu/README.txt b/sites/all/modules/contrib/admin/admin_menu/README.txt index 136db709..6fe556d2 100644 --- a/sites/all/modules/contrib/admin/admin_menu/README.txt +++ b/sites/all/modules/contrib/admin/admin_menu/README.txt @@ -1,65 +1,84 @@ +CONTENTS OF THIS FILE +--------------------- --- SUMMARY -- + * Introduction + * Requirements + * Installation + * Configuration + * Customization + * Troubleshooting + * FAQ + * Maintainers + + +INTRODUCTION +------------ The Administration menu module displays the entire administrative menu tree (and most local tasks) in a drop-down menu, providing administrators one- or two-click access to most pages. Other modules may also add menu links to the menu using hook_admin_menu_output_alter(). -For a full description of the module, visit the project page: - http://drupal.org/project/admin_menu +For a full description of the project visit the project page: +http://drupal.org/project/admin_menu To submit bug reports and feature suggestions, or to track changes: - http://drupal.org/project/issues/admin_menu +http://drupal.org/project/issues/admin_menu --- REQUIREMENTS -- +REQUIREMENTS +------------ -None. +No special requirements --- INSTALLATION -- +INSTALLATION +------------ -* Install as usual, see http://drupal.org/node/895232 for further information. +Install as you would normally install a contributed Drupal. See: +https://drupal.org/documentation/install/modules-themes/modules-7 for further +information. -* You likely want to disable Toolbar module, since its output clashes with - Administration menu. + * You likely want to disable Toolbar module, since its output clashes with + Administration menu. --- CONFIGURATION -- +CONFIGURATION +------------- -* Configure user permissions in Administration » People » Permissions: + * Configure user permissions in Administration » People » Permissions: - - Use the administration pages and help (System module) + - Use the administration pages and help (System module) - The top-level administration categories require this permission to be - accessible. The administration menu will be empty unless this permission is - granted. + The top-level administration categories require this permission to be + accessible. The administration menu will be empty unless this permission is + granted. - - Access administration menu + - Access administration menu - Users in roles with the "Access administration menu" permission will see - the administration menu at the top of each page. + Users in roles with the "Access administration menu" permission will see + the administration menu at the top of each page. - - Display Drupal links + - Display Drupal links - Users in roles with the "Display drupal links" permission will receive - links to drupal.org issue queues for all enabled contributed modules. The - issue queue links appear under the administration menu icon. + Users in roles with the "Display drupal links" permission will receive + links to drupal.org issue queues for all enabled contributed modules. The + issue queue links appear under the administration menu icon. - Note that the menu items displayed in the administration menu depend on the - actual permissions of the viewing user. For example, the "People" menu item - is not displayed to a user who is not a member of a role with the "Administer - users" permission. + Note that the menu items displayed in the administration menu depend on the + actual permissions of the viewing user. For example, the "People" menu item + is not displayed to a user who is not a member of a role with the + "Administer users" permission. -* Customize the menu settings in Administration » Configuration and modules » - Administration » Administration menu. + * Customize the menu settings in Administration » Configuration and modules » + Administration » Administration menu. -* To prevent administrative menu items from appearing twice, you may hide the - "Management" menu block. + * To prevent administrative menu items from appearing twice, you may hide the + "Management" menu block. --- CUSTOMIZATION -- +CUSTOMIZATION +------------- * To override the default administration menu icon, you may: @@ -82,12 +101,13 @@ None. body #admin-menu { font-size: 10px; } --- TROUBLESHOOTING -- +TROUBLESHOOTING +------------- * If the menu does not display, check the following: - - Are the "Access administration menu" and "Use the administration pages and help" - permissions enabled for the appropriate roles? + - Are the "Access administration menu" and "Use the administration pages and + help" permissions enabled for the appropriate roles? - Does html.tpl.php of your theme output the $page_bottom variable? @@ -99,90 +119,102 @@ None. See http://drupal.org/node/195386 for further information. --- FAQ -- +FAQ +--- -Q: When the administration menu module is enabled, blank space is added to the - bottom of my theme. Why? + Q: When the administration menu module is enabled, blank space is added to the + bottom of my theme. Why? -A: This is caused by a long list of links to module issue queues at Drupal.org. - Use Administer >> User management >> Permissions to disable the "display - drupal links" permission for all appropriate roles. Note that since UID 1 - automatically receives all permissions, the list of issue queue links cannot - be disabled for UID 1. + A: This is caused by a long list of links to module issue queues at Drupal.org. + Use Administer >> User management >> Permissions to disable the "display + drupal links" permission for all appropriate roles. Note that since UID 1 + automatically receives all permissions, the list of issue queue links cannot + be disabled for UID 1. -Q: After upgrading to 6.x-1.x, the menu disappeared. Why? + Q: After upgrading to 6.x-1.x, the menu disappeared. Why? -A: You may need to regenerate your menu. Visit - http://example.com/admin/build/modules to regenerate your menu (substitute - your site name for example.com). + A: You may need to regenerate your menu. Visit + http://example.com/admin/build/modules to regenerate your menu (substitute + your site name for example.com). -Q: Can I configure the administration menu module to display another menu (like - the Navigation menu, for instance)? + Q: Can I configure the administration menu module to display another menu (like + the Navigation menu, for instance)? -A: No. As the name implies, administration menu module is for administrative - menu links only. However, you can copy and paste the contents of - admin_menu.css into your theme's stylesheet and replace #admin-menu with any - other menu block id (#block-menu-1, for example). + A: No. As the name implies, administration menu module is for administrative + menu links only. However, you can copy and paste the contents of + admin_menu.css into your theme's stylesheet and replace #admin-menu with any + other menu block id (#block-menu-1, for example). -Q: Sometimes, the user counter displays a lot of anonymous users, but no spike - of users or requests appear in Google Analytics or other tracking tools. + Q: Sometimes, the user counter displays a lot of anonymous users, but no spike + of users or requests appear in Google Analytics or other tracking tools. -A: If your site was concurrently spidered by search-engine robots, it may have - a significant number of anonymous users for a short time. Most web tracking - tools like Google Analytics automatically filter out these requests. + A: If your site was concurrently spidered by search-engine robots, it may have + a significant number of anonymous users for a short time. Most web tracking + tools like Google Analytics automatically filter out these requests. -Q: I enabled "Aggregate and compress CSS files", but admin_menu.css is still - there. Is this normal? + Q: I enabled "Aggregate and compress CSS files", but admin_menu.css is still + there. Is this normal? -A: Yes, this is the intended behavior. the administration menu module only loads - its stylesheet as needed (i.e., on page requests by logged-on, administrative - users). + A: Yes, this is the intended behavior. the administration menu module only + loads its stylesheet as needed (i.e., on page requests by logged-on, + administrative users). -Q: Why are sub-menus not visible in Opera? + Q: Why are sub-menus not visible in Opera? -A: In the Opera browser preferences under "web pages" there is an option to fit - to width. By disabling this option, sub-menus in the administration menu - should appear. + A: In the Opera browser preferences under "web pages" there is an option to fit + to width. By disabling this option, sub-menus in the administration menu + should appear. -Q: How can the administration menu be hidden on certain pages? + Q: How can the administration menu be hidden on certain pages? -A: You can suppress it by simply calling the following function in PHP: + A: You can suppress it by simply calling the following function in PHP: + module_invoke('admin_menu', 'suppress'); - module_invoke('admin_menu', 'suppress'); - - However, this needs to happen as early as possible in the page request, so - placing it in the theming layer (resp. a page template file) is too late. - Ideally, the function is called in hook_init() in a custom module. If you do - not have a custom module, placing it into some conditional code at the top of - template.php may work out, too. + However, this needs to happen as early as possible in the page request, so + placing it in the theming layer (resp. a page template file) is too late. + Ideally, the function is called in hook_init() in a custom module. If you + do not have a custom module, placing it into some conditional code at the + top of template.php may work out, too. --- CONTACT -- +Q: What does the "Administration Development Tools" module do? + +A: The Administration Development Tools adds a jQuery Debugger which allows + a developer to debug and inspect arbitrary data/variables in Firebug's + console, and also to access them again in the global window object + (optionally using a named identifier, e.g. window.debug.myValue). + Chainable via jQuery. Especially useful for re-accessing and debugging + selected data via Firebug's console. + + +MAINTAINERS +----------- Current maintainers: -* Daniel F. Kudwien (sun) - http://drupal.org/user/54136 -* Peter Wolanin (pwolanin) - http://drupal.org/user/49851 -* Stefan M. Kudwien (smk-ka) - http://drupal.org/user/48898 -* Dave Reid (Dave Reid) - http://drupal.org/user/53892 + * Daniel F. Kudwien (sun) - http://drupal.org/user/54136 + * Peter Wolanin (pwolanin) - http://drupal.org/user/49851 + * Stefan M. Kudwien (smk-ka) - http://drupal.org/user/48898 + * Dave Reid (Dave Reid) - http://drupal.org/user/53892 + * Truls S. Yggeseth (truls1502) - http://drupal.org/user/325866 + * Sebastian Siemssen (fubhy) - https://www.drupal.org/user/761344 Major rewrite for Drupal 6 by Peter Wolanin (pwolanin). This project has been sponsored by: -* UNLEASHED MIND - Specialized in consulting and planning of Drupal powered sites, UNLEASHED - MIND offers installation, development, theming, customization, and hosting - to get you started. Visit http://www.unleashedmind.com for more information. + * UNLEASHED MIND + Specialized in consulting and planning of Drupal powered sites, UNLEASHED + MIND offers installation, development, theming, customization, and hosting + to get you started. Visit http://www.unleashedmind.com for more information. -* Lullabot - Friendly Drupal experts providing professional consulting & education - services. Visit http://www.lullabot.com for more information. - -* Acquia - Commercially Supported Drupal. Visit http://acquia.com for more information. + * Lullabot + Friendly Drupal experts providing professional consulting & education + services. Visit http://www.lullabot.com for more information. + * Acquia + Commercially Supported Drupal. Visit http://acquia.com for more information. diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_devel/admin_devel.info b/sites/all/modules/contrib/admin/admin_menu/admin_devel/admin_devel.info index ab3d641f..8b09eb18 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_devel/admin_devel.info +++ b/sites/all/modules/contrib/admin/admin_menu/admin_devel/admin_devel.info @@ -4,9 +4,8 @@ package = Administration core = 7.x scripts[] = admin_devel.js -; Information added by Drupal.org packaging script on 2014-12-19 -version = "7.x-3.0-rc5" +; Information added by Drupal.org packaging script on 2018-12-03 +version = "7.x-3.0-rc6" core = "7.x" project = "admin_menu" -datestamp = "1419029284" - +datestamp = "1543859284" diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu-rtl.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu-rtl.css index 9414dcf9..ff9f5008 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu-rtl.css +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu-rtl.css @@ -1,4 +1,3 @@ - #admin-menu { text-align: right; } @@ -25,7 +24,7 @@ border-right: 0; } #admin-menu .dropdown .admin-menu-tab a { - border-left: 1px solid #52565E; + border-left: 1px solid #52565e; border-right: 0; } #admin-menu .dropdown li li a { @@ -42,13 +41,13 @@ /* Second-level lists */ #admin-menu .dropdown li ul { left: auto; - right: -999em; + right: auto; } /* Third-and-above-level lists */ #admin-menu .dropdown li li.expandable ul { - margin-left: 0; - margin-right: 160px; + margin-left: 0 !important; + margin-right: 160px !important; } /* Lists nested under hovered list items */ diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.admin.js b/sites/all/modules/contrib/admin/admin_menu/admin_menu.admin.js index 9ee9f36f..37534631 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.admin.js +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.admin.js @@ -1,4 +1,8 @@ -(function($) { +/** + * @file + */ + +(function ($) { /** * Live preview of Administration menu components. @@ -45,9 +49,9 @@ Drupal.behaviors.adminMenuPermissionsSetupHelp = { // Figure out which is the other, check whether it still disabled, // and if so, ask whether to auto-enable it. var other = (this == $admin[index] ? $menu[index] : $admin[index]); - if (!other.checked && confirm(Drupal.t('Also allow !name role to !permission?', { - '!name': $roles[index].textContent, - '!permission': (this == $admin[index] ? menuPermission : adminPermission) + if (!other.checked && confirm(Drupal.t('Also allow @name role to @permission?', { + '@name': $roles[index].textContent, + '@permission': (this == $admin[index] ? menuPermission : adminPermission) }))) { other.checked = 'checked'; } diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.color.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu.color.css index ea3ef491..00cbf651 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.color.css +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.color.css @@ -1,4 +1,3 @@ - /** * @file * Administration menu color override. @@ -17,7 +16,7 @@ border-right-color: #a91f1f; } #admin-menu ul li.admin-menu-tab a { - border-right-color: #52565E; + border-right-color: #52565e; } #admin-menu li li a { border-top-color: #801f1f; diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu.css index 52ae3ff5..73f15e32 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.css +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.css @@ -1,4 +1,3 @@ - /** * @file * Administration menu. @@ -16,6 +15,7 @@ position: absolute; text-align: left; top: 0; + height: 30px; width: 100%; } #admin-menu-wrapper { @@ -62,7 +62,7 @@ body.admin-menu { #admin-menu li > span { background: transparent none; border: none; - color: #EEE; + color: #eee; font-weight: normal; text-align: left; /* LTR */ text-decoration: none; @@ -74,7 +74,7 @@ body.admin-menu { padding: 4px 8px; } #admin-menu .dropdown .admin-menu-tab a { - border-right: 1px solid #52565E; /* LTR */ + border-right: 1px solid #52565e; /* LTR */ } #admin-menu .dropdown li li a { border-right: none; /* LTR */ @@ -147,7 +147,7 @@ body.admin-menu { /* Second-and-more-level hovering */ #admin-menu .dropdown li li.expandable { - background: #45454A url(images/arrow.png) no-repeat 145px 6px; + background: #45454a url(images/arrow.png) no-repeat 145px 6px; } #admin-menu .dropdown li li:hover { background-color: #111; @@ -155,19 +155,19 @@ body.admin-menu { #admin-menu .dropdown li li:hover a, #admin-menu .dropdown li li:hover li:hover a, #admin-menu .dropdown li li:hover li:hover li:hover a { - color: #FFF; + color: #fff; } #admin-menu .dropdown li li.expandable:hover a, #admin-menu .dropdown li li.expandable:hover li.expandable:hover a { border-color: #444; - color: #EEE; + color: #eee; } #admin-menu .dropdown li li.expandable:hover li a, #admin-menu .dropdown li li.expandable:hover li.expandable:hover li a { border-color: #323232; } #admin-menu .dropdown li li:hover li a { - color: #EEE; + color: #eee; } /* Search form */ diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.inc b/sites/all/modules/contrib/admin/admin_menu/admin_menu.inc index 2eab789b..5721d9ad 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.inc +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.inc @@ -97,7 +97,7 @@ function admin_menu_tree_dynamic(array $expand_map) { $db_or = db_or(); foreach ($plids as $path_plids) { $db_and = db_and(); - // plids with value 0 may be ignored. + // Plids with value 0 may be ignored. foreach (array_filter($path_plids) as $column => $plid) { $db_and->condition($column, $plid); } @@ -204,7 +204,7 @@ function admin_menu_merge_tree(array &$tree, array $tree_dynamic, array $expand_ foreach ($load_functions as $index => $function) { if ($function) { if (is_array($function)) { - list($function,) = each($function); + $function = key($function); } // Add the loader function name minus "_load". $placeholder = '%' . substr($function, 0, -5); @@ -269,7 +269,7 @@ function admin_menu_translate($router_item, $map) { // replace any other. // @todo Doing this instead leads to plenty of duplicate links below // admin/structure/menu; likely a hidden recursion problem. - // $router_item['mlid'] = $router_item['href'] . $router_item['mlid']; + // $router_item['mlid'] = $router_item['href'] . $router_item['mlid'];. $router_item['mlid'] = $router_item['href']; // Turn menu callbacks into regular menu items to make them visible. if ($router_item['type'] == MENU_CALLBACK) { @@ -278,10 +278,12 @@ function admin_menu_translate($router_item, $map) { // @see _menu_tree_check_access() $key = (50000 + $router_item['weight']) . ' ' . $router_item['title'] . ' ' . $router_item['mlid']; - return array($key => array( - 'link' => $router_item, - 'below' => array(), - )); + return array( + $key => array( + 'link' => $router_item, + 'below' => array(), + ), + ); } return array(); @@ -461,20 +463,22 @@ function admin_menu_links_icon() { '#access' => user_access('display drupal links'), '#href' => 'http://drupal.org', ); - // Add links to project issue queues. - foreach (module_list(FALSE, TRUE) as $module) { - $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); - if (!isset($info['project']) || isset($links['icon']['drupal.org'][$info['project']])) { - continue; + if (variable_get('admin_menu_issue_queues', TRUE)) { + // Add links to project issue queues. + foreach (module_list(FALSE, TRUE) as $module) { + $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); + if (!isset($info['project']) || isset($links['icon']['drupal.org'][$info['project']])) { + continue; + } + $links['icon']['drupal.org'][$info['project']] = array( + '#title' => t('@project issue queue', array('@project' => $info['name'])), + '#weight' => ($info['project'] == 'drupal' ? -10 : 0), + '#href' => 'http://drupal.org/project/issues/' . $info['project'], + '#options' => array( + 'query' => array('version' => (isset($info['core']) ? $info['core'] : 'All')), + ), + ); } - $links['icon']['drupal.org'][$info['project']] = array( - '#title' => t('@project issue queue', array('@project' => $info['name'])), - '#weight' => ($info['project'] == 'drupal' ? -10 : 0), - '#href' => 'http://drupal.org/project/issues/' . $info['project'], - '#options' => array( - 'query' => array('version' => (isset($info['core']) ? $info['core'] : 'All')), - ), - ); } // Add items to flush caches. $links['icon']['flush-cache'] = array( @@ -570,7 +574,7 @@ function admin_menu_links_users() { '#description' => t('Current anonymous / authenticated users'), '#weight' => -90, '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-users')), - '#href' => (user_access('administer users') ? 'admin/people/people' : 'user'), + '#href' => (user_access('administer users') ? 'admin/people' : 'user'), ); return $links; } @@ -658,7 +662,7 @@ function admin_menu_theme_settings() { '#default_value' => variable_get('admin_menu_tweak_modules', 0), ); if (module_exists('util')) { - $form['tweaks']['admin_menu_tweak_modules']['#description'] .= '
' . t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') . ''; + $form['tweaks']['admin_menu_tweak_modules']['#description'] = '
' . t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') . ''; } $form['tweaks']['admin_menu_tweak_permissions'] = array( '#type' => 'checkbox', @@ -685,6 +689,11 @@ function admin_menu_theme_settings() { '#title' => t('Cache menu in client-side browser'), '#default_value' => variable_get('admin_menu_cache_client', 1), ); + $form['performance']['admin_menu_issue_queues'] = array( + '#type' => 'checkbox', + '#title' => t('Show Issue Queue links in icon menu'), + '#default_value' => variable_get('admin_menu_issue_queues', 1), + ); return system_settings_form($form); } @@ -763,18 +772,20 @@ function admin_menu_flush_cache($name = NULL) { if (!isset($caches[$name])) { return MENU_NOT_FOUND; } + $message = t('@title cache cleared.', array('@title' => $caches[$name]['title'])); } else { $caches[$name] = array( 'title' => t('Every'), 'callback' => 'drupal_flush_all_caches', ); + $message = t('All caches cleared.'); } // Pass the cache to flush forward to the callback. $function = $caches[$name]['callback']; $function($name); - drupal_set_message(t('!title cache cleared.', array('!title' => $caches[$name]['title']))); + drupal_set_message($message); // The JavaScript injects a destination request parameter pointing to the // originating page, so the user is redirected back to that page. Without @@ -907,4 +918,3 @@ function template_preprocess_admin_menu_icon(&$variables) { function theme_admin_menu_icon($variables) { return '' . $variables['alt'] . ''; } - diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.info b/sites/all/modules/contrib/admin/admin_menu/admin_menu.info index c6dbd892..ffd22e44 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.info +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.info @@ -8,9 +8,8 @@ configure = admin/config/administration/admin_menu dependencies[] = system (>7.10) files[] = tests/admin_menu.test -; Information added by Drupal.org packaging script on 2014-12-19 -version = "7.x-3.0-rc5" +; Information added by Drupal.org packaging script on 2018-12-03 +version = "7.x-3.0-rc6" core = "7.x" project = "admin_menu" -datestamp = "1419029284" - +datestamp = "1543859284" diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.js b/sites/all/modules/contrib/admin/admin_menu/admin_menu.js index 2e28b554..1e32b3d6 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.js +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.js @@ -1,4 +1,8 @@ -(function($) { +/** + * @file + */ + +(function ($) { Drupal.admin = Drupal.admin || {}; Drupal.admin.behaviors = Drupal.admin.behaviors || {}; @@ -139,7 +143,7 @@ Drupal.admin.getCache = function (hash, onSuccess) { * * @see toolbar.js */ -Drupal.admin.height = function() { +Drupal.admin.height = function () { var $adminMenu = $('#admin-menu'); var height = $adminMenu.outerHeight(); // In IE, Shadow filter adds some extra height, so we need to remove it from @@ -161,7 +165,7 @@ Drupal.admin.height = function() { Drupal.admin.attachBehaviors = function (context, settings, $adminMenu) { if ($adminMenu.length) { $adminMenu.addClass('admin-menu-processed'); - $.each(Drupal.admin.behaviors, function() { + $.each(Drupal.admin.behaviors, function () { this(context, settings, $adminMenu); }); } @@ -206,7 +210,7 @@ Drupal.admin.behaviors.replacements = function (context, settings, $adminMenu) { */ Drupal.admin.behaviors.destination = function (context, settings, $adminMenu) { if (settings.admin_menu.destination) { - $('a.admin-menu-destination', $adminMenu).each(function() { + $('a.admin-menu-destination', $adminMenu).each(function () { this.search += (!this.search.length ? '?' : '&') + Drupal.settings.admin_menu.destination; }); } diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.map.inc b/sites/all/modules/contrib/admin/admin_menu/admin_menu.map.inc index f86e80cd..831e3243 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.map.inc +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.map.inc @@ -80,7 +80,14 @@ function field_ui_admin_menu_map() { 'access callback' => 'user_access', 'access arguments' => array('administer site configuration'), ); - if (!call_user_func_array($bundle_info['admin']['access callback'], $bundle_info['admin']['access arguments'])) { + $access_arguments = $bundle_info['admin']['access arguments']; + if (isset($bundle_info['admin']['real path'])) { + $menu_item = menu_get_item($bundle_info['admin']['real path']); + if (isset($menu_item['map'])) { + $access_arguments = menu_unserialize(serialize($access_arguments), $menu_item['map']); + } + } + if (!call_user_func_array($bundle_info['admin']['access callback'], $access_arguments)) { continue; } diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.module b/sites/all/modules/contrib/admin/admin_menu/admin_menu.module index 795ad211..f9ce3aed 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.module +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.module @@ -63,7 +63,7 @@ function admin_menu_theme() { function admin_menu_menu() { // AJAX callback. // @see http://drupal.org/project/js - $items['js/admin_menu/cache'] = array( + $items['js/admin_menu/cache/%'] = array( 'page callback' => 'admin_menu_js_cache', 'delivery callback' => 'admin_menu_deliver', 'access arguments' => array('access administration menu'), @@ -78,7 +78,7 @@ function admin_menu_menu() { 'file' => 'system.admin.inc', 'file path' => drupal_get_path('module', 'system'), ); - $items['admin/config/administration/admin_menu'] = array( + $items['admin/config/administration/admin-menu'] = array( 'title' => 'Administration menu', 'description' => 'Adjust administration menu settings.', 'page callback' => 'drupal_get_form', @@ -211,7 +211,7 @@ function admin_menu_page_build(&$page) { // @todo Drupal.behaviors.adminMenuMarginTop is obsolete, but // hook_page_build() does not allow to set a CSS class on the body yet. // @see http://drupal.org/node/1473548, http://drupal.org/node/1194528 - //$page['#attributes']['class'][] = 'admin-menu'; + // $page['#attributes']['class'][] = 'admin-menu'; } if ($setting = variable_get('admin_menu_position_fixed', 1)) { $settings['position_fixed'] = $setting; @@ -230,7 +230,7 @@ function admin_menu_page_build(&$page) { if ($_GET['q'] == 'admin/modules' || strpos($_GET['q'], 'admin/modules/list') === 0) { $settings['tweak_modules'] = variable_get('admin_menu_tweak_modules', 0); } - if ($_GET['q'] == 'admin/people/permissions' || $_GET['q'] == 'admin/people/permissions/list') { + if (strpos($_GET['q'], 'admin/people/permissions') === 0) { $settings['tweak_permissions'] = variable_get('admin_menu_tweak_permissions', 0); } @@ -502,7 +502,6 @@ function admin_menu_output($complete = FALSE) { // @todo Move the below callbacks into hook_admin_menu_build() // implementations (and $module.admin_menu.inc). - // Add administration menu. if (!empty($components['admin_menu.menu']) || $complete) { $content['menu'] = admin_menu_links_menu(admin_menu_tree('management')); @@ -548,7 +547,10 @@ function admin_menu_output($complete = FALSE) { // Store the new hash for this user. if (!empty($_COOKIE['has_js']) && !$complete) { - admin_menu_cache_set($cid, md5($content)); + $cache = cache_get($cid, 'cache_admin_menu'); + if (!$cache || !isset($cache->data)) { + admin_menu_cache_set($cid, md5($content)); + } } return $content; @@ -603,11 +605,13 @@ function admin_menu_admin_menu_output_build(&$content) { * Implements hook_admin_menu_output_alter(). */ function admin_menu_admin_menu_output_alter(&$content) { - foreach ($content['menu'] as $key => $link) { - // Move local tasks on 'admin' into icon menu. - if ($key == 'admin/tasks' || $key == 'admin/index') { - $content['icon']['icon'][$key] = $link; - unset($content['menu'][$key]); + if (!empty($content['menu'])) { + foreach ($content['menu'] as $key => $link) { + // Move local tasks on 'admin' into icon menu. + if ($key == 'admin/tasks' || $key == 'admin/index') { + $content['icon']['icon'][$key] = $link; + unset($content['menu'][$key]); + } } } } @@ -677,6 +681,13 @@ function theme_admin_menu_links($variables) { $elements[$path]['#options']['attributes']['class'][] = 'admin-menu-destination'; } + // If the path has an alias replace the href with the alias. + if (module_exists('path')) { + if ($alias = drupal_get_path_alias($elements[$path]['#href'])) { + $elements[$path]['#href'] = $alias; + } + } + $link = l($elements[$path]['#title'], $elements[$path]['#href'], $elements[$path]['#options']); } // Handle plain text items, but do not interfere with menu additions. @@ -751,7 +762,7 @@ function admin_menu_translated_menu_link_alter(&$item, $map) { } } - // Don't waste cycles altering items that are not visible + // Don't waste cycles altering items that are not visible. if (!$item['access']) { return; } @@ -795,8 +806,8 @@ function admin_menu_flush_caches($uid = NULL) { cache_clear_all($cid, 'cache_menu', TRUE); // Flush client-side cache hashes. drupal_static_reset('admin_menu_cache_get'); - // db_table_exists() required for SimpleTest. - if (db_table_exists('cache_admin_menu')) { + // If cache_admin_menu is not empty, flush it. + if (!cache_is_empty('cache_admin_menu')) { cache_clear_all(isset($uid) ? $cid : '*', 'cache_admin_menu', TRUE); } } diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu.uid1.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu.uid1.css index e375cfe6..105fd242 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu.uid1.css +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu.uid1.css @@ -1,4 +1,3 @@ - /** * @file * Administration menu color override for uid1. diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar-rtl.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar-rtl.css new file mode 100644 index 00000000..a159034d --- /dev/null +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar-rtl.css @@ -0,0 +1,4 @@ +#admin-menu > div > .dropdown > li > a, +#admin-menu > div > .dropdown > li > span { + border-left: 0; +} diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css index a3e9f3e3..f1bc0935 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css @@ -1,4 +1,3 @@ - /** * @file * Toolbar style for Administration menu. @@ -63,8 +62,9 @@ body div#toolbar.toolbar { background: url(toolbar.png) no-repeat 0 -45px; text-indent: -9999px; } -#admin-menu > div > .dropdown > li > a { - border-right: 0; +#admin-menu > div > .dropdown > li > a, +#admin-menu > div > .dropdown > li > span { + border-right: 0; /* LTR */ margin-bottom: 4px; padding: 2px 10px 3px; } @@ -142,4 +142,3 @@ body div#toolbar.toolbar { #admin-menu .shortcut-toolbar a { display: block; } - diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info index fa4ca095..340ced07 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info @@ -4,9 +4,8 @@ package = Administration core = 7.x dependencies[] = admin_menu -; Information added by Drupal.org packaging script on 2014-12-19 -version = "7.x-3.0-rc5" +; Information added by Drupal.org packaging script on 2018-12-03 +version = "7.x-3.0-rc6" core = "7.x" project = "admin_menu" -datestamp = "1419029284" - +datestamp = "1543859284" diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install index bf067d78..f6449dcd 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install @@ -34,4 +34,3 @@ function admin_menu_toolbar_update_6300() { ->condition('name', 'admin_menu_toolbar') ->execute(); } - diff --git a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module index c6111bdc..0f5c0662 100644 --- a/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module +++ b/sites/all/modules/contrib/admin/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module @@ -115,4 +115,3 @@ function admin_menu_toolbar_admin_menu_output_alter(&$content) { $content['account']['account']['#options']['html'] = TRUE; } } - diff --git a/sites/all/modules/contrib/admin/admin_menu/tests/admin_menu.test b/sites/all/modules/contrib/admin/admin_menu/tests/admin_menu.test index 4b48c9ab..b7c611d7 100644 --- a/sites/all/modules/contrib/admin/admin_menu/tests/admin_menu.test +++ b/sites/all/modules/contrib/admin/admin_menu/tests/admin_menu.test @@ -16,7 +16,10 @@ class AdminMenuWebTestCase extends DrupalWebTestCase { 'admin_menu' => 'access administration menu', ); - function setUp() { + /** + * + */ + public function setUp() { // Enable admin menu module and any other modules. $modules = func_get_args(); $modules = isset($modules[0]) ? $modules[0] : $modules; @@ -108,12 +111,17 @@ class AdminMenuWebTestCase extends DrupalWebTestCase { $xpath = '//div[@id="admin-menu"]/div/ul' . implode('/parent::li/ul', $xpath); $this->assertNoElementByXPath($xpath, $args, $message . ' link not found.'); } + } /** * Tests menu links depending on user permissions. */ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { + + /** + * + */ public static function getInfo() { return array( 'name' => 'Menu link access permissions', @@ -122,14 +130,17 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { ); } - function setUp() { + /** + * + */ + public function setUp() { parent::setUp(array('node')); } /** * Test that the links are added to the page (no JS testing). */ - function testPermissions() { + public function testPermissions() { module_enable(array('contact')); $this->resetAll(); @@ -140,7 +151,7 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { // Create a user who // - can access content overview // - cannot access drupal.org links - // - cannot administer Contact module + // - cannot administer Contact module. $permissions = $this->basePermissions + array( 'access content overview', ); @@ -156,7 +167,7 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { // Create a user "reversed" to the above; i.e., who // - cannot access content overview // - can access drupal.org links - // - can administer Contact module + // - can administer Contact module. $permissions = $this->basePermissions + array( 'display drupal links', 'administer contact forms', @@ -172,7 +183,7 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { /** * Tests handling of links pointing to category/overview pages. */ - function testCategories() { + public function testCategories() { // Create a user with minimum permissions. $admin_user = $this->drupalCreateUser($this->basePermissions); $this->drupalLogin($admin_user); @@ -201,7 +212,7 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { /** * Tests that user role and permission changes are properly taken up. */ - function testPermissionChanges() { + public function testPermissionChanges() { // Create a user who is able to change permissions. $permissions = $this->basePermissions + array( 'administer permissions', @@ -253,12 +264,17 @@ class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { // Verify that Structure » Content types does not appear. $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types'))); } + } /** * Tests appearance, localization, and escaping of dynamic links. */ class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase { + + /** + * + */ public static function getInfo() { return array( 'name' => 'Dynamic links', @@ -267,14 +283,17 @@ class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase { ); } - function setUp() { + /** + * + */ + public function setUp() { parent::setUp(array('node')); } /** * Tests node type links. */ - function testNode() { + public function testNode() { $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); // Create a content-type with special characters. $type = $this->drupalCreateContentType(array('type' => 'special', 'name' => 'Cool & Special')); @@ -324,7 +343,7 @@ class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase { /** * Tests Add content links. */ - function testNodeAdd() { + public function testNodeAdd() { $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); // Verify that "Add content" does not appear for unprivileged users. @@ -359,12 +378,17 @@ class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase { t('Add content'), )); } + } /** * Tests appearance of different types of links. */ class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase { + + /** + * + */ public static function getInfo() { return array( 'name' => 'Link types', @@ -373,7 +397,10 @@ class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase { ); } - function setUp() { + /** + * + */ + public function setUp() { parent::setUp(array('help')); $permissions = module_invoke_all('permission'); @@ -385,7 +412,7 @@ class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase { /** * Tests appearance of different router item link types. */ - function testLinkTypes() { + public function testLinkTypes() { // Verify that MENU_NORMAL_ITEMs appear. $this->assertLinkTrailByTitle(array( t('Configuration'), @@ -420,12 +447,17 @@ class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase { ':title' => t('Index'), ), "Icon » Index link found."); } + } /** * Tests customized menu links. */ class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { + + /** + * + */ public static function getInfo() { return array( 'name' => 'Customized links', @@ -434,7 +466,10 @@ class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { ); } - function setUp() { + /** + * + */ + public function setUp() { parent::setUp(array('menu')); $this->admin_user = $this->drupalCreateUser($this->basePermissions + array( @@ -446,7 +481,7 @@ class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { /** * Test disabled custom links. */ - function testCustomDisabled() { + public function testCustomDisabled() { $type = $this->drupalCreateContentType(); $node = $this->drupalCreateNode(array('type' => $type->type)); $text = $this->randomName(); @@ -488,7 +523,7 @@ class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { /** * Tests external links. */ - function testCustomExternal() { + public function testCustomExternal() { // Add a custom link to the node to the menu. $edit = array( 'link_path' => 'http://example.com', @@ -516,5 +551,5 @@ class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { ':path' => $path, ))->fetchField(); } -} +} diff --git a/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.admin.inc b/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.admin.inc index 34a0d09f..c3aaea1f 100644 --- a/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.admin.inc +++ b/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.admin.inc @@ -465,12 +465,33 @@ function entity_translation_export_import_import_translation($data){ $bundle = $data['Bundle (Not Editable)']; $entity_id = $data['Entity ID (Not Editable)']; - $entities = entity_load($entity_type, array($entity_id)); + if(empty($entity_id)) { + if ($entity_type == 'taxonomy_term') { + // Handle taxonomy term entity. + $vocab = taxonomy_vocabulary_machine_name_load($bundle); + $term = new stdClass(); + $term->name = ''; + $term->vid = $vocab->vid; + taxonomy_term_save($term); - // If cannot load entity. - if(empty($entities)){ - drupal_set_message(t('Entity with id @id could not be found in database.', array('@id' => $entity_id))); - return FALSE; + $entities = entity_load($entity_type, array($term->tid)); + } + else if($entity_type == 'node') { + // Handle node entity. + $node = new stdClass(); + $node->type = $bundle; + node_object_prepare($node); //Set some default values + $node->status = 1; + $node->promote = 0; + $node->sticky = 0; + $node->uid = $user->uid; + node_save($node); + + $entities = entity_load($entity_type, array($node->nid)); + } + } + else { + $entities = entity_load($entity_type, array($entity_id)); } // Get the entity. diff --git a/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.info b/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.info index fd93689a..5e4ea753 100644 --- a/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.info +++ b/sites/all/modules/contrib/admin/entity_translation_export_import/entity_translation_export_import.info @@ -5,9 +5,9 @@ package = Multilingual - Entity Translation dependencies[] = entity dependencies[] = entity_translation -; Information added by drupal.org packaging script on 2013-09-30 -version = "7.x-1.0-beta3+0-dev" +; Information added by Drupal.org packaging script on 2017-02-08 +version = "7.x-1.0-beta4" core = "7.x" project = "entity_translation_export_import" -datestamp = "1380577025" +datestamp = "1486567689" diff --git a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.components.inc b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.components.inc index 35934551..f1ab2561 100644 --- a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.components.inc +++ b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.components.inc @@ -1,13 +1,13 @@ array(), 'description' => '', 'available_countries' => array(), + 'default_country' => '', + 'format_handlers' => array(), 'csv_separate' => 0, ), ); @@ -30,21 +32,22 @@ function _webform_defaults_addressfield() { /** * Generate the form for editing a component. + * * Create a set of form elements to be displayed on the form for editing this * component. Use care naming the form items, as this correlates directly to the * database schema. The component "Name" and "Description" fields are added to * every component type and are not necessary to specify here (although they * may be overridden if desired). * - * @param $component + * @param mixed $component * A Webform component array. * - * @return + * @return array * An array of form items to be displayed on the edit component page */ function _webform_edit_addressfield($component) { $form = array(); - + $form['extra']['available_countries'] = array( '#type' => 'select', '#multiple' => TRUE, @@ -53,6 +56,21 @@ function _webform_edit_addressfield($component) { '#options' => _addressfield_country_options_list(), '#default_value' => $component['extra']['available_countries'], ); + $form['extra']['default_country'] = array( + '#type' => 'select', + '#multiple' => FALSE, + '#title' => t('Default country'), + '#description' => t('Select which country should be selected as the default.'), + '#options' => array_merge(array(0 => t('- None -')), _addressfield_country_options_list()), + '#default_value' => $component['extra']['default_country'], + ); + $form['extra']['format_handlers'] = array( + '#type' => 'checkboxes', + '#title' => t('Format handlers'), + '#options' => addressfield_format_plugins_options(), + '#required' => TRUE, + '#default_value' => !empty($component['extra']['format_handlers']) ? $component['extra']['format_handlers'] : array('address'), + ); $form['extra']['csv_separate'] = array( '#type' => 'radios', '#title' => t('CSV download'), @@ -69,18 +87,21 @@ function _webform_edit_addressfield($component) { /** * Render a Webform component to be part of a form. * - * @param $component + * @param mixed $component * A Webform component array. - * @param $value + * @param mixed $value * If editing an existing submission or resuming a draft, this will contain * an array of values to be shown instead of the default in the component * configuration. This value will always be an array, keyed numerically for * each value saved in this field. - * @param $filter + * @param bool $filter * Whether or not to filter the contents of descriptions and values when * rendering the component. Values need to be unfiltered to be editable by * Form Builder. * + * @return array + * Form element. + * * @see _webform_client_form_add_component() */ function _webform_render_addressfield($component, $value = NULL, $filter = TRUE) { @@ -98,55 +119,98 @@ function _webform_render_addressfield($component, $value = NULL, $filter = TRUE) 'description', ), ); - + $available = !empty($component['extra']['available_countries']) ? $component['extra']['available_countries'] : NULL; - - // Get the current address - if (!empty($value[0])) { - if (is_string($value[0])) { - $address = unserialize($value[0]); + + // Get the current address. + $address = _addressfield_tokens_expand_value($value); + if (empty($address)) { + if (!empty($component['value'])) { + $address = $component['value']; } else { - $address = $value[0]; + $address = _webform_addressfield($component['cid']); } } - elseif (!empty($component['value'])) { - $address = $component['value']; - } - else { - $address = _webform_addressfield($component['cid']); - } if (empty($address)) { - $address = addressfield_default_values($available); + $address = _webform_addressfield_default_values($available, $component); } - + // Generate the address form. $context = array( 'mode' => 'form', + 'instance' => array( + 'required' => $component['required'], + ), + 'form_key' => $component['form_key'], ); - $element += addressfield_generate($address, array('address'), $context); - - if (!empty($available)) { - $element['country']['#options'] = array_intersect_key($element['country']['#options'], $available); + $handlers = !empty($component['extra']['format_handlers']) ? $component['extra']['format_handlers'] : array('address'); + $element += addressfield_generate($address, $handlers, $context); + + if (empty($address['country'])) { + $element['street_block']['#access'] = FALSE; + $element['locality_block']['#access'] = FALSE; } - $element['country']['#element_validate'] = array('_webform_addressfield_country_validate'); - $element['country']['#cid'] = $component['cid']; - $element['country']['#limit_validation_errors'] = array(); - + + if (isset($element['country'])) { + if (!empty($available)) { + $element['country']['#options'] = array_intersect_key($element['country']['#options'], $available); + + // Hide the country element only if there is one option and the whole field + // is required, otherwise there will always be an additional None option. + // @see addressfield_format_address_hide_country() + if (!empty($handlers['address-hide-country']) && count($element['country']['#options']) == 1 && $component['required']) { + $element['country']['#access'] = FALSE; + } + } + $element['country']['#default_value'] = $address['country']; + $element['country']['#element_validate'] = array('_webform_addressfield_country_validate'); + $element['country']['#cid'] = $component['cid']; + $element['country']['#limit_validation_errors'] = array(); + } + $form_state = array(); - drupal_alter('field_widget_addressfield_standard_form', $element, $form_state, $context); - + drupal_alter('field_widget_addressfield_standard_form', $element, $form_state, $context); + return $element; } +function _webform_addressfield_default_values($available, $component) { + $default_country = !empty($component['extra']['default_country']) + ? $component['extra']['default_country'] + : addressfield_tokens_default_country(); + $default_values = array( + 'country' => $default_country, + 'name_line' => '', + 'first_name' => '', + 'last_name' => '', + 'organisation_name' => '', + 'administrative_area' => '', + 'sub_administrative_area' => '', + 'locality' => '', + 'dependent_locality' => '', + 'postal_code' => '', + 'thoroughfare' => '', + 'premise' => '', + 'sub_premise' => '', + 'data' => '', + ); + return ($default_values); +} + /** - * Stores an addressfield submitted in a webform component. Ideally we should store - * it in the $form_state instead, but there appears to be no way to get it to actually - * pass through to _webform_render_addressfield(). - * - * @param $cid integer The ID of the webform component. - * @param $address array If set, this address will be stored with the given $cid. - * @return array The address stored with the given $cid, if there is one; otherwise, NULL. + * Stores an addressfield submitted in a webform component. + * + * Ideally store it in the $form_state instead, but there appears to be no way + * to get it to actually pass through to _webform_render_addressfield(). + * + * @param int $cid + * The ID of the webform component. + * @param mixed $address + * If set, this address will be stored with the given $cid. + * + * @return array + * The address stored with the given $cid, if there is one; otherwise, NULL. */ function _webform_addressfield($cid, $address = NULL) { $out = &drupal_static(__FUNCTION__, array()); @@ -160,40 +224,41 @@ function _webform_addressfield($cid, $address = NULL) { } /** - * Validates a country, and if it changes, rebuilds the form for the new country + * Validates a country, and if changed, rebuilds the form for the new country. */ function _webform_addressfield_country_validate(&$element, &$form_state) { // If the country was changed, rebuild the form. - if ($element['#default_value'] != $element['#value']) { + if (!isset($element['#default_value']) || $element['#default_value'] != $element['#value']) { $form_state['rebuild'] = TRUE; } - + $cid = $element['#cid']; $parents = $element['#parents']; array_pop($parents); // Search through the form values to find the current address. $address = drupal_array_get_nested_value($form_state['values'], $parents); - + _webform_addressfield($cid, $address); } /** * Display the result of a submission for a component. + * * The output of this function will be displayed under the "Results" tab then * "Submissions". This should output the saved data in some reasonable manner. * - * @param $component + * @param mixed $component * A Webform component array. - * @param $value + * @param mixed $value * An array of information containing the submission result, directly * correlating to the webform_submitted_data database table schema. - * @param $format + * @param string $format * Either 'html' or 'text'. Defines the format that the content should be * returned as. Make sure that returned content is run through check_plain() * or other filtering functions when returning HTML. * - * @return + * @return array * A renderable element containing at the very least these properties: * - #title * - #weight @@ -205,27 +270,23 @@ function _webform_addressfield_country_validate(&$element, &$form_state) { * (such as wrapping the text) or as HTML (ensuring consistent output). */ function _webform_display_addressfield($component, $value, $format = 'html') { - $address = NULL; - if (isset($value[0])) { - $address = $value[0]; - if (is_string($address)) { - $address = unserialize($address); - } - } + $address = _addressfield_tokens_expand_value($value); return array( '#title' => $component['name'], '#weight' => $component['weight'], '#theme' => $format == 'html' ? 'addressfield_formatter' : 'addressfield_formatter__linear', - '#theme_wrappers' => $format == 'html' ? array('webform_element' ) : array('webform_element_text'), + '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'), '#post_render' => array('webform_element_wrapper'), '#component' => $component, '#format' => $format, - '#address' => $address, + '#address' => $address ? $address : NULL, + '#handlers' => $component['extra']['format_handlers'], ); } /** * A hook for changing the input values before saving to the database. + * * Webform expects a component to consist of a single field, or a single array * of fields. If you have a component that requires a deeper form tree * you must flatten the data into a single array using this callback @@ -234,12 +295,12 @@ function _webform_display_addressfield($component, $value, $format = 'html') { * Note that Webform will save the result of this function directly into the * database. * - * @param $component + * @param mixed $component * A Webform component array. - * @param $value + * @param mixed $value * The POST data associated with the user input. * - * @return + * @return array * An array of values to be saved into the database. Note that this should be * a numerically keyed array. */ @@ -249,88 +310,92 @@ function _webform_submit_addressfield($component, $value) { /** * Calculate and returns statistics about results for this component. + * * This takes into account all submissions to this webform. The output of this * function will be displayed under the "Results" tab then "Analysis". * - * @param $component + * @param mixed $component * An array of information describing the component, directly correlating to * the webform_component database schema. - * @param $sids + * @param mixed $sids * An optional array of submission IDs (sid). If supplied, the analysis will * be limited to these sids. - * @param $single + * @param bool $single * Boolean flag determining if the details about a single component are being * shown. May be used to provided detailed information about a single * component's analysis, such as showing "Other" options within a select list. * - * @return + * @return array * An array of data rows, each containing a statistic for this component's * submissions. */ function _webform_analysis_addressfield($component, $sids = array(), $single = FALSE) { - // TODO Update this function - + // @todo Update this function + // Generate the list of options and questions. $query = db_select('webform_submitted_data', 'wsd') ->fields('wsd', array('data')) ->condition('nid', $component['nid']) ->condition('cid', $component['cid']); - - if ( count($sids) ) { + + if (count($sids)) { $query->condition('sid', $sids, 'IN'); } $non_blanks = 0; $submissions = 0; $results = $query->execute(); foreach ($results as $row) { - if ( drupal_strlen(trim($row->data)) > 0 ) { + if (drupal_strlen(trim($row->data)) > 0) { $non_blanks++; } $submissions++; } $rows[0] = array( t('Left Blank'), - ( $submissions - $non_blanks ) + ($submissions - $non_blanks), ); $rows[1] = array( t('User entered value'), - $non_blanks + $non_blanks, ); - return $rows; + return array('table_rows' => $rows); } /** * Return the result of a component value for display in a table. + * * The output of this function will be displayed under the "Results" tab then * "Table". * - * @param $component + * @param mixed $component * A Webform component array. - * @param $value + * @param mixed $value * An array of information containing the submission result, directly * correlating to the webform_submitted_data database schema. * - * @return + * @return string * Textual output formatted for human reading. */ function _webform_table_addressfield($component, $value) { - if (!empty($value[0])) { - return theme('addressfield_formatter', array( 'address' => $value[0] )); + $address = _addressfield_tokens_expand_value($value); + if ($address) { + return theme('addressfield_formatter', array('address' => $address)); } return ''; } /** * Return the header for this component to be displayed in a CSV file. + * * The output of this function will be displayed under the "Results" tab then * "Download". * - * @param $component + * @param mixed $component * A Webform component array. - * @param $export_options + * @param mixed $export_options * An array of options that may configure export of this field. * - * @return + * @return array * An array of data to be displayed in the first three rows of a CSV file, not * including either prefixed or trailing commas. */ @@ -340,7 +405,6 @@ function _webform_csv_headers_addressfield($component, $export_options) { $header[0] = array(); $header[1] = array(); $header[2] = array(); - foreach (addressfield_tokens_property_names() as $key => $name) { $header[0][] = ''; $header[1][] = (empty($header[1])) ? $component['name'] : ''; @@ -349,7 +413,7 @@ function _webform_csv_headers_addressfield($component, $export_options) { } else { $header[0] = array(''); - $header[1] = array(); + $header[1] = array(''); $header[2] = array($component['name']); } return $header; @@ -357,34 +421,56 @@ function _webform_csv_headers_addressfield($component, $export_options) { /** * Format the submitted data of a component for CSV downloading. + * * The output of this function will be displayed under the "Results" tab then * "Download". * - * @param $component + * @param mixed $component * A Webform component array. - * @param $export_options + * @param mixed $export_options * An array of options that may configure export of this field. - * @param $value + * @param mixed $value * An array of information containing the submission result, directly * correlating to the webform_submitted_data database schema. * - * @return + * @return array * An array of items to be added to the CSV file. Each value within the array * will be another column within the file. This function is called once for * every row of data. */ function _webform_csv_data_addressfield($component, $export_options, $value) { + $address = _addressfield_tokens_expand_value($value); if (!empty($component['extra']['csv_separate']) && $component['extra']['csv_separate'] == 1) { + // Each address component should be in a separate column. $return = array(); foreach (addressfield_tokens_property_names() as $key => $name) { - $return[] = (isset($value[0][$key])) ? $value[0][$key] : ''; + $return[] = (isset($address[$key])) ? $address[$key] : ''; } return $return; } else { - if (!empty($value[0])) { - return theme('addressfield_formatter__linear', array( 'address' => $value[0] )); + // The entire address should be displayed in the one column. + if ($address) { + return theme('addressfield_formatter__linear', array('address' => $address)); } return ''; } } + +/** + * Expand a raw address submission as loaded from the database to an array. + * + * @param string $value + * An array of information containing the submission result, directly + * correlating to the {webform_submitted_data} database schema. + * + * @return array|false + * An associative array of address fields, or FALSE on failure. + */ +function _addressfield_tokens_expand_value($value) { + if (isset($value[0]) && is_string($value[0])) { + return unserialize($value[0]); + } + return FALSE; +} + diff --git a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.info b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.info index 833cbe53..d5409935 100644 --- a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.info +++ b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.info @@ -1,16 +1,13 @@ - -name = Address Field Tokens -description = Creates tokens for address fields, adds new addressfield renders, and adds webform integration. -core = 7.x -package = Fields - -dependencies[] = addressfield -dependencies[] = entity_token -dependencies[] = token +name = Address Field Tokens +description = Creates tokens for address fields, adds new addressfield renders, and adds webform integration. +core = 7.x +package = Fields +dependencies[] = addressfield +dependencies[] = entity_token +dependencies[] = token -; Information added by Drupal.org packaging script on 2014-10-29 -version = "7.x-1.5" +; Information added by Drupal.org packaging script on 2018-10-11 +version = "7.x-1.13" core = "7.x" project = "addressfield_tokens" -datestamp = "1414599829" - +datestamp = "1539260884" diff --git a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.module b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.module index 92ad204d..e9143019 100644 --- a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.module +++ b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.module @@ -4,9 +4,12 @@ * Main components. */ +/** + * Implements hook_menu(). + */ function addressfield_tokens_menu() { $items = array(); - + $items['admin/config/regional/address'] = array( 'title' => 'Addresses', 'description' => 'Settings for address fields and tokens', @@ -16,7 +19,7 @@ function addressfield_tokens_menu() { 'file' => 'addressfield_tokens.admin.inc', 'type' => MENU_NORMAL_ITEM, ); - + return $items; } @@ -34,19 +37,31 @@ function addressfield_tokens_theme($existing, $type, $theme, $path) { 'file' => 'addressfield_tokens.theme.inc', ), 'addressfield_formatter__linear' => array( - 'variables' => array('address' => NULL, 'premise' => TRUE, 'organisation_name' => TRUE, 'name_line' => TRUE), + 'variables' => array( + 'address' => NULL, + 'premise' => TRUE, + 'organisation_name' => TRUE, + 'name_line' => TRUE, + ), 'file' => 'addressfield_tokens.theme.inc', ), 'addressfield_formatter__components' => array( 'variables' => array( 'address' => NULL, - 'components' => array('thoroughfare', 'premise', 'locality', 'administrative_area', 'postal_code', 'country'), + 'components' => array( + 'thoroughfare', + 'premise', + 'locality', + 'administrative_area', + 'postal_code', + 'country', + ), 'separator' => ', ', ), 'file' => 'addressfield_tokens.theme.inc', ), ); - + return $theme; } @@ -75,7 +90,14 @@ function addressfield_tokens_field_formatter_info() { 'label' => t('Address components'), 'field types' => array('addressfield'), 'settings' => array( - 'components' => array('thoroughfare', 'premise', 'locality', 'administrative_area', 'postal_code', 'country'), + 'components' => array( + 'thoroughfare', + 'premise', + 'locality', + 'administrative_area', + 'postal_code', + 'country', + ), 'separator' => ', ', ), ), @@ -103,14 +125,13 @@ function addressfield_tokens_field_formatter_settings_form($field, $instance, $v $element['separator'] = array( '#type' => 'textfield', '#title' => t('Separator'), - '#description' => t('The separator to use between components. Use \n for a line break.'), + '#description' => t('The separator to use between components. Use br tag for a line break.'), '#default_value' => $settings['separator'], ); } return $element; } - /** * Implements hook_field_formatter_settings_summary(). */ @@ -132,7 +153,7 @@ function addressfield_tokens_field_formatter_settings_summary($field, $instance, */ function addressfield_tokens_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { $element = array(); - + switch ($display['type']) { case 'addressfield_citystate': $theme = array('addressfield_formatter__citystate', 'addressfield_formatter'); @@ -147,7 +168,7 @@ function addressfield_tokens_field_formatter_view($entity_type, $entity, $field, ); } break; - + case 'addressfield_linear': $theme = array('addressfield_formatter__linear', 'addressfield_formatter'); @@ -161,7 +182,7 @@ function addressfield_tokens_field_formatter_view($entity_type, $entity, $field, ); } break; - + case 'addressfield_country': foreach ($items as $delta => $item) { if (!empty($item['country'])) { @@ -175,11 +196,11 @@ function addressfield_tokens_field_formatter_view($entity_type, $entity, $field, } } break; - + case 'addressfield_state': foreach ($items as $delta => $item) { if (!empty($item['country']) && !empty($item['administrative_area'])) { - $state = _addressfield_tokens_state($item['country'], $item['administrative_area']); + $state = addressfield_tokens_state($item['country'], $item['administrative_area']); $element[$delta] = array( '#type' => 'markup', '#markup' => filter_xss($state), @@ -189,19 +210,19 @@ function addressfield_tokens_field_formatter_view($entity_type, $entity, $field, } } break; - + case 'addressfield_components': $theme = array('addressfield_formatter__components', 'addressfield_formatter'); $settings = $display['settings']; foreach ($items as $delta => $item) { if (!empty($item['country'])) { array_unshift($theme, 'addressfield_formatter__components__' . $item['country']); - } + } $element[$delta] = array( '#theme' => $theme, '#address' => array_map('filter_xss', $item), '#components' => $settings['components'], - '#separator' => filter_xss($settings['separator']), + '#separator' => filter_xss($settings['separator'], array('br')), ); } break; @@ -230,11 +251,31 @@ function addressfield_tokens_property_names() { return $names; } +/** + * Generates token components. + * + * @return mixed + * Array of components. + */ function addressfield_tokens_components() { $comps = &drupal_static(__FUNCTION__, array()); if (empty($comps)) { $names = addressfield_tokens_property_names(); - foreach (array('first_name', 'last_name', 'name_line', 'organisation_name', 'thoroughfare', 'premise', 'locality', 'dependent_locality', 'administrative_area', 'sub_administrative_area', 'postal_code', 'country') as $key) { + $fields = array( + 'first_name', + 'last_name', + 'name_line', + 'organisation_name', + 'thoroughfare', + 'premise', + 'locality', + 'dependent_locality', + 'administrative_area', + 'sub_administrative_area', + 'postal_code', + 'country', + ); + foreach ($fields as $key) { $comps[$key] = $names[$key]; if (in_array($key, array('administrative_area', 'country'))) { $comps[$key . '_full'] = t('@name (full)', array( @@ -248,14 +289,15 @@ function addressfield_tokens_components() { /** * Gets the list of countries from the locale settings in Drupal. - * - * @return array An array of countries. The keys are the 2-letter + * + * @return array + * An array of countries. The keys are the 2-letter * abbreviations and the values are the full country names. */ function _addressfield_tokens_countries() { $countries = &drupal_static(__FUNCTION__); if (empty($countries)) { - include_once('includes/locale.inc'); + require_once DRUPAL_ROOT . '/includes/locale.inc'; $countries = country_get_list(); } return $countries; @@ -263,14 +305,17 @@ function _addressfield_tokens_countries() { /** * Gets the name of the country with the given abbreviation. - * - * @param string $country The 2-letter abbreviation of the country. - * @return string The name of the country, or FALSE. + * + * @param string $country + * The 2-letter abbreviation of the country. + * + * @return string + * The name of the country, or FALSE. */ function _addressfield_tokens_country($country) { $countries = _addressfield_tokens_countries(); - - // Country abbreviations will always be two uppercase letters. + + // Country abbreviations will always be two uppercase letters. $country = drupal_strtoupper($country); if (!empty($country) && isset($countries[$country])) { return check_plain($countries[$country]); @@ -279,11 +324,12 @@ function _addressfield_tokens_country($country) { } /** - * Gets the abbreviation of the country with the given name - * - * @param string + * Gets the abbreviation of the country with the given name. + * + * @param string $country * The name of the country. - * @return string $country + * + * @return string * The 2-letter abbreviation of the country, or FALSE. */ function _addressfield_tokens_country_abbr($country) { @@ -297,55 +343,63 @@ function _addressfield_tokens_country_abbr($country) { /** * Gets the list of states in the given country. - * - * @param string $country The 2-letter abbreviation of the country. - * - * @return array An array of countries. The keys are the 2-letter + * + * @param string $country + * The 2-letter abbreviation of the country. + * + * @return array + * An array of countries. The keys are the 2-letter * abbreviations and the values are the full country names. */ -function _addressfield_tokens_states($country) { +function addressfield_tokens_states($country) { + global $language; + $langcode = $language->language; $states = &drupal_static(__FUNCTION__); $country = drupal_strtoupper($country); if (!isset($states[$country])) { - $cache = cache_get('addressfield_tokens_states'); + $cache = cache_get('addressfield_tokens_states:' . $langcode); if ($cache) { $states = $cache->data; } } if (!isset($states[$country])) { $format = addressfield_generate(array('country' => $country), array('address'), array('mode' => 'render')); - + if (isset($format['locality_block']['administrative_area']['#options'])) { $states[$country] = $format['locality_block']['administrative_area']['#options']; } else { $states[$country] = array(); } - cache_set('addressfield_tokens_states', $states); + cache_set('addressfield_tokens_states:' . $langcode, $states); } return $states[$country]; } /** * Gets the name of the state with the given abbreviation. - * - * @param string $country The 2-letter abbreviation of the country. - * @param string $state The 2-letter abbreviation of the state. - * @return string The name of the state, or FALSE. + * + * @param string $country + * The 2-letter abbreviation of the country. + * @param string $state + * The 2-letter abbreviation of the state. + * + * @return string + * The name of the state, or FALSE. */ -function _addressfield_tokens_state($country, $state) { - $states = _addressfield_tokens_states($country); - - // State abbreviations will usually be two uppercase letters. - $state = drupal_strtoupper($state); - if (!empty($state) && !empty($states[$state])) { +function addressfield_tokens_state($country, $state) { + $states = addressfield_tokens_states($country); + + // State abbreviations will usually be two uppercase letters. + $state_upper = drupal_strtoupper($state); + if (!empty($state_upper) && !empty($states[$state_upper])) { return check_plain($states[$state]); } return check_plain($state); } -/** - * Implements hook_webform_component_info(). +/** + * Implements hook_webform_component_info(). */ function addressfield_tokens_webform_component_info() { $components = array(); @@ -387,6 +441,15 @@ function addressfield_tokens_webform_component_info() { return $components; } +/** + * Retrieves node components based on Node ID. + + * @param int $nid + * Node ID. + * + * @return mixed + * Components. + */ function _addressfield_tokens_webform_components($nid) { $components = &drupal_static(__FUNCTION__, array()); if (!isset($components[$nid])) { @@ -402,13 +465,14 @@ function _addressfield_tokens_webform_components($nid) { /** * Implements hook_webform_submission_load(). - */ + * Commented out to solve issue https://www.drupal.org/project/addressfield_tokens/issues/2674752 + * function addressfield_tokens_webform_submission_load(&$submissions) { $submissions_reset = reset($submissions); $nid = $submissions_reset->nid; - + $components = _addressfield_tokens_webform_components($nid); - + foreach ($submissions as $sid => $submission) { foreach ($components as $cid => $component) { if (!empty($submission->data[$cid])) { @@ -421,17 +485,40 @@ function addressfield_tokens_webform_submission_load(&$submissions) { $data = empty($data) ? array() : unserialize($data); $addresses[$delta] = $data; } - drupal_array_set_nested_value($submission->data, $parents, $addresses); + if (count($addresses)) { + drupal_array_set_nested_value($submission->data, $parents, $addresses); + } } } } } +**/ -/** - * Implements hook_webform_validator_alter(). +/** + * Implements hook_webform_validator_alter(). */ function addressfield_tokens_webform_validator_alter(&$validators) { $validators['unique']['component_types'][] = 'addressfield'; $validators['oneoftwo']['component_types'][] = 'addressfield'; $validators['oneofseveral']['component_types'][] = 'addressfield'; } + +/** + * Implements hook_webform_hints_element_alter(). + */ +function addressfield_tokens_webform_hints_element_alter(&$element, &$required_label) +{ + if ($element['#type'] == 'addressfield_container' || $element['#type'] == 'fieldset') { + $addressfield_tokens_fields_info = addressfield_tokens_field_formatter_info(); + foreach ($addressfield_tokens_fields_info['addressfield_components']['settings']['components'] as $component) { + if (isset($element[$component])) { + if (isset($element[$component]['#options'])) { + $element[$component]['#empty_option'] = '- ' . $element[$component]['#title'] . $required_label . ' -'; + } + + $element[$component]['#attributes']['placeholder'] = $element[$component]['#title'] . $required_label; + $element[$component]['#title_display'] = 'invisible'; + } + } + } +} diff --git a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.theme.inc b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.theme.inc index 74182dfc..16483671 100644 --- a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.theme.inc +++ b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.theme.inc @@ -11,7 +11,13 @@ */ function theme_addressfield_formatter($vars) { $address = $vars['address']; + if (isset($address['addressfield'])) { + $address = $address['addressfield']; + } $handlers = $vars['handlers']; + if (empty($handlers)) { + $handlers = array('address'); + } $out = addressfield_generate($address, $handlers, array('mode' => 'render')); return '
' . render($out) . '
'; @@ -39,7 +45,7 @@ function theme_addressfield_formatter__citystate($vars) { // If there's no location, render an alternate if (empty($out)) { - $out[] = 'Undefined'; + return ''; } // Render the location components @@ -56,6 +62,18 @@ function theme_addressfield_formatter__citystate($vars) { function theme_addressfield_formatter__linear($vars) { $loc = $vars['address']; + // If single line name is empty, construct it from first and last name. + if (empty($loc['name_line'])) { + $parts = array(); + if (!empty($loc['first_name'])) { + $parts[] = $loc['first_name']; + } + if (!empty($loc['last_name'])) { + $parts[] = $loc['last_name']; + } + $loc['name_line'] = join(' ', $parts); + } + // Determine which location components to render $out = array(); if (!empty($loc['name_line']) && $vars['name_line']) { @@ -103,9 +121,9 @@ function theme_addressfield_formatter__components($vars) { $out[$key] = _addressfield_tokens_country($loc['country']); } elseif ($key == 'administrative_area_full' && !empty($loc['country']) && !empty($loc['administrative_area'])) { - $out[$key] = _addressfield_tokens_state($loc['country'], $loc['administrative_area']); + $out[$key] = addressfield_tokens_state($loc['country'], $loc['administrative_area']); } } return implode($separator, $out); -} \ No newline at end of file +} diff --git a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.tokens.inc b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.tokens.inc index 9102af62..de6db03b 100644 --- a/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.tokens.inc +++ b/sites/all/modules/contrib/dev/addressfield_tokens/addressfield_tokens.tokens.inc @@ -1,36 +1,37 @@ t('Address field'), 'description' => t('An address associated with an entity.'), 'needs-data' => 'addressfield', ); - - // Add tokens for each component of the address - $info['tokens'] += array( 'addressfield' => array() ); - + + // Add tokens for each component of the address. + $info['tokens'] += array('addressfield' => array()); + $props = addressfield_data_property_info(); $names = addressfield_tokens_property_names(); $params = array( '@default_country' => addressfield_tokens_default_country(), ); - + foreach ($props as $field => $data) { $fieldtoken = str_replace('_', '-', $field); - + if (!empty($names[$field])) { $name = $names[$field]; $descr = $data['label']; @@ -38,7 +39,7 @@ function addressfield_tokens_token_info_alter(&$info) { else { $name = $data['label']; $descr = $name; - + $matches = array(); if (preg_match('/^(.*)\s+\(i\.e\.\s+(.*)\)$/', $name, $matches)) { $name = $matches[1]; @@ -54,7 +55,7 @@ function addressfield_tokens_token_info_alter(&$info) { } $info['tokens']['addressfield']['administrative-area']['name'] .= ' (abbreviation)'; $info['tokens']['addressfield']['country']['name'] .= ' (abbreviation)'; - + // Add tokens for the formatted address and text-only version. $info['tokens']['addressfield'] += array( 'full' => array( @@ -83,7 +84,7 @@ function addressfield_tokens_token_info_alter(&$info) { 'type' => 'text', ), ); - + // Add user tokens that are useful for MailChimp. if (module_exists('mailchimp')) { $info['tokens']['addressfield'] += array( @@ -95,9 +96,23 @@ function addressfield_tokens_token_info_alter(&$info) { ); } - // Attach tokens to all address fields + // Add extra text to webform submission values help. + if (array_key_exists('submission', $info['tokens'])) { + $info['tokens']['submission']['values']['description'] .= ' +
+ ' . t('For addressfield components you can also choose individual elements of the address using the syntax field_key:element, For example:') . ' + +
'; + } + + // Attach tokens to all address fields. $valid_types = entity_token_types(); - $entity_info = entity_get_info(); foreach ($valid_types as $token_type => $type) { foreach (entity_get_all_property_info($type) as $name => $property) { @@ -116,14 +131,6 @@ function addressfield_tokens_token_info_alter(&$info) { /** * Implements hook_tokens(). - * - * @param string $type The type of tokens to replace. We are looking for 'addressfield', but can also chain - * addressfields onto entities that have addressfields as properties. - * @param array $tokens The tokens to replace. - * @param array $data The data to use as replacements. We are looking for an 'addressfield' property. - * @param array $options Additional options for the tokenizer. - * - * @return array The replaced values. */ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array $options = array()) { $url_options = array(); @@ -140,27 +147,49 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array $replacements = array(); $last_original = NULL; - // Process address field tokens - if ($type == 'addressfield' && !empty($data['addressfield'])) { + // Process webform submission addressfield tokens. + if ($type == 'submission' && !empty($data['webform-submission'])) { + $submission = $data['webform-submission']; + $node = isset($data['node']) ? $data['node'] : node_load($submission->nid); + $value_tokens = token_find_with_prefix($tokens, 'values'); + // Loop through the components of the webform looking for addressfield + // components with the expected form_key. + foreach ($node->webform['components'] as $cid => $component) { + if ($component['type'] == 'addressfield' && isset($submission->data[$cid][0])) { + $address = $submission->data[$cid][0]; + if (is_string($address)) { + $address = unserialize($address); + } + $address_tokens = token_find_with_prefix($value_tokens, $component['form_key']); + foreach ($address_tokens as $token => $original) { + if (isset($address[$token])) { + $replacements[$original] = $sanitize ? filter_xss($address[$token]) : $address[$token]; + } + } + } + } + } + // Process address field tokens. + elseif ($type == 'addressfield' && !empty($data['addressfield'])) { foreach ($tokens as $name => $original) { $last_original = $original; $name = str_replace('-', '_', $name); $address = $data['addressfield']; - + // If the address field exists, use it. if (isset($address[$name])) { $replacements[$original] = $sanitize ? filter_xss($address[$name]) : $address[$name]; } else { - // Otherwise, it's a special token + // Otherwise, it's a special token. switch ($name) { case 'full': $render = addressfield_generate($address, array('address'), array( - 'mode' => 'render', + 'mode' => 'render', )); $replacements[$original] = $sanitize ? filter_xss(drupal_render($render)) : drupal_render($render); break; - + case 'text': $out = array(); if (!empty($address['thoroughfare'])) { @@ -182,7 +211,7 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array } $replacements[$original] = $sanitize ? filter_xss(implode("\n", $out)) : implode("\n", $out); break; - + case 'city_state': $out = array(); if (!empty($address['locality'])) { @@ -194,20 +223,20 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array if (!empty($address['country']) && $address['country'] != addressfield_tokens_default_country()) { $out[] = _addressfield_tokens_country($address['country']); } - $replacements[$original] = $sanitize ? filter_xss(implode(", ", $out)) : implode(", ", $out); + $replacements[$original] = $sanitize ? filter_xss(implode(", ", $out)) : implode(", ", $out); break; - + case 'state_name': if (!empty($address['administrative_area']) && !empty($address['country'])) { if ($sanitize) { - $replacements[$original] = filter_xss(_addressfield_tokens_state($address['country'], $address['administrative_area'])); + $replacements[$original] = filter_xss(addressfield_tokens_state($address['country'], $address['administrative_area'])); } else { - $replacements[$original] = _addressfield_tokens_state($address['country'], $address['administrative_area']); + $replacements[$original] = addressfield_tokens_state($address['country'], $address['administrative_area']); } } break; - + case 'country_name': if (!empty($address['country'])) { if ($sanitize) { @@ -218,16 +247,23 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array } } break; - + case 'mc_address': - $address_components = array('thoroughfare', 'premise', 'locality', 'administrative_area', 'postal_code', 'country'); + $address_components = array( + 'thoroughfare', + 'premise', + 'locality', + 'administrative_area', + 'postal_code', + 'country', + ); $mc_address = array(); foreach ($address_components as $component) { if (!empty($address[$component])) { $mc_address[] = check_plain($address[$component]); } } - // MailChimp requires the address to be a string of double-space + // MailChimp requires the address to be a string of double-space // delimited address fields. (http://kb.mailchimp.com/article/how-do-i-set-up-the-address-field-type-for-import) $replacements[$original] = !empty($mc_address) ? implode(' ', $mc_address) : ''; break; @@ -242,7 +278,7 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array $token_types = entity_token_types(); $info = token_info(); if (isset($info['tokens'][$type])) { - // Otherwise, chain address fields attached to other entities + // Otherwise, chain address fields attached to other entities. foreach ($info['tokens'][$type] as $name => $token_info) { if (isset($token_info['type']) && $token_info['type'] == 'addressfield') { if ($chained_tokens = token_find_with_prefix($tokens, $name)) { @@ -261,6 +297,6 @@ function addressfield_tokens_tokens($type, $tokens, array $data = array(), array } } } - + return $replacements; -} \ No newline at end of file +} diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.address_formats.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.address_formats.inc index 19e7958b..65aac347 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.address_formats.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.address_formats.inc @@ -3,7 +3,7 @@ /** * Contains the predefined address formats. * - * Derived from Google's dataset: https://i18napis.appspot.com/address. + * Derived from Google's dataset: https://chromium-i18n.appspot.com/ssl-address. */ /** @@ -40,12 +40,13 @@ function addressfield_get_address_format($country_code) { // These formats differ from the default only by the presence of the // postal code in 'used_fields'. $countries_with_optional_postal_code = array( - 'AC', 'AD', 'AL', 'AZ', 'BA', 'BB', 'BD', 'BG', 'BH', 'BM', 'BN', 'BT', - 'CR', 'CY', 'DO', 'DZ', 'EC', 'EH', 'ET', 'FO', 'GE', 'GN', 'GT', - 'GW', 'HR', 'HT', 'IL', 'IS', 'JO', 'KE', 'KG', 'KH', 'KW', 'LA', - 'LA', 'LB', 'LK', 'LR', 'LS', 'MA', 'MC', 'MD', 'ME', 'MG', 'MK', 'MM', - 'MT', 'MU', 'MV', 'NE', 'NP', 'OM', 'PK', 'PY', 'RO', 'RS', 'SA', 'SI', - 'SN', 'SZ', 'TA', 'TJ', 'TM', 'TN', 'VA', 'VC', 'VG', 'XK', 'ZM', + 'AC', 'AD', 'AF', 'AI', 'AL', 'AZ', 'BA', 'BB', 'BD', 'BG', 'BH', 'BM', + 'BN', 'BT', 'CU', 'CR', 'CY', 'DO', 'DZ', 'EC', 'EH', 'ET', 'FO', 'GE', + 'GN', 'GT', 'GW', 'HR', 'HM', 'HT', 'IL', 'IS', 'JO', 'KE', 'KG', 'KH', + 'KP', 'KW', 'LA', 'LB', 'LK', 'LR', 'LS', 'MA', 'MC', 'MD', 'ME', 'MG', + 'MK', 'MM', 'MT', 'MU', 'MV', 'NE', 'NP', 'OM', 'PK', 'PY', 'RO', 'RS', + 'SA', 'SD', 'SI', 'SN', 'SZ', 'TA', 'TJ', 'TM', 'TN', 'TZ', 'VA', 'VC', + 'VG', 'XK', 'ZM', ); foreach ($countries_with_optional_postal_code as $code) { $address_formats[$code] = array( @@ -71,6 +72,8 @@ function addressfield_get_address_format($country_code) { $address_formats['AE'] = array( 'used_fields' => array('administrative_area'), 'administrative_area_label' => t('Emirate'), + 'render_administrative_area_value' => TRUE, + 'required_fields' => array('administrative_area'), ); $address_formats['AM'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), @@ -114,7 +117,7 @@ function addressfield_get_address_format($country_code) { 'used_fields' => array('locality', 'administrative_area', 'postal_code'), ); $address_formats['CL'] = array( - 'used_fields' => array('dependent_locality', 'locality', 'administrative_area', 'postal_code'), + 'used_fields' => array('locality', 'administrative_area', 'postal_code'), 'administrative_area_label' => t('State', array(), array('context' => 'Territory of a country')), 'render_administrative_area_value' => TRUE, ); @@ -122,9 +125,11 @@ function addressfield_get_address_format($country_code) { 'used_fields' => array('dependent_locality', 'locality', 'administrative_area', 'postal_code'), 'required_fields' => array('locality', 'administrative_area'), 'dependent_locality_label' => t('District'), + 'render_administrative_area_value' => TRUE, ); $address_formats['CO'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), + 'required_fields' => array('locality', 'administrative_area'), 'administrative_area_label' => t('Department', array(), array('context' => 'Territory of a country')), ); $address_formats['CV'] = array( @@ -142,6 +147,7 @@ function addressfield_get_address_format($country_code) { 'used_fields' => array('locality', 'administrative_area', 'postal_code'), 'required_fields' => array('locality', 'postal_code'), 'administrative_area_label' => t('County'), + 'render_administrative_area_value' => TRUE, ); $address_formats['ES'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), @@ -155,7 +161,7 @@ function addressfield_get_address_format($country_code) { 'postal_code_label' => t('ZIP code'), ); $address_formats['GB'] = array( - 'used_fields' => array('locality', 'administrative_area', 'postal_code'), + 'used_fields' => array('locality', 'postal_code'), 'required_fields' => array('locality', 'postal_code'), 'locality_label' => t('Town/City'), 'administrative_area_label' => t('County'), @@ -165,8 +171,8 @@ function addressfield_get_address_format($country_code) { 'used_fields' => array('postal_code'), ); $address_formats['GU'] = array( - 'used_fields' => array('locality', 'administrative_area', 'postal_code'), - 'required_fields' => array('locality', 'administrative_area', 'postal_code'), + 'used_fields' => array('locality', 'postal_code'), + 'required_fields' => array('locality', 'postal_code'), 'administrative_area_label' => t('State', array(), array('context' => 'Territory of a country')), 'postal_code_label' => t('ZIP code'), ); @@ -182,13 +188,15 @@ function addressfield_get_address_format($country_code) { ); $address_formats['ID'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), + 'required_fields' => array('administrative_area'), 'locality_label' => t('City/Regency'), 'render_administrative_area_value' => TRUE, ); $address_formats['IE'] = array( - 'used_fields' => array('locality', 'administrative_area'), + 'used_fields' => array('dependent_locality', 'locality', 'administrative_area', 'postal_code'), 'locality_label' => t('Town/City'), 'administrative_area_label' => t('County'), + 'postal_code_label' => t('Eircode'), 'render_administrative_area_value' => TRUE, ); $address_formats['IN'] = array( @@ -293,7 +301,7 @@ function addressfield_get_address_format($country_code) { 'used_fields' => array('locality', 'administrative_area', 'postal_code'), ); $address_formats['NG'] = array( - 'used_fields' => array('locality', 'administrative_area', 'postal_code'), + 'used_fields' => array('dependent_locality', 'locality', 'administrative_area', 'postal_code'), 'administrative_area_label' => t('State', array(), array('context' => 'Territory of a country')), ); $address_formats['NI'] = array( @@ -330,6 +338,7 @@ function addressfield_get_address_format($country_code) { ); $address_formats['PH'] = array( 'used_fields' => array('dependent_locality', 'locality', 'administrative_area', 'postal_code'), + 'render_administrative_area_value' => TRUE, ); $address_formats['PR'] = array( 'used_fields' => array('locality', 'postal_code'), @@ -344,7 +353,7 @@ function addressfield_get_address_format($country_code) { ); $address_formats['RU'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), - 'required_fields' => array('locality', 'postal_code'), + 'required_fields' => array('locality', 'administrative_area', 'postal_code'), 'render_administrative_area_value' => TRUE, ); $address_formats['SC'] = array( @@ -389,7 +398,7 @@ function addressfield_get_address_format($country_code) { ); $address_formats['UA'] = array( 'used_fields' => array('locality', 'administrative_area', 'postal_code'), - 'required_fields' => array('locality', 'postal_code'), + 'required_fields' => array('locality', 'administrative_area', 'postal_code'), 'administrative_area_label' => t('Region', array(), array('context' => 'Territory of a country')), ); $address_formats['UM'] = array( diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.administrative_areas.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.administrative_areas.inc index aa6ebad6..a2eeaccb 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.administrative_areas.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.administrative_areas.inc @@ -132,7 +132,7 @@ function _addressfield_get_administrative_areas_defaults() { 'AT' => 'Atacama', 'BI' => 'Biobío', 'CO' => 'Coquimbo', - 'LI' => 'Libertador General Bernardo O\'Higgins', + 'LI' => "Libertador General Bernardo O'Higgins", 'LL' => 'Los Lagos', 'LR' => 'Los Ríos', 'MA' => 'Magallanes y de la Antártica Chilena', @@ -449,112 +449,112 @@ function _addressfield_get_administrative_areas_defaults() { 'AL' => 'Alessandria', 'AN' => 'Ancona', 'AO' => 'Aosta', - 'AP' => 'Ascoli Piceno', - 'AQ' => "L'Aquila", 'AR' => 'Arezzo', + 'AP' => 'Ascoli Piceno', 'AT' => 'Asti', 'AV' => 'Avellino', 'BA' => 'Bari', - 'BG' => 'Bergamo', - 'BI' => 'Biella', + 'BT' => 'Barletta-Andria-Trani', 'BL' => 'Belluno', 'BN' => 'Benevento', + 'BG' => 'Bergamo', + 'BI' => 'Biella', 'BO' => 'Bologna', - 'BR' => 'Brindisi', - 'BS' => 'Brescia', - 'BT' => 'Barletta-Andria-Trani', 'BZ' => 'Bolzano/Bozen', + 'BS' => 'Brescia', + 'BR' => 'Brindisi', 'CA' => 'Cagliari', - 'CB' => 'Campobasso', - 'CE' => 'Caserta', - 'CH' => 'Chieti', - 'CI' => 'Carbonia-Iglesias', 'CL' => 'Caltanissetta', - 'CN' => 'Cuneo', - 'CO' => 'Como', - 'CR' => 'Cremona', - 'CS' => 'Cosenza', + 'CB' => 'Campobasso', + 'CI' => 'Carbonia-Iglesias', + 'CE' => 'Caserta', 'CT' => 'Catania', 'CZ' => 'Catanzaro', + 'CH' => 'Chieti', + 'CO' => 'Como', + 'CS' => 'Cosenza', + 'CR' => 'Cremona', + 'KR' => 'Crotone', + 'CN' => 'Cuneo', 'EN' => 'Enna', - 'FC' => 'Forlì-Cesena', - 'FE' => 'Ferrara', - 'FG' => 'Foggia', - 'FI' => 'Firenze', 'FM' => 'Fermo', + 'FE' => 'Ferrara', + 'FI' => 'Firenze', + 'FG' => 'Foggia', + 'FC' => 'Forlì-Cesena', 'FR' => 'Frosinone', 'GE' => 'Genova', 'GO' => 'Gorizia', 'GR' => 'Grosseto', 'IM' => 'Imperia', 'IS' => 'Isernia', - 'KR' => 'Crotone', - 'LC' => 'Lecco', + 'AQ' => "L'Aquila", + 'SP' => 'La Spezia', + 'LT' => 'Latina', 'LE' => 'Lecce', + 'LC' => 'Lecco', 'LI' => 'Livorno', 'LO' => 'Lodi', - 'LT' => 'Latina', 'LU' => 'Lucca', - 'MB' => 'Monza e Brianza', 'MC' => 'Macerata', - 'ME' => 'Messina', - 'MI' => 'Milano', 'MN' => 'Mantova', - 'MO' => 'Modena', 'MS' => 'Massa-Carrara', 'MT' => 'Matera', + 'VS' => 'Medio Campidano', + 'ME' => 'Messina', + 'MI' => 'Milano', + 'MO' => 'Modena', + 'MB' => 'Monza e Brianza', 'NA' => 'Napoli', 'NO' => 'Novara', 'NU' => 'Nuoro', 'OG' => 'Ogliastra', - 'OR' => 'Oristano', 'OT' => 'Olbia-Tempio', - 'PA' => 'Palermo', - 'PC' => 'Piacenza', + 'OR' => 'Oristano', 'PD' => 'Padova', - 'PE' => 'Pescara', - 'PG' => 'Perugia', - 'PI' => 'Pisa', - 'PN' => 'Pordenone', - 'PO' => 'Prato', + 'PA' => 'Palermo', 'PR' => 'Parma', - 'PT' => 'Pistoia', - 'PU' => 'Pesaro e Urbino', 'PV' => 'Pavia', + 'PG' => 'Perugia', + 'PU' => 'Pesaro e Urbino', + 'PE' => 'Pescara', + 'PC' => 'Piacenza', + 'PI' => 'Pisa', + 'PT' => 'Pistoia', + 'PN' => 'Pordenone', 'PZ' => 'Potenza', + 'PO' => 'Prato', + 'RG' => 'Ragusa', 'RA' => 'Ravenna', 'RC' => 'Reggio Calabria', 'RE' => 'Reggio Emilia', - 'RG' => 'Ragusa', 'RI' => 'Rieti', - 'RM' => 'Roma', 'RN' => 'Rimini', + 'RM' => 'Roma', 'RO' => 'Rovigo', 'SA' => 'Salerno', - 'SI' => 'Siena', - 'SO' => 'Sondrio', - 'SP' => 'La Spezia', - 'SR' => 'Siracusa', 'SS' => 'Sassari', 'SV' => 'Savona', + 'SI' => 'Siena', + 'SR' => 'Siracusa', + 'SO' => 'Sondrio', 'TA' => 'Taranto', 'TE' => 'Teramo', - 'TN' => 'Trento', + 'TR' => 'Terni', 'TO' => 'Torino', 'TP' => 'Trapani', - 'TR' => 'Terni', - 'TS' => 'Trieste', + 'TN' => 'Trento', 'TV' => 'Treviso', + 'TS' => 'Trieste', 'UD' => 'Udine', 'VA' => 'Varese', + 'VE' => 'Venezia', 'VB' => 'Verbano-Cusio-Ossola', 'VC' => 'Vercelli', - 'VE' => 'Venezia', - 'VI' => 'Vicenza', 'VR' => 'Verona', - 'VS' => 'Medio Campidano', - 'VT' => 'Viterbo', 'VV' => 'Vibo Valentia', + 'VI' => 'Vicenza', + 'VT' => 'Viterbo', ); $administrative_areas['JM'] = array( '13' => 'Clarendon', @@ -663,11 +663,11 @@ function _addressfield_get_administrative_areas_defaults() { 'BCN' => 'Baja California', 'BCS' => 'Baja California Sur', 'CAM' => 'Campeche', + 'CMX' => 'Ciudad de México', 'COA' => 'Coahuila', 'COL' => 'Colima', 'CHP' => 'Chiapas', 'CHH' => 'Chihuahua', - 'DIF' => 'Distrito Federal', 'DUG' => 'Durango', 'MEX' => 'Estado de México', 'GUA' => 'Guanajuato', @@ -709,7 +709,7 @@ function _addressfield_get_administrative_areas_defaults() { '13' => t('Sarawak'), '10' => t('Selangor'), '11' => t('Terengganu'), - ); + ); $administrative_areas['PE'] = array( 'AMA' => 'Amazonas', 'ANC' => 'Ancash', @@ -737,6 +737,90 @@ function _addressfield_get_administrative_areas_defaults() { 'TUM' => 'Tumbes', 'UCA' => 'Ucayali', ); + $administrative_areas['PH'] = array( + 'ABR' => 'Abra', + 'AGN' => 'Agusan del Norte', + 'AGS' => 'Agusan del Sur', + 'AKL' => 'Aklan', + 'ALB' => 'Albay', + 'ANT' => 'Antique', + 'APA' => 'Apayao', + 'AUR' => 'Aurora', + 'BAS' => 'Basilan', + 'BAN' => 'Bataan', + 'BTN' => 'Batanes', + 'BTG' => 'Batangas', + 'BEN' => 'Benguet', + 'BIL' => 'Biliran', + 'BOH' => 'Bohol', + 'BUK' => 'Bukidnon', + 'BUL' => 'Bulacan', + 'CAG' => 'Cagayan', + 'CAN' => 'Camarines Norte', + 'CAS' => 'Camarines Sur', + 'CAM' => 'Camiguin', + 'CAP' => 'Capiz', + 'CAT' => 'Catanduanes', + 'CAV' => 'Cavite', + 'CEB' => 'Cebu', + 'COM' => 'Compostela Valley', + 'NCO' => 'Cotabato', + 'DAV' => 'Davao del Norte', + 'DAS' => 'Davao del Sur', + 'a9d' => 'Davao Occidental', + 'DAO' => 'Davao Oriental', + 'DIN' => 'Dinagat Islands', + 'EAS' => 'Eastern Samar', + 'GUI' => 'Guimaras', + 'IFU' => 'Ifugao', + 'ILN' => 'Ilocos Norte', + 'ILS' => 'Ilocos Sur', + 'ILI' => 'Iloilo', + 'ISA' => 'Isabela', + 'KAL' => 'Kalinga', + 'LUN' => 'La Union', + 'LAG' => 'Laguna', + 'LAN' => 'Lanao del Norte', + 'LAS' => 'Lanao del Sur', + 'LEY' => 'Leyte', + 'MAG' => 'Maguindanao', + 'MAD' => 'Marinduque', + 'MAS' => 'Masbate', + '00' => 'Metro Manila', + 'MDC' => 'Mindoro Occidental', + 'MDR' => 'Mindoro Oriental', + 'MSC' => 'Misamis Occidental', + 'MSR' => 'Misamis Oriental', + 'MOU' => 'Mountain Province', + 'NEC' => 'Negros Occidental', + 'NER' => 'Negros Oriental', + 'NSA' => 'Northern Samar', + 'NUE' => 'Nueva Ecija', + 'NUV' => 'Nueva Vizcaya', + 'PLW' => 'Palawan', + 'PAM' => 'Pampanga', + 'PAN' => 'Pangasinan', + 'QUE' => 'Quezon Province', + 'QUI' => 'Quirino', + 'RIZ' => 'Rizal', + 'ROM' => 'Romblon', + 'WSA' => 'Samar', + 'SAR' => 'Sarangani', + 'SIG' => 'Siquijor', + 'SOR' => 'Sorsogon', + 'SCO' => 'South Cotabato', + 'SLE' => 'Southern Leyte', + 'SUK' => 'Sultan Kudarat', + 'SLU' => 'Sulu', + 'SUN' => 'Surigao del Norte', + 'SUR' => 'Surigao del Sur', + 'TAR' => 'Tarlac', + 'TAW' => 'Tawi-Tawi', + 'ZMB' => 'Zambales', + 'ZAN' => 'Zamboanga del Norte', + 'ZAS' => 'Zamboanga del Sur', + 'ZSI' => 'Zamboanga Sibuguey', + ); $administrative_areas['RU'] = array( 'MOW' => t('Moskva'), 'SPE' => t('Sankt-Peterburg'), @@ -931,31 +1015,31 @@ function _addressfield_get_administrative_areas_defaults() { ); $administrative_areas['UA'] = array( '43' => t('Crimea'), - '05' => t('Vinnyts\'ka oblast'), - '07' => t('Volyns\'ka oblast'), + '05' => t("Vinnyts'ka oblast"), + '07' => t("Volyns'ka oblast"), '12' => t('Dnipropetrovsk Oblast'), '14' => t('Donetsk Oblast'), - '18' => t('Zhytomyrs\'ka oblast'), - '21' => t('Zakarpats\'ka oblast'), - '23' => t('Zaporiz\'ka oblast'), - '26' => t('Ivano-Frankivs\'ka oblast'), - '30' => t('Kiev Oblast'), - '35' => t('Kirovohrads\'ka oblast'), - '09' => t('Luhans\'ka oblast'), + '18' => t("Zhytomyrs'ka oblast"), + '21' => t("Zakarpats'ka oblast"), + '23' => t("Zaporiz'ka oblast"), + '26' => t("Ivano-Frankivs'ka oblast"), + '30' => t('Kyiv Oblast'), + '35' => t("Kirovohrads'ka oblast"), + '09' => t("Luhans'ka oblast"), '46' => t('Lviv Oblast'), - '48' => t('Mykolaivs\'ka oblast'), + '48' => t("Mykolaivs'ka oblast"), '51' => t('Odessa Oblast'), - '53' => t('Poltavs\'ka oblast'), - '56' => t('Rivnens\'ka oblast'), - '40' => t('Sevastopol\' city'), - '59' => t('Sums\'ka oblast'), - '61' => t('Ternopil\'s\'ka oblast'), + '53' => t("Poltavs'ka oblast"), + '56' => t("Rivnens'ka oblast"), + '40' => t("Sevastopol' city"), + '59' => t("Sums'ka oblast"), + '61' => t("Ternopil's'ka oblast"), '63' => t('Kharkiv Oblast'), - '65' => t('Khersons\'ka oblast'), - '68' => t('Khmel\'nyts\'ka oblast'), - '71' => t('Cherkas\'ka oblast'), - '77' => t('Chernivets\'ka oblast'), - '74' => t('Chernihivs\'ka oblast'), + '65' => t("Khersons'ka oblast"), + '68' => t("Khmel'nyts'ka oblast"), + '71' => t("Cherkas'ka oblast"), + '77' => t("Chernivets'ka oblast"), + '74' => t("Chernihivs'ka oblast"), ); $administrative_areas['US'] = array( 'AL' => t('Alabama'), diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.devel_generate.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.devel_generate.inc index 2eb9c41a..f72daccb 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.devel_generate.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.devel_generate.inc @@ -41,9 +41,9 @@ function _addressfield_sample_addresses() { if (!isset($fields)) { $filepath = DRUPAL_ROOT . '/' . drupal_get_path('module', 'addressfield'); $fields = array(); - if ($handle = @fopen("$filepath/addresses.txt",'r')) { + if ($handle = @fopen("$filepath/addresses.txt", 'r')) { if (is_resource($handle)) { - while (($buffer = fgets($handle)) !== false) { + while (($buffer = fgets($handle)) !== FALSE) { list($country, $administrative_area, $sub_administrative_area, $locality, $dependent_locality, $postal_code, $thoroughfare, $premise, $sub_premise) = explode("\t", $buffer); $fields[] = array( 'country' => ($country == 'NULL') ? NULL : trim($country), diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.feeds.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.feeds.inc index 062b221f..695f838d 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.feeds.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.feeds.inc @@ -36,10 +36,20 @@ function addressfield_feeds_processor_targets_alter(&$targets, $entity_type, $bu * A string identifying the target on the node. * @param $values * The value to populate the target with. + * @param array $mapping + * Associative array of the mapping settings from the per mapping + * configuration form. */ -function addressfield_set_target($source, $entity, $target, $values) { +function addressfield_set_target($source, $entity, $target, $values, $mapping) { + $language = $mapping['language']; list($field_name, $sub_field) = explode(':', $target, 2); + // Field info and instance are required for setting default values. + $entity_type = $source->importer->processor->entityType(); + list(, , $bundle_name) = entity_extract_ids($entity_type, $entity); + $info = field_info_field($field_name); + $instance = field_info_instance($entity_type, $field_name, $bundle_name); + // Convert the values into an array if it isn't one already to correspond to // Drupal's handling of field value arrays. if (!is_array($values)) { @@ -48,12 +58,16 @@ function addressfield_set_target($source, $entity, $target, $values) { // If the field is already set on the given entity, update the existing value // array. Otherwise start with a fresh field value array. - $field = isset($entity->$field_name) ? $entity->$field_name : array(); + $field = isset($entity->{$field_name}) ? $entity->{$field_name} : array(); // Loop over the field values array... foreach ($values as $delta => $value) { - $field[LANGUAGE_NONE][$delta][$sub_field] = $value; + // Set defaults for new values. + if (!isset($field[$language][$delta])) { + $field[$language][$delta] = addressfield_default_values($info, $instance); + } + $field[$language][$delta][$sub_field] = $value; } - $entity->$field_name = $field; + $entity->{$field_name} = $field; } diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.info b/sites/all/modules/contrib/fields/addressfield/addressfield.info index 89e95157..3ed18f06 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.info +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.info @@ -10,9 +10,8 @@ files[] = views/addressfield_views_handler_field_administrative_area.inc files[] = views/addressfield_views_handler_field_country.inc files[] = views/addressfield_views_handler_filter_country.inc -; Information added by Drupal.org packaging script on 2015-10-07 -version = "7.x-1.2" +; Information added by Drupal.org packaging script on 2018-10-26 +version = "7.x-1.3" core = "7.x" project = "addressfield" -datestamp = "1444254070" - +datestamp = "1540579391" diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.migrate.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.migrate.inc index cc98911c..f88536bb 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.migrate.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.migrate.inc @@ -5,6 +5,11 @@ * Base integration with the Migrate API class. */ +// Avoid issues when migrate module is disabled. +if (!class_exists('MigrateFieldHandler')) { + return; +} + /** * Implements hook_migrate_api(). */ diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.module b/sites/all/modules/contrib/fields/addressfield/addressfield.module index 25b277dc..bf0bf701 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.module +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.module @@ -52,6 +52,37 @@ function addressfield_module_implements_alter(&$implementations, $hook) { } } +/** + * Returns a list of address fields optionally filtered by entity type. + * + * @param string $entity_type + * Optional machine-name of an entity type to filter the returned array by. + * + * @return array + * An array of address field mapping data. + */ +function addressfield_get_address_fields($entity_type = '') { + $fields = &drupal_static(__FUNCTION__ . '_' . $entity_type); + + if (isset($fields)) { + return $fields; + } + + // Get mapping data for all address fields. + $fields = array_filter(field_info_field_map(), 'addressfield_field_map_filter'); + + // Filter the list of fields by entity type if specified. + if (!empty($fields) && !empty($entity_type)) { + foreach ($fields as $field_name => $field) { + if (!isset($field['bundles'][$entity_type])) { + unset($fields[$field_name]); + } + } + } + + return $fields; +} + /** * Returns TRUE if a field map array value represents an addressfield. * @@ -305,7 +336,14 @@ function theme_addressfield_container($variables) { if (strlen($element['#children']) > 0) { $output = '<' . $element['#tag'] . drupal_attributes($element['#attributes']) . '>'; $output .= $element['#children']; - $output .= '"; + $output .= ''; + // Add a linebreak to the HTML after a div. This is invisible on the + // rendered page but improves the appearance of address field output when + // HTML tags are stripped, such as by Views Data Export. + if ($element['#tag'] == 'div') { + $output .= PHP_EOL; + } + return $output; } else { @@ -446,7 +484,7 @@ function addressfield_field_presave($entity_type, $entity, $field, $instance, $l // spaces to single spaces. foreach ($item as $key => &$value) { if (!in_array($key, array('data')) && is_string($value)) { - $value = trim(str_replace(' ', ' ', $value)); + $value = trim(preg_replace('/[[:blank:]]{2,}/u', ' ', $value)); } } } diff --git a/sites/all/modules/contrib/fields/addressfield/addressfield.tokens.inc b/sites/all/modules/contrib/fields/addressfield/addressfield.tokens.inc index 1c91e531..5c325f0d 100644 --- a/sites/all/modules/contrib/fields/addressfield/addressfield.tokens.inc +++ b/sites/all/modules/contrib/fields/addressfield/addressfield.tokens.inc @@ -89,11 +89,13 @@ function addressfield_token_info() { */ function addressfield_token_info_alter(&$data) { // Loop over every address field on the site. - foreach (array_filter(field_info_field_map(), 'addressfield_field_map_filter') as $field_name => $field) { - foreach ($data['tokens'] as $group => $token){ - if (isset($data['tokens'][$group][$field_name]) && is_array($data['tokens'][$group][$field_name])) { - // Set the token type for the field to use the addressfield child tokens. - $data['tokens'][$group][$field_name]['type'] = 'address-field'; + foreach (addressfield_get_address_fields() as $field_name => $field) { + foreach (array($field_name, strtr($field_name, '_', '-')) as $name) { + foreach ($data['tokens'] as $group => $token) { + if (isset($data['tokens'][$group][$name]) && is_array($data['tokens'][$group][$name])) { + // Set the token type for the field to use the addressfield child tokens. + $data['tokens'][$group][$name]['type'] = 'address-field'; + } } } } @@ -212,19 +214,27 @@ function addressfield_tokens($type, $tokens, array $data = array(), array $optio // and helps us avoid having to do the entity detection ourselves. if ($type == 'entity') { // Loop over the address fields defined on the site. - foreach (array_filter(field_info_field_map(), 'addressfield_field_map_filter') as $field_name => $field) { - // If there are any address field tokens in the token list... - if ($addressfield_tokens = token_find_with_prefix($tokens, $field_name)) { - // If the current field is on the matching entity type... - if (!empty($field['bundles'][$data['entity_type']])) { - // Extract the format handlers selected in a representative instance - // settings form for use in formatting tokens. - $instance = field_info_instance($data['entity_type'], $field_name, reset($field['bundles'][$data['entity_type']])); - $format_handlers = $instance['widget']['settings']['format_handlers']; + foreach (addressfield_get_address_fields($data['entity_type']) as $field_name => $field) { + // If the current field is on the matching entity type... + if (!empty($field['bundles'][$data['entity_type']])) { + // Extract the format handlers selected in a representative instance + // settings form for use in formatting tokens. + $instance = field_info_instance($data['entity_type'], $field_name, reset($field['bundles'][$data['entity_type']])); + $format_handlers = $instance['widget']['settings']['format_handlers']; + } + + foreach (array($field_name, strtr($field_name, '_', '-')) as $prefix) { + // If there are any address field tokens in the token list... + $addressfield_tokens = token_find_with_prefix($tokens, $prefix); + + if (!$addressfield_tokens) { + continue; } - // Generate the necessary address field tokens for the entity. - $replacements += token_generate('address-field', $addressfield_tokens, array('address-field' => $data['entity']->$field_name, 'format_handlers' => $format_handlers), $options); + if (property_exists($data['entity'], $field_name)) { + // Generate the necessary address field tokens for the entity. + $replacements += token_generate('address-field', $addressfield_tokens, array('address-field' => $data['entity']->$field_name, 'format_handlers' => $format_handlers), $options); + } } } } diff --git a/sites/all/modules/contrib/fields/addressfield/example/addressfield_example.info b/sites/all/modules/contrib/fields/addressfield/example/addressfield_example.info index b0f19829..a5dea64c 100644 --- a/sites/all/modules/contrib/fields/addressfield/example/addressfield_example.info +++ b/sites/all/modules/contrib/fields/addressfield/example/addressfield_example.info @@ -7,9 +7,8 @@ hidden = TRUE dependencies[] = ctools dependencies[] = addressfield -; Information added by Drupal.org packaging script on 2015-10-07 -version = "7.x-1.2" +; Information added by Drupal.org packaging script on 2018-10-26 +version = "7.x-1.3" core = "7.x" project = "addressfield" -datestamp = "1444254070" - +datestamp = "1540579391" diff --git a/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-administrative-area.inc b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-administrative-area.inc new file mode 100644 index 00000000..eb3be37b --- /dev/null +++ b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-administrative-area.inc @@ -0,0 +1,24 @@ + t('Hide the administrative area'), + 'format callback' => 'addressfield_format_address_hide_administrative_area', + 'type' => 'address', + 'weight' => -84, +); + +/** + * Format callback. + * + * @see CALLBACK_addressfield_format_callback() + */ +function addressfield_format_address_hide_administrative_area(&$format, $address, $context = array()) { + if (isset($format['locality_block']['administrative_area'])) { + $format['locality_block']['administrative_area']['#access'] = FALSE; + } +} diff --git a/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-country.inc b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-country.inc index 13ebd1cb..59881fb8 100644 --- a/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-country.inc +++ b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-country.inc @@ -20,7 +20,7 @@ $plugin = array( function addressfield_format_address_hide_country(&$format, $address, $context = array()) { // Hide the country element only if the whole field is required, otherwise // there will always be an additional None option. - if ($context['mode'] == 'form' && $context['instance']['required']) { + if ($context['mode'] == 'form' && (empty($context['instance']) || $context['instance']['required'])) { if (!empty($format['country']['#options']) && count($format['country']['#options']) == 1) { $format['country']['#access'] = FALSE; } diff --git a/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-locality.inc b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-locality.inc new file mode 100644 index 00000000..1e380025 --- /dev/null +++ b/sites/all/modules/contrib/fields/addressfield/plugins/format/address-hide-locality.inc @@ -0,0 +1,24 @@ + t('Hide the locality'), + 'format callback' => 'addressfield_format_address_hide_locality', + 'type' => 'address', + 'weight' => -84, +); + +/** + * Format callback. + * + * @see CALLBACK_addressfield_format_callback() + */ +function addressfield_format_address_hide_locality(&$format, $address, $context = array()) { + if (isset($format['locality_block']['locality'])) { + $format['locality_block']['locality']['#access'] = FALSE; + } +} diff --git a/sites/all/modules/contrib/fields/addressfield/plugins/format/address.inc b/sites/all/modules/contrib/fields/addressfield/plugins/format/address.inc index e9b801f1..ca354d57 100644 --- a/sites/all/modules/contrib/fields/addressfield/plugins/format/address.inc +++ b/sites/all/modules/contrib/fields/addressfield/plugins/format/address.inc @@ -240,7 +240,12 @@ function addressfield_format_address_generate(&$format, $address, $context = arr if (in_array($address['country'], $countries_postal_code_after_locality)) { // Take the widget out of the array. $postal_code_widget = $format['locality_block']['postal_code']; - $postal_code_widget['#prefix'] = ' '; + + // If the postal code not in its own row, add a separating space. + if (empty($postal_code_widget['#tag'])) { + $postal_code_widget['#prefix'] = ' '; + } + unset($format['locality_block']['postal_code']); // Add it back. diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/README.txt b/sites/all/modules/contrib/fields/autocomplete_deluxe/README.txt old mode 100644 new mode 100755 diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.api.php b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.api.php old mode 100644 new mode 100755 index 29d26f5e..80026c67 --- a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.api.php +++ b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.api.php @@ -1,5 +1,4 @@ 'a', 2 => - * 'b', 3 => 'c'). + * - #autocomplete_options needs an array in the form of an array (similar to + * #options in core for selects or checkboxes): array('a', 'b', 'c') or + * array(1 => 'a', 2 => 'b', 3 => 'c'). * - * Besides this two, there are three other options, wich autocomplete deluxe + * Besides these two, there are four other options which autocomplete deluxe * accepts: * - #multiple Indicates whether the user may select more than one item. Expects * TRUE or FALSE, by default it is set to FALSE. - * - #autocomplete_multiple_delimiter If #multiple is TRUE, then you can use - * this option to set a seperator for multiple values. By default a string - * with the follwing content will be used: ', '. - * - #autocomplete_min_length Indicates how many characters must be entered - * until, the suggesion list can be opened. Especially helpfull, when your + * - #delimiter If #multiple is TRUE, then you can use this option to set a + * seperator for multiple values. By default a string with the following + * content will be used: ', '. + * - #min_length Indicates how many characters must be entered + * until, the suggesion list can be opened. Especially helpful, when your * ajax callback returns only valid suggestion for a minimum characters. * The default is 0. + * - #not_found_message A message text which will be displayed, if the entered + * term was not found. */ function somefunction() { switch ($type) { @@ -38,16 +39,18 @@ function somefunction() { '#type' => 'autocomplete_deluxe', '#autocomplete_options' => $options, '#multiple' => FALSE, - '#autocomplete_min_length' => 0, + '#min_length' => 0, ); break; + case 'ajax': $element = array( '#type' => 'autocomplete_deluxe', '#autocomplete_deluxe_path' => url('some_uri', array('absolute' => TRUE)), '#multiple' => TRUE, - '#autocomplete_min_length' => 1, - '#autocomplete_multiple_delimiter' => '|', + '#min_length' => 1, + '#delimiter' => '|', + '#not_found_message' => "The term '@term' will be added.", ); break; } diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.css b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.css old mode 100644 new mode 100755 diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info index 42af1bb4..9e31eb7c 100644 --- a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info +++ b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info @@ -5,9 +5,9 @@ core = 7.x files[] = autocomplete_deluxe.module dependencies[] = taxonomy -; Information added by Drupal.org packaging script on 2017-01-11 -version = "7.x-2.2" +; Information added by Drupal.org packaging script on 2017-07-25 +version = "7.x-2.3" core = "7.x" project = "autocomplete_deluxe" -datestamp = "1484128687" +datestamp = "1501005546" diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js old mode 100644 new mode 100755 diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.module b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.module old mode 100644 new mode 100755 diff --git a/sites/all/modules/contrib/localisation/entity_translation/CHANGELOG.txt b/sites/all/modules/contrib/localisation/entity_translation/CHANGELOG.txt index de210110..1b4d667b 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/CHANGELOG.txt +++ b/sites/all/modules/contrib/localisation/entity_translation/CHANGELOG.txt @@ -1,9 +1,83 @@ Entity Translation 7.x-1.x, xxxx-xx-xx -------------------------------------- -#2189567 by stefanos.petrakis, jmuzz: Fixed problems enabling and disabling translation on - a field with revisions enabled. -#2798721 by gnucifer: Path scheme not initialized on delete translation confirmation form. +#3025770 by sudheeshps, patelmayank7552, stefanos.petrakis: PHP 7.0 + Compatibility +#2536292 by plopesc, stefanos.petrakis: "Warning: array_merge(): Argument #2 is + not an array in entity_translation_menu_alter" When 'page arguments' or + 'access arguments' are not defined in the original item +#2921298 by Stevel, stefanos.petrakis: Missing test dependencies + + +Entity Translation 7.x-1.0, 2018-04-01 +-------------------------------------- +(no change) + + +Entity Translation 7.x-1.0-rc1, 2018-03-21 +------------------------------------------ +#2927815 by Skabbkladden, dawehner: Infinite loop with language neutral alias + and pathauto. +#2890683 by tobiberlin, stefanos.petrakis: entity_translation_field_attach_form() + adding unwanted fields to form. +#2907366 by swati.nuna: Invalid hook hook_translation_info() mentioned in + docblock for entity_translation_edit_form_info(). +#1799770 by plach, bforchhammer: Update id and bundle when setting a wrapped + entity. +#2339315 by plach: Added documentation for + hook_entity_translation_source_field_state_alter(). +#1506054 by plach, Owen Barton: Taxonomy term reference: language-aware widget + and autocomplete. +#2907275 by jalpesh: CSS class name misspelled in entity_translation_overview(). + + +Entity Translation 7.x-1.0-beta7, 2017-08-21 +-------------------------------------------- +#2903195 by stefanos.petrakis, BAHbKA, plach: Enabling translation for not + empty taxonomy vocabulary. +#2425825 by jamesrward: Update from before beta4 fails. +#2900094 by joseph.olstad: code sniffer drupal.org recommended code syntax + fixes. +#2883805 by mikran: entity_translation_update_7008 is broken when taxonomy + module is not enabled. +#2877074 by plach, stefanos.petrakis, joseph.olstad: Refactor the + entity_translation_language() callback to make it bundle-specific. +#2743685 by stefanos.petrakis, bwaindwain: Pathauto update for all translations + for a single node. +#2899658 by joseph.olstad, stefanos.petrakis: entity_translation_upgrade_do + needs to automatically create the entity_translation row for the source + language in entity_translation. +#1800158 by meichr: Entity Translation Upgrade, drush extension. +#2885858 by StephaneQ: Can't delete taxonomy term translation since beta6 + update. +#2572203 by mattew: Wrong query generated when several Translations + relationships are used. +#2824255 by ccarrascal, plach: Notice: Undefined index for language in + setTranslation(). +#2750179 by wadmiraal: Allowed default translation handler to be completely + overridden. +#2307937 by meichr, joseph.olstad: Batch API needs $context['results'] handled + as an array, not a value. +#1175170 by hgoto, Pisco, alberto56: Optionally enable disabled languages for + entity translation. +#2870524 by stefanos.petrakis, joseph.olstad: Field copy fails with content + translation for fields with entity translation enabled. + + +Entity Translation 7.x-1.0-beta6, 2017-03-03 +-------------------------------------------- +#2849464 by plach, czigor, stefanos.petrakis: Added an API to set the active + language. +#2438615 by David_Rothstein, matthiasm11: New nodes are always created using + LANGUAGE_NONE (only changed to the correct language during form submission). +#2820454 by Dylan Donkersgoed: PHP notice when attaching single field + with field_attach_form. +#2826297 by Thomas Cys, dwebpoint, stefanos.petrakis: 'clone' is a reserved + keyword introduced in PHP version 5.0 and cannot be invoked as a function. +#2189567 by stefanos.petrakis, jmuzz: Fixed problems enabling and disabling + translation on a field with revisions enabled. +#2798721 by gnucifer: Path scheme not initialized on delete translation + confirmation form. #2215771 by colan, stefanos.petrakis: Fixed "Undefined index: translate in EntityTranslationDefaultHandler->entityForm()". #1829636 by bforchhammer, stefanos.petrakis: Fixed "All languages" suffix not diff --git a/sites/all/modules/contrib/localisation/entity_translation/MAINTAINERS.txt b/sites/all/modules/contrib/localisation/entity_translation/MAINTAINERS.txt index f5aa1df0..12b879d9 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/MAINTAINERS.txt +++ b/sites/all/modules/contrib/localisation/entity_translation/MAINTAINERS.txt @@ -9,8 +9,9 @@ Project maintainers The Entity translation maintainers oversee the development of the project as a whole. The project maintainers for Entity translation are: -- Francesco Placella 'plach' -- Daniel F. Kudwien 'sun' +- Francesco Placella 'plach' +- Daniel F. Kudwien 'sun' +- Stefanos Petrakis 'stefanos.petrakis' Component maintainers @@ -25,14 +26,15 @@ http://drupal.org/node/363367 to find out how to become a component maintainer. Current component maintainers for Entity translation: Base system -- Francesco Placella 'plach' -- Benedikt Forchhammer 'bforchhammer' +- Francesco Placella 'plach' +- Benedikt Forchhammer 'bforchhammer' +- Stefanos Petrakis 'stefanos.petrakis' Menu integration -- Benedikt Forchhammer 'bforchhammer' +- Benedikt Forchhammer 'bforchhammer' Views integration -- Fabian Sörqvist 'fabsor' +- Fabian Sörqvist 'fabsor' Node translation upgrade -- Francesco Placella 'plach' +- Francesco Placella 'plach' diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.admin.inc b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.admin.inc index b3f93057..add6bd96 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.admin.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.admin.inc @@ -18,6 +18,13 @@ function entity_translation_admin_form($form, $form_state) { '#default_value' => variable_get('locale_field_language_fallback', TRUE), ); + $form['entity_translation_languages_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Use only enabled languages'), + '#description' => t('If checked, disabled languages will not show up as available languages. This setting does not apply to content types that are configured to use the Multilingual content (i18n_node) module as this module provides its own configuration.'), + '#default_value' => variable_get('entity_translation_languages_enabled', FALSE), + ); + $form['entity_translation_show_fallback_on_overview_pages'] = array( '#type' => 'checkbox', '#title' => t('Show fallback statuses on overview pages'), @@ -45,7 +52,7 @@ function entity_translation_admin_form($form, $form_state) { ); $_null = NULL; - list($items, ) = menu_router_build(); + list($items,) = menu_router_build(); _entity_translation_validate_path_schemes($_null, FALSE, $items); foreach (entity_get_info() as $entity_type => $info) { @@ -316,7 +323,7 @@ function entity_translation_overview($entity_type, $entity, $callback = NULL) { $link = isset($add_links->links[$langcode]['href']) ? $add_links->links[$langcode] : array('href' => $add_path, 'language' => $language); $link['query'] = isset($_GET['destination']) ? drupal_get_destination() : FALSE; $options[] = $translatable ? l(t('add'), $link['href'], $link) : t('No translatable fields'); - $classes[] = $translatable ? '' : 'non-traslatable'; + $classes[] = $translatable ? '' : 'non-translatable'; } $status = t('Not translated'); // Show fallback information if required. @@ -389,7 +396,7 @@ function _entity_translation_label($entity_type, $entity, $langcode = NULL) { /** * Theme wrapper for the entity translation language page. */ -function theme_entity_translation_overview($variables){ +function theme_entity_translation_overview($variables) { $rows = $variables['rows']; return theme('table', array( 'rows' => $rows, @@ -400,7 +407,7 @@ function theme_entity_translation_overview($variables){ /** * Theme wrapper for the entity translation language outdated translation. */ -function theme_entity_translation_overview_outdated($variables){ +function theme_entity_translation_overview_outdated($variables) { $message = $variables['message']; return ' - ' . $message . ''; } @@ -410,7 +417,7 @@ function theme_entity_translation_overview_outdated($variables){ */ function entity_translation_delete_confirm($form, $form_state, $entity_type, $entity, $langcode) { $handler = entity_translation_get_handler($entity_type, $entity); - $handler->setFormLanguage($langcode); + $handler->setActiveLanguage($langcode); $handler->initPathScheme(); $languages = language_list(); @@ -452,7 +459,7 @@ function entity_translation_delete_confirm_submit($form, &$form_state) { $form_state['redirect'] = $handler->getTranslatePath(); } -/* +/** * Confirm form for changing field translatability. */ function entity_translation_translatable_form($form, &$form_state, $field_name) { @@ -547,7 +554,7 @@ function entity_translation_translatable_form_submit($form, $form_state) { batch_set($batch); } -/* +/** * Toggle translatability of the given field. * * This is called from a batch operation, but should only run once per field. @@ -602,12 +609,28 @@ function entity_translation_translatable_batch($translatable, $field_name, $copy ->range($offset, $limit) ->execute(); - foreach ($result as $entity_type => $revisions) { - foreach ($revisions as $revision) { - // $revision is a partial entity object that will be used as an array of - // conditions. - $conditions = (array) $revision; - $entity = reset(entity_load($entity_type, FALSE, $conditions)); + foreach ($result as $entity_type => $partial_entities) { + + // Load all revisionable entities' revisions. + if (EntityTranslationDefaultHandler::isEntityTypeRevisionable($entity_type)) { + $entities = array(); + // Extract the revision identifier from the entity's definition. + $entity_info = entity_get_info($entity_type); + $revision_id_key = $entity_info['entity keys']['revision']; + // Load each revisionable entity's revision using $conditions, which + // should include the revision id information. + foreach ($partial_entities as $partial_entity) { + $conditions = (array) $partial_entity; + $revision_condition = array_intersect_key($conditions, array($revision_id_key => $revision_id_key)); + $entity_revisions = entity_load($entity_type, FALSE, $revision_condition); + $entities[] = reset($entity_revisions); + } + } + else { + $entities = entity_load($entity_type, array_keys($partial_entities)); + } + + foreach ($entities as $entity) { $context['sandbox']['progress']++; $handler = entity_translation_get_handler($entity_type, $entity); $langcode = $handler->getLanguage(); @@ -626,9 +649,10 @@ function entity_translation_translatable_batch($translatable, $field_name, $copy if ($translatable && isset($entity->{$field_name}[LANGUAGE_NONE])) { // If the field is being switched to translatable and has data for // LANGUAGE_NONE then we need to move the data to the right language. - + // In case the 'Copy translations' option was selected, move the + // available LANGUAGE_NONE field data into all existing translation + // languages, otherwise only into the entity's language. $translations = $handler->getTranslations(); - if ($copy_all_languages && !empty($translations->data)) { foreach ($translations->data as $translation) { $entity->{$field_name}[$translation['language']] = $entity->{$field_name}[LANGUAGE_NONE]; diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.api.php b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.api.php index 2eb8262d..f8891bdc 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.api.php +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.api.php @@ -164,3 +164,17 @@ function hook_entity_translation_delete($entity_type, $entity, $langcode) { */ function hook_entity_translation_delete_revision($entity_type, $entity, $langcode) { } + +/** + * Allows to sets the right values in the form state when adding a translation. + */ +function hook_entity_translation_source_field_state_alter(&$field_state) { + if (isset($field_state['entity'])) { + module_load_include('inc', 'entity', 'includes/entity.ui'); + foreach ($field_state['entity'] as $delta => $entity) { + if ($entity instanceof FieldCollectionItemEntity) { + $field_state['entity'][$delta] = entity_ui_clone_entity('field_collection_item', $entity); + } + } + } +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.info b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.info index 86d655b3..273d8de6 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.info +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.info @@ -5,6 +5,9 @@ core = 7.x configure = admin/config/regional/entity_translation dependencies[] = locale (>7.14) +test_dependencies[] = pathauto:pathauto +test_dependencies[] = title:title + files[] = includes/translation.handler_factory.inc files[] = includes/translation.handler.inc files[] = includes/translation.handler.comment.inc @@ -23,9 +26,8 @@ files[] = views/entity_translation_handler_filter_language.inc files[] = views/entity_translation_handler_filter_translation_exists.inc files[] = views/entity_translation_handler_field_field.inc -; Information added by Drupal.org packaging script on 2016-09-28 -version = "7.x-1.0-beta5+15-dev" +; Information added by Drupal.org packaging script on 2019-01-20 +version = "7.x-1.0+5-dev" core = "7.x" project = "entity_translation" -datestamp = "1475057941" - +datestamp = "1548022384" diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.install b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.install index b3339899..4d41c1de 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.install +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.install @@ -175,6 +175,9 @@ function entity_translation_install() { // Enable revision support for entity translation. variable_set('entity_translation_revision_enabled', TRUE); + + // Enable taxonomy autocomplete support. + variable_set('entity_translation_taxonomy_autocomplete', TRUE); } /** @@ -356,7 +359,11 @@ function entity_translation_update_7006() { 'not null' => FALSE, 'description' => 'The entity revision id this translation relates to', ); - db_add_field('entity_translation', 'revision_id', $spec); + + // Create revision id column if it doesn't exist already. + if (!db_field_exists('entity_translation', 'revision_id')) { + db_add_field('entity_translation', 'revision_id', $spec); + } // Create the entity translation revision schema. $table = array( @@ -429,7 +436,11 @@ function entity_translation_update_7006() { 'primary key' => array('entity_type', 'revision_id', 'language'), 'indexes'=> array('revision_id' => array('revision_id')), ); - db_create_table('entity_translation_revision', $table); + + // Create entity translation revision table if it doesn't exist already. + if (!db_table_exists('entity_translation_revision')) { + db_create_table('entity_translation_revision', $table); + } } /** @@ -452,6 +463,9 @@ function entity_translation_update_7007() { * through it. */ function entity_translation_update_7008() { + if (!module_exists('taxonomy')) { + return; + } // According to EXPLAIN joining {taxonomy_vocabulary} here makes the query // perform way worse, so we just split into two quick ones. $query = "SELECT t.vid diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.module b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.module index e583ee11..c9f4a01c 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.module +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.module @@ -244,6 +244,13 @@ function entity_translation_menu() { 'file' => 'entity_translation.admin.inc', ); + $items['entity_translation/taxonomy_term/autocomplete'] = array( + 'title' => 'Entity translation autocomplete', + 'page callback' => 'entity_translation_taxonomy_term_autocomplete', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; } @@ -457,7 +464,11 @@ function entity_translation_menu_alter(&$items) { // Replace the main edit callback with our proxy implementation to set // form language to the current language and check access. $entity_position = array_search($scheme['path wildcard'], $edit_path_parts); - $original_item = $edit_item; + // Make sure incoming page and access arguments are arrays. + $original_item = $edit_item + array( + 'page arguments' => array(), + 'access arguments' => array(), + ); $args = array($entity_type, $entity_position, FALSE, $original_item); $edit_item['page callback'] = 'entity_translation_edit_page'; $edit_item['page arguments'] = array_merge($args, $original_item['page arguments']); @@ -550,7 +561,7 @@ function entity_translation_edit_page() { $handler = entity_translation_get_handler($entity_type, $entity); $handler->initPathScheme(); $langcode = entity_translation_get_existing_language($entity_type, $entity, $langcode); - $handler->setFormLanguage($langcode); + $handler->setActiveLanguage($langcode); // Display the entity edit form. return _entity_translation_callback($edit_form_item['page callback'], $args, $edit_form_item); @@ -693,7 +704,7 @@ function entity_translation_add_page() { $handler = entity_translation_get_handler($entity_type, $entity); $handler->initPathScheme(); - $handler->setFormLanguage($langcode); + $handler->setActiveLanguage($langcode); $handler->setSourceLanguage($source); // Display the entity edit form. @@ -918,7 +929,7 @@ function entity_translation_field_language_alter(&$display_language, $context) { if (isset($translations->data[$context['language']]) && !entity_translation_access($entity_type, $translations->data[$context['language']])) { list(, , $bundle) = entity_extract_ids($entity_type, $entity); $instances = field_info_instances($entity_type, $bundle); - $entity = clone($entity); + $entity = clone $entity; foreach ($translations->data as $langcode => $translation) { if ($langcode == $context['language'] || !entity_translation_access($entity_type, $translations->data[$langcode])) { @@ -1194,7 +1205,7 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f if (empty($form['#entity_translation_source_form']) && entity_translation_enabled($entity_type, $bundle)) { $handler = entity_translation_get_handler($entity_type, $entity); $langcode = !empty($langcode) ? $langcode : $handler->getLanguage(); - $form_langcode = $handler->getFormLanguage(); + $form_langcode = $handler->getActiveLanguage(); $translations = $handler->getTranslations(); $update_langcode = $form_langcode && ($form_langcode != $langcode); $source = $handler->getSourceLanguage(); @@ -1217,7 +1228,7 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f // language information from source to target language, this way the // user can find the form items already populated with the source values // while the field form element holds the correct language information. - if ($field['translatable']) { + if ($field['translatable'] && isset($form[$field_name])) { $element = &$form[$field_name]; $element['#entity_type'] = $entity_type; $element['#entity'] = $entity; @@ -1253,11 +1264,14 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f list(, , $bundle) = entity_extract_ids($entity_type, $entity); foreach (field_info_instances($entity_type, $bundle) as $instance) { $field_name = $instance['field_name']; - $field = field_info_field($field_name); - // If access is not set or is granted we check whether the user has - // access to shared fields. - $form[$field_name]['#access'] = (!isset($form[$field_name]['#access']) || $form[$field_name]['#access']) && ($field['translatable'] || $shared_access); - $form[$field_name]['#multilingual'] = (boolean) $field['translatable']; + // Check if a field is part of the form array. + if (isset($form[$field_name])) { + $field = field_info_field($field_name); + // If access is not set or is granted we check whether the user has + // access to shared fields. + $form[$field_name]['#access'] = (!isset($form[$field_name]['#access']) || $form[$field_name]['#access']) && ($field['translatable'] || $shared_access); + $form[$field_name]['#multilingual'] = (boolean) $field['translatable']; + } } } @@ -1491,7 +1505,7 @@ function entity_translation_form_alter(&$form, &$form_state) { if (!$handler->isNewEntity()) { $handler->entityForm($form, $form_state); $translations = $handler->getTranslations(); - $form_langcode = $handler->getFormLanguage(); + $form_langcode = $handler->getActiveLanguage(); if (!isset($translations->data[$form_langcode]) || count($translations->data) > 1) { // Hide shared form elements if the user is not allowed to edit them. $handler->entityFormSharedElements($form); @@ -1520,7 +1534,7 @@ function entity_translation_form_alter(&$form, &$form_state) { function entity_translation_entity_form_source_language_submit($form, &$form_state) { $handler = entity_translation_entity_form_get_handler($form, $form_state); $langcode = $form_state['values']['source_language']['language']; - $path = "{$handler->getEditPath()}/add/$langcode/{$handler->getFormLanguage()}"; + $path = "{$handler->getEditPath()}/add/$langcode/{$handler->getActiveLanguage()}"; $options = array(); if (isset($_GET['destination'])) { $options['query'] = drupal_get_destination(); @@ -1536,7 +1550,7 @@ function entity_translation_entity_form_source_language_submit($form, &$form_sta */ function entity_translation_entity_form_delete_translation_submit($form, &$form_state) { $handler = entity_translation_entity_form_get_handler($form, $form_state); - $path = "{$handler->getTranslatePath()}/delete/{$handler->getFormLanguage()}"; + $path = "{$handler->getTranslatePath()}/delete/{$handler->getActiveLanguage()}"; $options = array(); if (isset($_GET['destination'])) { $options['query'] = drupal_get_destination(); @@ -1564,7 +1578,7 @@ function entity_translation_entity_form_language_update($element, &$form_state, // needed when responding to an AJAX request where the languages cannot be set // from the usual page callback. if (!empty($form_state['entity_translation']['form_langcode'])) { - $handler->setFormLanguage($form_state['entity_translation']['form_langcode']); + $handler->setActiveLanguage($form_state['entity_translation']['form_langcode']); } // When responding to an AJAX request we should ignore any change in the // language widget as it may alter the field language expected by the AJAX @@ -1597,6 +1611,9 @@ function entity_translation_field_attach_submit($entity_type, $entity, $form, &$ // Update the wrapped entity with the submitted values. $handler->setEntity($entity); $handler->entityFormSubmit($form, $form_state); + + // Process in-place translations for the taxonomy autocomplete widget. + entity_translation_taxonomy_term_field_attach_submit($entity_type, $entity, $form, $form_state); } } @@ -1671,7 +1688,7 @@ function theme_entity_translation_language_tabs($variables) { * Adds an option to enable field synchronization. * Enable a selector to choose whether a field is translatable. */ -function entity_translation_form_field_ui_field_edit_form_alter(&$form, $form_state) { +function entity_translation_form_field_ui_field_edit_form_alter(&$form, &$form_state) { $instance = $form['#instance']; $entity_type = $instance['entity_type']; $field_name = $instance['field_name']; @@ -1691,7 +1708,8 @@ function entity_translation_form_field_ui_field_edit_form_alter(&$form, $form_st $label = t('Field translation'); $title = t('Users may translate all occurrences of this field:') . _entity_translation_field_desc($field); - if (field_has_data($field)) { + $form_state['field_has_data'] = field_has_data($field); + if ($form_state['field_has_data']) { $path = "admin/config/regional/entity_translation/translatable/$field_name"; $status = $translatable ? $title : (t('All occurrences of this field are untranslatable:') . _entity_translation_field_desc($field)); $link_title = !$translatable ? t('Enable translation') : t('Disable translation'); @@ -1719,6 +1737,11 @@ function entity_translation_form_field_ui_field_edit_form_alter(&$form, $form_st '#default_value' => $translatable, ); } + + $function = 'entity_translation_form_field_ui_field_edit_' . $instance['widget']['type'] . '_form_alter'; + if (function_exists($function)) { + $function($form, $form_state); + } } /** @@ -1821,32 +1844,37 @@ function entity_translation_settings($entity_type, $bundle) { * Entity language callback. * * This callback changes the entity language from the actual one to the active - * form language. This overriding allows to obtain language dependent form - * widgets where multilingual values are supported (e.g. field or path alias - * widgets) even if the code was not originally written with supporting multiple - * values per language in mind. + * language. This overriding allows to obtain language dependent form widgets + * where multilingual values are supported (e.g. field or path alias widgets) + * even if the code was not originally written with supporting multiple values + * per language in mind. * * The main drawback of this approach is that code needing to access the actual * language in the entity form build/validation/submit workflow cannot rely on * the entity_language() function. On the other hand in these scenarios assuming - * the presence of Entity translation should be safe, thus being able to rely on - * the EntityTranslationHandlerInterface::getLanguage() method. + * the presence of Entity translation should be safe, thus developers can rely + * on the EntityTranslationHandlerInterface::getLanguage() method. * - * @param $entity_type + * @param string $entity_type * The the type of the entity. - * @param $entity + * @param object $entity * The entity whose language has to be returned. * - * @return + * @return string * A valid language code. */ function entity_translation_language($entity_type, $entity) { $handler = entity_translation_get_handler($entity_type, $entity); - if (empty($handler)) { + if (!$handler) { return LANGUAGE_NONE; } - $langcode = $handler->getFormLanguage(); - return !empty($langcode) ? $langcode : $handler->getLanguage(); + if (entity_translation_enabled($entity_type, $entity)) { + $langcode = $handler->getActiveLanguage(); + return $langcode ? $langcode : $handler->getLanguage(); + } + else { + return $handler->getLanguage(); + } } /** @@ -1862,15 +1890,8 @@ function entity_translation_language($entity_type, $entity) { * A class implementing EntityTranslationHandlerInterface. */ function entity_translation_get_handler($entity_type = NULL, $entity = NULL) { - if (class_exists('EntityTranslationHandlerFactory')) { - $factory = EntityTranslationHandlerFactory::getInstance(); - return empty($entity) ? $factory->getLastHandler($entity_type) : $factory->getHandler($entity_type, $entity); - } - // @todo BC layer. Remove before the first stable release. - elseif (!empty($entity_type) && is_object($entity)) { - $entity_info = entity_get_info($entity_type); - return new EntityTranslationDefaultHandler($entity_type, $entity_info, $entity); - } + $factory = EntityTranslationHandlerFactory::getInstance(); + return empty($entity) ? $factory->getLastHandler($entity_type) : $factory->getHandler($entity_type, $entity); } /** @@ -1915,7 +1936,7 @@ function entity_translation_current_form_get_handler() { } /** - * Returns an array of edit form info as defined in hook_translation_info(). + * Returns an array of edit form info as defined in hook_entity_info(). * * @param $form * The entity edit form. @@ -2027,7 +2048,7 @@ function entity_translation_entity_uuid_presave(&$entity, $entity_type) { } /** - * Implement hook_pathauto_alias_alter(). + * Implements hook_pathauto_alias_alter(). * * When bulk-updating aliases for nodes automatically create a path for every * translation. @@ -2037,17 +2058,20 @@ function entity_translation_pathauto_alias_alter(&$alias, array &$context) { $entity_type = $context['module']; // Ensure that we are dealing with a bundle having entity translation enabled. - if ($context['op'] == 'bulkupdate' && !empty($info[$entity_type]['token type']) && !empty($context['data'][$info[$entity_type]['token type']])) { + if (in_array($context['op'], array('bulkupdate', 'update')) && !empty($info[$entity_type]['token type']) && !empty($context['data'][$info[$entity_type]['token type']])) { $entity = $context['data'][$info[$entity_type]['token type']]; if (entity_translation_enabled($entity_type, $entity)) { $translations = entity_translation_get_handler($entity_type, $entity)->getTranslations(); - // Only create extra aliases if we are working on the original language to - // avoid infinite recursion. - if ($context['language'] == $translations->original) { + // To avoid infinite recursion, remember the starting language. + static $pathauto_start_language; + if (!$pathauto_start_language) { + $pathauto_start_language = $context['language']; + } + if ($context['language'] == $pathauto_start_language && $context['language'] != LANGUAGE_NONE) { foreach ($translations->data as $language => $translation) { - // We already have an alias for the original language, so let's not + // We already have an alias for the starting language, so let's not // create another one. - if ($language == $translations->original) { + if ($language == $pathauto_start_language) { continue; } pathauto_create_alias($entity_type, $context['op'], $context['source'], $context['data'], $context['type'], $language); @@ -2085,3 +2109,11 @@ function entity_translation_entity_save($entity_type, $entity) { field_attach_update($entity_type, $entity); } } + +/** + * Implements hook_field_attach_prepare_translation_alter(). + */ +function entity_translation_field_attach_prepare_translation_alter(&$entity, $context) { + $handler = entity_translation_get_handler('node', $entity); + $handler->setActiveLanguage($context['langcode']); +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.taxonomy.inc b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.taxonomy.inc index 97210f98..35cc8874 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation.taxonomy.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation.taxonomy.inc @@ -40,6 +40,9 @@ function entity_translation_taxonomy_term_menu_alter(&$items, $backup) { $items['taxonomy/term/%taxonomy_term/translate']['access callback'] = 'entity_translation_taxonomy_term_tab_access'; $items['taxonomy/term/%taxonomy_term/translate']['file'] = 'entity_translation.admin.inc'; $items['taxonomy/term/%taxonomy_term/translate']['module'] = 'entity_translation'; + + // Delete translation callback. + $items['taxonomy/term/%taxonomy_term/translate/delete/%entity_translation_language']['access arguments'] = $access_arguments; } /** @@ -94,3 +97,472 @@ function entity_translation_form_taxonomy_form_vocabulary_submit($form, &$form_s variable_set('entity_translation_taxonomy', $info); } +/** + * Returns a translated label for the specified taxonomy term. + * + * @param object $term + * A taxonomy term object. + * @param string $langcode + * The language the label should be translated in. + * + * @return string + * The translated taxonomy term label. + * + * @internal This is supposed to be used only by the ET taxonomy integration + * code, as it might be removed/replaced in any moment of the ET lifecycle. + */ +function _entity_translation_taxonomy_label($term, $langcode) { + $entity_type = 'taxonomy_term'; + if (function_exists('title_entity_label')) { + $label = title_entity_label($term, $entity_type, $langcode); + } + else { + $label = entity_label($entity_type, $term); + } + return (string) $label; +} + +/** + * Implements entity_translation_form_field_ui_field_edit_WIDGET_TYPE_form_alter(). + * + * {@inheritdoc} + */ +function entity_translation_form_field_ui_field_edit_taxonomy_autocomplete_form_alter(&$form, &$form_state) { + $key = 'entity_translation_taxonomy_autocomplete_translate'; + $instance = $form['#instance']; + $field_name = $instance['field_name']; + $entity_type = $instance['entity_type']; + $field = field_info_field($field_name); + $translatable = field_is_translatable($entity_type, $field); + $bundle = !empty($field['settings']['allowed_values'][0]['vocabulary']) ? $field['settings']['allowed_values'][0]['vocabulary'] : NULL; + $access = variable_get('entity_translation_taxonomy_autocomplete', FALSE); + + // Add a checkbox to toggle in-place translation for autocomplete widgets. + $form['instance']['settings'][$key] = array( + '#type' => 'checkbox', + '#title' => t('Enable in-place translation of terms'), + '#description' => t('Check this option if you wish to use translation forms to perform in-place translation for terms entered in the original language.'), + '#default_value' => !$translatable && !empty($form['#instance']['settings'][$key]), + '#access' => $access && (!$form_state['field_has_data'] || !$translatable) && entity_translation_enabled('taxonomy_term', $bundle), + '#states' => array( + 'visible' => array(':input[name="field[translatable]"]' => array('checked' => FALSE)), + ), + '#weight' => -8, + ); +} + +/** + * Checks whether in-place translation is enabled for the autocomplete widget. + * + * @param array $element + * The widget form element. + * @param array $form_state + * The form state array. + * + * @return bool + * TRUE if in-place translation is enabled, FALSE otherwise. + */ +function _entity_translation_taxonomy_autocomplete_translation_enabled($element, $form_state) { + $field = field_info_field($element['#field_name']); + if (field_is_translatable($element['#entity_type'], $field)) { + return FALSE; + } + + list($id, , $bundle) = entity_extract_ids($element['#entity_type'], $element['#entity']); + if (!$id) { + return FALSE; + } + + $entity_type = 'taxonomy_term'; + $parent_handler = entity_translation_get_handler($element['#entity_type'], $element['#entity']); + $active_langcode = $parent_handler->getActiveLanguage(); + $translations = $parent_handler->getTranslations(); + $entity_langcode = isset($translations->original) ? $translations->original : LANGUAGE_NONE; + $instance = field_info_instance($element['#entity_type'], $field['field_name'], $bundle); + + // We need to make sure that we are not dealing with a translation form. + // However checking the active language is not enough, because the user may + // have changed the entity language. + return + (isset($form_state['entity_translation']['is_translation']) ? + $form_state['entity_translation']['is_translation'] : ($active_langcode != $entity_langcode)) && + !empty($instance['settings']['entity_translation_taxonomy_autocomplete_translate']) && + (user_access('translate any entity') || user_access("translate $entity_type entities")); +} + +/** + * Implements hook_field_widget_WIDGET_TYPE_form_alter(). + * + * {@inheritdoc} + */ +function entity_translation_field_widget_taxonomy_autocomplete_form_alter(&$element, &$form_state, $context) { + // The autocomplete widget is also displayed in the field configuration form, + // in which case we do not need to perform any alteration. To preserve BC, by + // default we enable our taxonomy autocomplete override only on new sites. + if (!isset($element['#entity']) || !variable_get('entity_translation_taxonomy_autocomplete', FALSE)) { + return; + } + + // We will need to translate term names, if Title is enabled and configured + // for this vocabulary. + $entity_type = 'taxonomy_term'; + $field = field_widget_field($element, $form_state); + $bundle = !empty($field['settings']['allowed_values'][0]['vocabulary']) ? $field['settings']['allowed_values'][0]['vocabulary'] : NULL; + if ($bundle && entity_translation_enabled($entity_type, $bundle)) { + $parent_handler = entity_translation_get_handler($element['#entity_type'], $element['#entity']); + $langcode = $parent_handler->getActiveLanguage(); + $terms = array_values(_entity_translation_taxonomy_autocomplete_widget_get_terms($element)); + + // If we are using the regular autocomplete behavior also in translation + // forms, we need to set our custom callback. + if (!_entity_translation_taxonomy_autocomplete_translation_enabled($element, $form_state)) { + $element['#autocomplete_path'] = 'entity_translation/' . $entity_type . '/autocomplete/' . $langcode . '/' . $element['#field_name']; + $translations = $parent_handler->getTranslations(); + if (isset($translations->original) && $translations->original != $langcode) { + $labels = array(); + foreach ($terms as $delta => $term) { + $labels[] = _entity_translation_taxonomy_label($term, $langcode); + } + $element['#default_value'] = implode(', ', $labels); + } + } + // Otherwise we just provide the in-place translation widget. + else { + $element['#type'] = 'fieldset'; + $element['#description'] = t('Enter one translation for each term'); + $element['#access'] = (bool) $terms; + foreach ($terms as $delta => $term) { + $element[$delta] = array( + '#type' => 'textfield', + '#default_value' => _entity_translation_taxonomy_label($term, $langcode), + '#required' => TRUE, + '#tid' => $term->tid, + ); + } + $element['#process'][] = 'entity_translation_taxonomy_autocomplete_process'; + } + + // The native term save logic is performed at widget validation level, so we + // just replace the validation handler to provide our logic instead. + $element['#element_validate'] = array_values(array_diff($element['#element_validate'], array('taxonomy_autocomplete_validate'))); + $element['#element_validate'][] = 'entity_translation_taxonomy_autocomplete_validate'; + } +} + +/** + * Returns the terms referenced by the taxonomy autocomplete widget field. + * + * @param array $element + * The taxonomy autocomplete form element. + * + * @return object[] + * An associative array of taxonomy term object keyed by their identifiers. + */ +function _entity_translation_taxonomy_autocomplete_widget_get_terms($element) { + $items = isset($element['#entity']->{$element['#field_name']}[$element['#language']]) ? + $element['#entity']->{$element['#field_name']}[$element['#language']] : array(); + $tids = array_map(function ($item) { return $item['tid']; }, $items); + return taxonomy_term_load_multiple($tids); +} + +/** + * Process callback for the ET taxonomy autocomplete widget. + * + * {@inheritdoc} + */ +function entity_translation_taxonomy_autocomplete_process($element) { + // The in-place translation widget makes sense only for untranslatable field, + // which may have the "(all languages)" label suffix. In this case it would be + // confusing so we need to revert that. + $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']); + $element['#title'] = check_plain($instance['label']); + return $element; +} + +/** + * Entity translation taxonomy autocomplete callback. + * + * @param string $langcode + * The input language. + * @param string $field_name + * The name of the term reference field. + * @param string $tags_typed + * (optional) A comma-separated list of term names entered in the + * autocomplete form element. Only the last term is used for autocompletion. + * Defaults to an empty string. + * + * @see taxonomy_autocomplete() + */ +function entity_translation_taxonomy_term_autocomplete($langcode = NULL, $field_name = '', $tags_typed = '') { + // If the request has a '/' in the search text, then the menu system will have + // split it into multiple arguments, recover the intended $tags_typed. + $args = func_get_args(); + // Shift off the $langcode and $field_name arguments. + array_shift($args); + array_shift($args); + $tags_typed = implode('/', $args); + + // Make sure the field exists and is a taxonomy field. + if (!($field = field_info_field($field_name)) || $field['type'] !== 'taxonomy_term_reference') { + // Error string. The JavaScript handler will realize this is not JSON and + // will display it as debugging information. + print t('Taxonomy field @field_name not found.', array('@field_name' => $field_name)); + exit; + } + + // The user enters a comma-separated list of tags. We only autocomplete the + // last tag. + $tags_typed = drupal_explode_tags($tags_typed); + $tag_last = drupal_strtolower(array_pop($tags_typed)); + + $term_matches = array(); + if ($tag_last != '') { + if (!isset($langcode) || $langcode == LANGUAGE_NONE) { + $langcode = $GLOBALS['language_content']->language; + } + + // Part of the criteria for the query come from the field's own settings. + $vocabulary = _entity_translation_taxonomy_reference_get_vocabulary($field); + + $entity_type = 'taxonomy_term'; + $query = new EntityFieldQuery(); + $query->addTag('taxonomy_term_access'); + $query->entityCondition('entity_type', $entity_type); + + // If the Title module is enabled and the taxonomy term name is replaced for + // the current bundle, we can look for translated names, otherwise we fall + // back to the regular name property. + if (module_invoke('title', 'field_replacement_enabled', $entity_type, $vocabulary->machine_name, 'name')) { + $name_field = 'name_field'; + $language_group = 0; + // Do not select already entered terms. + $column = 'value'; + if (!empty($tags_typed)) { + $query->fieldCondition($name_field, $column, $tags_typed, 'NOT IN', NULL, $language_group); + } + $query->fieldCondition($name_field, $column, $tag_last, 'CONTAINS', NULL, $language_group); + $query->fieldLanguageCondition($name_field, array($langcode, LANGUAGE_NONE), NULL, NULL, $language_group); + } + else { + $name_field = 'name'; + // Do not select already entered terms. + if (!empty($tags_typed)) { + $query->propertyCondition($name_field, $tags_typed, 'NOT IN'); + } + $query->propertyCondition($name_field, $tag_last, 'CONTAINS'); + } + + // Select rows that match by term name. + $query->propertyCondition('vid', $vocabulary->vid); + $query->range(0, 10); + $result = $query->execute(); + + // Populate the results array. + $prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : ''; + $terms = !empty($result[$entity_type]) ? taxonomy_term_load_multiple(array_keys($result[$entity_type])) : array(); + foreach ($terms as $tid => $term) { + $name = _entity_translation_taxonomy_label($term, $langcode); + $n = $name; + // Term names containing commas or quotes must be wrapped in quotes. + if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) { + $n = '"' . str_replace('"', '""', $name) . '"'; + } + $term_matches[$prefix . $n] = check_plain($name); + } + } + + drupal_json_output($term_matches); +} + +/** + * Returns the vocabulary enabled for the specified taxonomy reference field. + * + * @param array $field + * A field definition. + * + * @return object|null + * A vocabulary object or NULL if none is found. + */ +function _entity_translation_taxonomy_reference_get_vocabulary($field) { + $vocabulary = NULL; + if (!empty($field['settings']['allowed_values'])) { + $vids = array(); + $vocabularies = taxonomy_vocabulary_get_names(); + foreach ($field['settings']['allowed_values'] as $tree) { + $vids[] = $vocabularies[$tree['vocabulary']]->vid; + } + $vocabulary = taxonomy_vocabulary_load(reset($vids)); + } + return $vocabulary; +} + +/** + * Form element validate handler for taxonomy term autocomplete element. + * + * {@inheritdoc} + * + * @see taxonomy_autocomplete_validate() + */ +function entity_translation_taxonomy_autocomplete_validate($element, &$form_state) { + $value = array(); + list($id) = entity_extract_ids($element['#entity_type'], $element['#entity']); + $is_new = !isset($id); + + // This is the language of the parent entity, that we will be applying to new + // terms. + $parent_handler = entity_translation_get_handler($element['#entity_type'], $element['#entity']); + $langcode = !empty($form_state['entity_translation']['form_langcode']) ? + $form_state['entity_translation']['form_langcode'] : $parent_handler->getActiveLanguage(); + + // Handle in-place translation. + if (_entity_translation_taxonomy_autocomplete_translation_enabled($element, $form_state)) { + // The referenced terms cannot change, so we just need to collect their term + // identifiers. We also build a map of the corresponding deltas for later + // use. + $deltas = array(); + foreach (element_children($element) as $delta) { + $tid = $element[$delta]['#tid']; + $deltas[$tid] = $delta; + $value[$delta]['tid'] = $tid; + } + + // Save term translations. + $entity_type = 'taxonomy_term'; + $name_field = 'name_field'; + $source_langcode = $parent_handler->getSourceLanguage(); + // This is a validation handler, so we must defer the actual save to the + // submit phase. + $terms_to_save = &$form_state['entity_translation']['taxonomy_autocomplete'][$element['#entity_type']][$id][$element['#field_name']]; + foreach (taxonomy_term_load_multiple(array_keys($deltas)) as $term) { + // This is also the right context to perform validation. + $term_translation = $element[$deltas[$term->tid]]['#value']; + if (!$term_translation) { + $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']); + drupal_set_message(t('The translations for %field_label cannot be empty.', array('%field_label' => $instance['label'])), 'error', FALSE); + continue; + } + + $handler = entity_translation_get_handler($entity_type, $term); + $translations = $handler->getTranslations(); + $term_langcode = $handler->getLanguage(); + $typed_langcode = $term_langcode != LANGUAGE_NONE ? $langcode : $term_langcode; + + // Create a new translation in the active language, if it is missing. + if (!isset($translations->data[$typed_langcode]) && $typed_langcode != LANGUAGE_NONE) { + $translation = array( + 'language' => $typed_langcode, + 'source' => $source_langcode, + 'uid' => $GLOBALS['user']->uid, + 'status' => 1, + 'created' => REQUEST_TIME, + 'changed' => REQUEST_TIME, + ); + $translation_values = array( + $name_field => array($typed_langcode => array(array('value' => $term_translation))), + ); + $handler->setTranslation($translation, $translation_values); + $terms_to_save[] = $term; + } + // Otherwise we just update the existing translation, if it has changed. + // If the term is language-neutral, we just update its main value. This is + // expected to happen normally, but could when referencing existing terms. + elseif ($term_translation != _entity_translation_taxonomy_label($term, $typed_langcode)) { + $term->{$name_field}[$typed_langcode][0]['value'] = $term_translation; + $terms_to_save[] = $term; + } + } + } + // Autocomplete widgets do not send their tids in the form, so we must detect + // them here and process them independently. + elseif ($tags = $element['#value']) { + $entity_type = 'taxonomy_term'; + $field = field_widget_field($element, $form_state); + $vocabulary = _entity_translation_taxonomy_reference_get_vocabulary($field); + $typed_tags = drupal_explode_tags($tags); + + // Collect existing terms by name. + $existing_terms = array(); + foreach (_entity_translation_taxonomy_autocomplete_widget_get_terms($element) as $term) { + $name = _entity_translation_taxonomy_label($term, $langcode); + $existing_terms[$name] = $term; + } + + // Select terms that match by the (translated) name. + $query = new EntityFieldQuery(); + $query->addTag('taxonomy_term_access'); + $query->entityCondition('entity_type', $entity_type); + $query->propertyCondition('vid', $vocabulary->vid); + if ($langcode != LANGUAGE_NONE && module_invoke('title', 'field_replacement_enabled', $entity_type, $vocabulary->machine_name, 'name')) { + $language_group = 0; + // Do not select already entered terms. + $name_field = 'name_field'; + $column = 'value'; + $query->fieldCondition($name_field, $column, $typed_tags, NULL, NULL, $language_group); + // When we are creating a new entity, we cannot filter by active language, + // as that may have not be applied to the autocomplete query. + if (!$is_new) { + $query->fieldLanguageCondition($name_field, array($langcode, LANGUAGE_NONE), NULL, NULL, $language_group); + } + } + else { + $query->propertyCondition('name', $typed_tags); + } + $result = $query->execute(); + + // When we are creating a new entity, the language used for the autocomplete + // query is the current content language, so we should use that to update + // the map of existing terms. + if (!empty($result[$entity_type])) { + $typed_langcode = !$is_new ? $langcode : $GLOBALS['language_content']->language; + foreach (taxonomy_term_load_multiple(array_keys($result[$entity_type])) as $term) { + $name = _entity_translation_taxonomy_label($term, $typed_langcode); + $existing_terms[$name] = $term; + } + } + + // Now collect the identifiers for the various terms and update the taxonomy + // reference field values. + foreach ($typed_tags as $delta => $typed_tag) { + // See if the term exists in the chosen vocabulary and return the tid. + // Otherwise create a new 'autocreate' term for insert/update. + if (isset($existing_terms[$typed_tag])) { + $term = $existing_terms[$typed_tag]; + } + else { + $term = (object) array( + 'tid' => 'autocreate', + 'vid' => $vocabulary->vid, + 'name' => $typed_tag, + 'vocabulary_machine_name' => $vocabulary->machine_name, + ); + $handler = entity_translation_get_handler($entity_type, $term); + $handler->setOriginalLanguage($langcode); + $handler->initTranslations(); + } + $value[] = (array) $term; + } + } + + form_set_value($element, $value, $form_state); +} + +/** + * Term-specific implementation of hook_field_attach_submit(). + */ +function entity_translation_taxonomy_term_field_attach_submit($entity_type, $entity, $form, &$form_state) { + // Finally save in-place translations + if (!empty($form_state['entity_translation']['taxonomy_autocomplete'])) { + foreach ($form_state['entity_translation']['taxonomy_autocomplete'] as $entity_type => $entity_type_data) { + foreach ($entity_type_data as $id => $field_name_data) { + foreach ($field_name_data as $field_name => $term_data) { + if (!is_array($term_data)) { + continue; + } + foreach ($term_data as $term) { + entity_translation_entity_save('taxonomy_term', $term); + } + } + } + } + } +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.info b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.info index d7720cf7..ccade082 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.info +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.info @@ -7,9 +7,8 @@ dependencies[] = i18n dependencies[] = i18n_menu files[] = entity_translation_i18n_menu.test -; Information added by Drupal.org packaging script on 2016-09-28 -version = "7.x-1.0-beta5+15-dev" +; Information added by Drupal.org packaging script on 2019-01-20 +version = "7.x-1.0+5-dev" core = "7.x" project = "entity_translation" -datestamp = "1475057941" - +datestamp = "1548022384" diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.module b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.module index 572f0e05..03fd5dfe 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.module +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.module @@ -164,7 +164,7 @@ function entity_translation_i18n_menu_form(&$form, &$form_state) { $default = isset($source_menu['language']) && $source_menu['language'] != LANGUAGE_NONE; $languages = language_list(); $handler = entity_translation_entity_form_get_handler($form, $form_state); - $langcode = $handler->getFormLanguage(); + $langcode = $handler->getActiveLanguage(); $language_name = isset($languages[$langcode]) ? t($languages[$langcode]->name) : t('current'); $form['menu']['#multilingual'] = TRUE; diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.test b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.test index db85b83f..94196543 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.test +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.test @@ -125,23 +125,36 @@ class EntityTranslationMenuTranslationTestCase extends EntityTranslationTestCase $this->assertText($link_title, 'New menu link title found: ' . $link_title); } + /** + * Asserts a link with a given label and title is found in the page. + */ + function assertLinkWithTitleAttribute($label, $title) { + $links = $this->xpath('//a[normalize-space(text())=:label and normalize-space(@title)=:title]', array( + ':label' => $label, + ':title' => $title, + )); + $this->assert(isset($links[0])); + } + /** * Test if menu localization works. */ function testMenuLocalization() { // Create Basic page in English. $link_title_en = $this->randomName(); - $node = $this->createPage($link_title_en, NULL, 'en'); + $link_description_en = $this->randomName() . ' & htmlentity'; + $node = $this->createPage($link_title_en, $link_description_en, 'en'); // Submit translation in Spanish. $link_title_es = $this->randomName(); - $node_translation = $this->createTranslation($node, $link_title_es, NULL, 'es'); + $link_description_es = $this->randomName() . ' & htmlentity'; + $node_translation = $this->createTranslation($node, $link_title_es, $link_description_es, 'es'); // Check menu links in both languages. $this->get('en', ''); - $this->assertText($link_title_en); + $this->assertLinkWithTitleAttribute($link_title_en, $link_description_en); $this->get('es', ''); - $this->assertText($link_title_es); + $this->assertLinkWithTitleAttribute($link_title_es, $link_description_es); // Edit English menu link. $link_title_en2 = $this->randomName(); @@ -149,15 +162,19 @@ class EntityTranslationMenuTranslationTestCase extends EntityTranslationTestCase // Check that Spanish menu link has not changed. $this->get('es', ''); - $this->assertText($link_title_es); + $this->assertLinkWithTitleAttribute($link_title_es, $link_description_es); // Edit Spanish menu link. $link_title_es2 = $this->randomName(); $this->editPage($node, $link_title_es, $link_title_es2, 'es'); - // Check that English menu link has not changed. + // Check that English menu link has changed. $this->get('en', ''); - $this->assertText($link_title_en2); + $this->assertLinkWithTitleAttribute($link_title_en2, $link_description_en); + + // Check that Spanish menu link has changed. + $this->get('es', ''); + $this->assertLinkWithTitleAttribute($link_title_es2, $link_description_es); // Delete Spanish translation and check that the respective menu item has // been deleted as well. diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.admin.inc b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.admin.inc index b6ec6a25..a8a5f5ff 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.admin.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.admin.inc @@ -34,8 +34,8 @@ function entity_translation_upgrade_start($types) { */ function entity_translation_upgrade_end($success, $results, $operations, $elapsed) { if (!empty($results)) { - $message = format_plural($results, '1 node translation successfully upgraded.', '@count node translations successfully upgraded.'); - watchdog('entity translation upgrade', '@count node translations successfully upgraded.', array('@count' => $results), WATCHDOG_INFO); + $message = format_plural($results['total'], '1 node translation successfully upgraded.', '@count node translations successfully upgraded.'); + watchdog('entity translation upgrade', '@count node translations successfully upgraded.', array('@count' => $results['total']), WATCHDOG_INFO); } else { $message = t('No node translation available for the upgrade.'); @@ -91,6 +91,10 @@ function entity_translation_upgrade_do($types, &$context) { $node = $nodes[$nid]; $original = $nodes[$node->tnid]; $handler = entity_translation_get_handler('node', $original); + // Instantiate the data and original properties of the translations. + if (empty($handler->getTranslations()->data)) { + $handler->initTranslations(); + } if (!isset($instances[$node->type])) { $instances[$node->type] = field_info_instances('node', $node->type); @@ -185,7 +189,7 @@ function entity_translation_upgrade_do($types, &$context) { $context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total']; if ($context['finished'] >= 1) { - $context['results'] = $context['sandbox']['total']; + $context['results']['total'] = $context['sandbox']['total']; } } } diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.drush.inc b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.drush.inc new file mode 100644 index 00000000..f0e6049f --- /dev/null +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.drush.inc @@ -0,0 +1,117 @@ + "Upgrades all nodes of the specified content type from Content Translation to Entity Translation.", + 'arguments' => array( + 'content_type' => 'Content type of nodes to be upgraded.', + ), + 'examples' => array( + 'drush entity-translation-upgrade article' => 'Upgrades all nodes of content type "article" from Content Translation to Entity Translation.', + ), + 'aliases' => array('etu'), + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, + ); + + return $items; +} + +/** + * Implements hook_drush_help(). + * + * @param + * A string with the help section + * + * @return + * A string with the help text for the entity-translation-upgrade command + */ +function entity_translation_upgrade_drush_help($section) { + switch ($section) { + case 'drush:entity-translation-upgrade': + return dt("Brief help for Drush command entity-translation-upgrade."); + + case 'meta:entity_translation_upgrade:title': + return dt("Entity Translation Upgrade commands"); + + case 'meta:entity_translation_upgrade:summary': + return dt("Upgrading nodes to Entity Translation."); + } +} + +/** + * Implements drush_hook_COMMAND(). + * + * @param + * The content type of which the nodes shall be upgraded + * + * Runs the batch upgrading nodes of the specified content_type to Entity + * Translation. Lets user choose content type from a list, if argument has + * not been provided. + */ +function drush_entity_translation_upgrade($content_type = "") { + // Get all installed content types. + $available_types = array(); + $available_types_chose = array(); + $available_types_str = ''; + foreach (node_type_get_types() as $type) { + $available_types[$type->type] = $type->type; + $available_types_chose[$type->type] = $type->name; + if (strlen($available_types_str) > 0) { + $available_types_str .= ', '; + } + $available_types_str .= $type->type; + } + + // If argument content_type is empty, prompt user for content type. + if (!$content_type) { + $content_type = drush_choice($available_types_chose, dt('Choose the content type of the nodes to be upgraded to Entity Translation:')); + } + + // Do content type argument checks. + if (!$content_type) { + return TRUE; + } + if (strlen($available_types_str) == 0) { + return drush_set_error(dt('Entity Translation Upgrade cannot run as no content type has been installed.')); + } + if (!in_array($content_type, $available_types)) { + return drush_set_error(dt('"@content_type" is not a valid content type machine name. Please use one of these installed content types as argument: @available_types_str.', array('@content_type' => $content_type, '@available_types_str' => $available_types_str))); + } + + // Start batch to upgrade nodes of the specified content type. + $types = array($content_type => $content_type); + $batch = array( + 'operations' => array( + array('entity_translation_upgrade_do', array($types)), + array('entity_translation_upgrade_complete', array()), + ), + 'finished' => 'entity_translation_upgrade_drush_end', + 'file' => drupal_get_path('module', 'entity_translation_upgrade') . '/entity_translation_upgrade.admin.inc', + 'progressive' => FALSE, + ); + batch_set($batch); + drush_backend_batch_process(); +} + +/** + * This is the 'finished' batch callback, drush version. + */ +function entity_translation_upgrade_drush_end($success, $results, $operations, $elapsed) { + // Print result messages. + if (!empty($results)) { + $message = format_plural($results['total'], '1 node translation successfully upgraded.', '@count node translations successfully upgraded.'); + $severity = 'ok'; + watchdog('Entity Translation upgrade', '@count node translations successfully upgraded.', array('@count' => $results['total']), WATCHDOG_INFO); + } + else { + $message = t('No node translation available for the upgrade.'); + $severity = 'warning'; + } + + drush_log($message, $severity); +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.info b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.info index 5912510b..c1f6dced 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.info +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.info @@ -3,10 +3,10 @@ description = Provides an upgrade path from node-based translation to field-base package = Multilingual - Entity Translation core = 7.x dependencies[] = entity_translation +files[] = entity_translation_upgrade.test -; Information added by Drupal.org packaging script on 2016-09-28 -version = "7.x-1.0-beta5+15-dev" +; Information added by Drupal.org packaging script on 2019-01-20 +version = "7.x-1.0+5-dev" core = "7.x" project = "entity_translation" -datestamp = "1475057941" - +datestamp = "1548022384" diff --git a/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.test b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.test new file mode 100644 index 00000000..5fba31b1 --- /dev/null +++ b/sites/all/modules/contrib/localisation/entity_translation/entity_translation_upgrade/entity_translation_upgrade.test @@ -0,0 +1,163 @@ + 'Translation upgrade', + 'description' => 'Tests for the upgrade from Content Translation to Entity Translation.', + 'group' => 'Entity translation', + 'dependencies' => array(), + ); + } + + function setUp() { + parent::setUp('locale', 'translation', 'translation_test', 'entity_translation', 'entity_translation_upgrade'); + $this->getAdminUser(array( + 'toggle field translatability', + 'administer entity translation', + )); + $this->getTranslatorUser(array( + 'translate content', + )); + $this->login($this->getAdminUser()); + $this->addLanguage('en'); + $this->addLanguage('es'); + $this->configureContentTypeForContentTranslation(); + $this->enableUrlLanguageDetection(); + $this->login($this->getTranslatorUser()); + } + + /** + * Configure the "Basic page" content type for entity translation tests. + */ + public function configureContentTypeForContentTranslation() { + // Configure the "Basic page" content type to use multilingual support with + // content translation. + $edit = array(); + $edit['language_content_type'] = TRANSLATION_ENABLED; + $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.')); + + } + + /** + * Toggle body field's translatability. + */ + public function makeBodyFieldTranslatable() { + $edit = array(); + $this->drupalGet('admin/structure/types/manage/page/fields/body'); + $this->clickLink('Enable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + $this->assertRaw(t('Data successfully processed.'), t('Body field have been made translatable.')); + } + + /** + * @see TranslationTestCase::createPage + */ + function createContentTranslationPage($title, $body, $language = NULL) { + $edit = array(); + $langcode = LANGUAGE_NONE; + $edit["title"] = $title; + $edit["body[$langcode][0][value]"] = $body; + if (!empty($language)) { + $edit['language'] = $language; + } + $this->drupalPost('node/add/page', $edit, t('Save')); + $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), 'Basic page created.'); + + // Check to make sure the node was created. + $node = $this->drupalGetNodeByTitle($title); + $this->assertTrue($node, 'Node found in database.'); + + return $node; + } + + /** + * @see TranslationTestCase::createTranslation + */ + function createContentTranslationTranslation($node, $title, $body, $language) { + $this->drupalGet('node/add/page', array('query' => array('translation' => $node->nid, 'target' => $language))); + + $langcode = LANGUAGE_NONE; + $body_key = "body[$langcode][0][value]"; + $this->assertFieldByXPath('//input[@id="edit-title"]', $node->title, "Original title value correctly populated."); + $this->assertFieldByXPath("//textarea[@name='$body_key']", $node->body[LANGUAGE_NONE][0]['value'], "Original body value correctly populated."); + + $edit = array(); + $edit["title"] = $title; + $edit[$body_key] = $body; + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), 'Translation created.'); + + // Check to make sure that translation was successful. + $translation = $this->drupalGetNodeByTitle($title); + $this->assertTrue($translation, 'Node found in database.'); + $this->assertTrue($translation->tnid == $node->nid, 'Translation set id correctly stored.'); + + return $translation; + } + + /** + * Tests copying of source node's body value in the add translation form page. + */ + public function testUpgradeContentToEntityTranslation() { + // Create Basic page in English. + $node_title = $this->randomName(); + $node_body = $this->randomName(); + $node = $this->createContentTranslationPage($node_title, $node_body, 'en'); + + // Submit translation in Spanish. + $this->drupalGet('node/' . $node->nid . '/translate'); + $node_translation_title = $this->randomName(); + $node_translation_body = $this->randomName(); + $node_translation = $this->createContentTranslationTranslation($node, $node_translation_title, $node_translation_body, 'es'); + + // Make Body field translatable before we run the upgrade. + $this->login($this->getAdminUser()); + $this->makeBodyFieldTranslatable(); + + // Run the upgrade for all Page nodes. + $edit = array( + 'types[page]' => 'page', + ); + $this->drupalPost('admin/config/regional/entity_translation', $edit, t('Upgrade')); + + // Switch to our translator user. + $this->login($this->getTranslatorUser()); + + // Check that the unpublished target node triggers a redirect. + $this->drupalGet('node/' . $node_translation->nid); + $headers = $this->drupalGetHeaders(TRUE); + list(, $status) = explode(' ', $headers[0][':status'], 3); + $this->assertEqual($status, 301, 'Expected response code was sent.'); + $languages = language_list(); + $this->assertEqual($this->getUrl(), url('node/' . $node->nid, array('absolute' => TRUE, 'language' => $languages['es'])), 'entity_translation_upgrade_redirect() redirected to expected URL.'); + + // Check that the body is displayed when the active language is English. + $this->drupalGet('node/' . $node->nid); + $this->assertRaw($node_body, t('Body field displayed correctly in the source language.')); + + // Check that the translated body is displayed when the active language is Spanish. + $this->drupalGet('es/node/' . $node->nid); + $this->assertRaw($node_translation_body, t('Body field displayed correctly in the target language.')); + + // Check that the edit forms are initialized correctly in the target language. + $this->drupalGet('node/' . $node->nid . '/edit'); + $this->assertFieldByXPath("//textarea[@name='body[en][0][value]']", $node_body, "Body field correctly instantiated with the value of the source language."); + $this->drupalGet('es/node/' . $node->nid . '/edit'); + $this->assertFieldByXPath("//textarea[@name='body[es][0][value]']", $node_translation_body, "Body field correctly instantiated with the value of the target language."); + + } + +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler.inc b/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler.inc index 91dbb4d1..f66c3f3b 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler.inc @@ -98,6 +98,62 @@ interface EntityTranslationHandlerInterface { */ public function getLanguage(); + /** + * Sets the active language. + * + * This is the language that determines which translation should be considered + * "active" for the wrapped entity. The "Entity Translation" module uses this + * information to implement the UI-based translation workflow. Other modules + * can rely on it to implement their own entity translation-related logic. + * + * This will affect which language is returned by the core "entity_language()" + * function. + * + * @param string $langcode + * The active language code. + * + * @see entity_language() + * @see entity_translation_language() + * @see ::getActiveLanguage() + */ + public function setActiveLanguage($langcode); + + /** + * Returns the active language. + * + * @return string + * The active language for the wrapped entity. + * + * @see ::setActiveLanguage() + */ + public function getActiveLanguage(); + + /** + * Sets the active form language. + * + * @param string $langcode + * The active form language code. + * + * @deprecated in 7.x-1.0-beta6, will be removed before 7.x-1.0. Use + * ::setActiveLanguage() instead. + * + * @see ::setActiveLanguage() + */ + public function setFormLanguage($langcode); + + /** + * Retrieves the active form language. + * + * @return string + * The active form language code. + * + * @deprecated in 7.x-1.0-beta6, will be removed before 7.x-1.0. Use + * ::getActiveLanguage() instead. + * + * @see ::getActiveLanguage() + */ + public function getFormLanguage(); + /** * Returns the translation object key for the wrapped entity type. */ @@ -109,7 +165,7 @@ interface EntityTranslationHandlerInterface { public function getDefaultLanguage(); /** - * Sets the language of the orginal translation. + * Sets the language of the original translation. * * @param $langcode * The language code of the original content values. @@ -272,16 +328,6 @@ interface EntityTranslationHandlerInterface { */ public function isAliasEnabled(); - /** - * Sets the active form language. - */ - public function setFormLanguage($langcode); - - /** - * Retrieves the active form language. - */ - public function getFormLanguage(); - /** * Sets the source language for the translation being created. */ @@ -364,19 +410,19 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa */ protected $children = array(); - private $entityForm; - private $translating; - private $outdated; - private $formLanguage; - private $sourceLanguage; + protected $entityForm; + protected $translating; + protected $outdated; + protected $activeLanguage; + protected $sourceLanguage; - private $pathScheme; - private $pathWildcard; - private $basePath; - private $editPath; - private $translatePath; - private $viewPath; - private $routerMap; + protected $pathScheme; + protected $pathWildcard; + protected $basePath; + protected $editPath; + protected $translatePath; + protected $viewPath; + protected $routerMap; /** * Initializes an instance of the translation handler. @@ -396,7 +442,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa $this->entityForm = FALSE; $this->translating = FALSE; $this->outdated = FALSE; - $this->formLanguage = FALSE; + $this->activeLanguage = FALSE; $this->sourceLanguage = FALSE; $this->pathScheme = 'default'; $this->routerMap = array(); @@ -481,7 +527,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa public function addChild($entity_type, $entity) { if (!empty($this->factory)) { $handler = $this->factory->getHandler($entity_type, $entity); - $handler->setFormLanguage($this->getFormLanguage()); + $handler->setActiveLanguage($this->getActiveLanguage()); $handler->setSourceLanguage($this->getSourceLanguage()); // Avoid registering more than one child handler for each entity. $hid = $this->factory->getHandlerId($entity_type, $entity); @@ -632,6 +678,12 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa throw new Exception('Invalid translation language'); } + // $args will be used later on in a call to notifyChildren(). We need + // to call func_get_args() before any modifications to the function's + // arguments take place. This is due to changes in PHP 7.0 and onwards. + // @see http://php.net/manual/en/function.func-get-args.php#refsect1-function.func-get-args-notes + $args = func_get_args(); + $translations = $this->getTranslations(); $langcode = $translation['language']; @@ -658,13 +710,12 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa foreach (field_info_instances($this->entityType, $this->bundle) as $instance) { $field_name = $instance['field_name']; $field = field_info_field($field_name); - if ($field['translatable'] && isset($values[$field_name])) { + if ($field['translatable'] && isset($values[$field_name][$langcode])) { $this->entity->{$field_name}[$langcode] = $values[$field_name][$langcode]; } } } - $args = func_get_args(); $this->notifyChildren(__FUNCTION__, $args); } @@ -803,6 +854,55 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa } } + /** + * {@inheritdoc} + */ + public function setActiveLanguage($langcode) { + // @todo To fully preserve BC, we proxy the call to the deprecated + // ::setFormLanguage method. This will keep things working even when it + // has been overridden. Inline its implementation here upon removal. + $this->setFormLanguage($langcode); + } + + /** + * {@inheritdoc} + */ + public function getActiveLanguage() { + // @todo To fully preserve BC, we proxy the call to the deprecated + // ::getFormLanguage method. This will keep things working even when it + // has been overridden. Inline its implementation here upon removal. + return $this->getFormLanguage(); + } + + /** + * {@inheritdoc} + */ + public function setFormLanguage($langcode) { + $this->activeLanguage = $langcode; + $args = func_get_args(); + $this->notifyChildren(__FUNCTION__, $args); + } + + /** + * {@inheritdoc} + */ + public function getFormLanguage() { + if (!empty($this->activeLanguage)) { + return $this->activeLanguage; + } + // For new entities the active language should match the default language. + // The language stored with the entity itself (for example, $node->language) + // may not be reliable since the function creating the entity object will + // not know which language "Entity Translation" is configured to create the + // entity in. + elseif ($this->isNewEntity()) { + return $this->getDefaultLanguage(); + } + else { + return $this->getLanguage(); + } + } + /** * @see EntityTranslationHandlerInterface::getLanguageKey() */ @@ -952,7 +1052,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa if ($outdated) { $translations = $this->getTranslations(); foreach ($translations->data as $langcode => &$translation) { - if ($langcode != $this->getFormLanguage()) { + if ($langcode != $this->getActiveLanguage()) { $translation['translate'] = 1; } } @@ -1097,7 +1197,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa */ public function getSharedFieldsAccess() { $settings = entity_translation_settings($this->entityType, $this->bundle); - return ($settings['shared_fields_original_only'] == FALSE || $this->getLanguage() == $this->getFormLanguage()) && + return ($settings['shared_fields_original_only'] == FALSE || $this->getLanguage() == $this->getActiveLanguage()) && (!entity_translation_workflow_enabled() || user_access('edit translation shared fields') || user_access("edit {$this->entityType} translation shared fields")); } @@ -1108,22 +1208,6 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa return !empty($this->entityInfo['translation']['entity_translation']['alias']); } - /** - * @see EntityTranslationHandlerInterface::setFormLanguage() - */ - public function setFormLanguage($langcode) { - $this->formLanguage = $langcode; - $args = func_get_args(); - $this->notifyChildren(__FUNCTION__, $args); - } - - /** - * @see EntityTranslationHandlerInterface::getFormLanguage() - */ - public function getFormLanguage() { - return !empty($this->formLanguage) ? $this->formLanguage : $this->getLanguage(); - } - /** * @see EntityTranslationHandlerInterface::setSourceLanguage() */ @@ -1161,7 +1245,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa public function entityForm(&$form, &$form_state) { $this->entityForm = TRUE; $translations = $this->getTranslations(); - $form_langcode = $this->getFormLanguage(); + $form_langcode = $this->getActiveLanguage(); $langcode = $this->getLanguage(); $is_translation = $this->isTranslationForm(); $new_translation = !isset($translations->data[$form_langcode]); @@ -1461,7 +1545,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa $language_key = $this->getLanguageKey(); if (isset($form_state['values'][$language_key]) && !$this->isTranslationForm()) { $langcode = $form_state['values'][$language_key]; - $this->setFormLanguage($langcode); + $this->setActiveLanguage($langcode); } } @@ -1474,7 +1558,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa } $this->updateFormLanguage($form_state); - $form_langcode = $this->getFormLanguage(); + $form_langcode = $this->getActiveLanguage(); foreach (field_info_instances($this->entityType, $this->bundle) as $instance) { $field_name = $instance['field_name']; @@ -1496,7 +1580,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa * @see EntityTranslationHandlerInterface::entityFormSubmit() */ public function entityFormSubmit($form, &$form_state) { - $form_langcode = $this->getFormLanguage(); + $form_langcode = $this->getActiveLanguage(); $translations = $this->getTranslations(); $is_translation = !empty($form_state['entity_translation']['is_translation']); $new_translation = !isset($translations->data[$form_langcode]); @@ -1551,7 +1635,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa if (count($translations->data) > 0) { $languages = language_list(); - $form_langcode = $this->getFormLanguage(); + $form_langcode = $this->getActiveLanguage(); $language_tabs = array(); if ($this->getSourceLanguage()) { @@ -1624,7 +1708,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa * Returns TRUE if an entity translation is being edited. */ protected function isTranslationForm() { - return !$this->isNewEntity() && $this->getFormLanguage() != $this->getLanguage(); + return !$this->isNewEntity() && $this->getActiveLanguage() != $this->getLanguage(); } /** @@ -1653,7 +1737,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa * * @throws Exception */ - private function initPathVariables() { + protected function initPathVariables() { if (empty($this->pathScheme) || !isset($this->entityInfo['translation']['entity_translation']['path schemes'][$this->pathScheme])) { throw new Exception("Cannot initialize entity translation path variables (invalid path scheme)."); } diff --git a/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler_factory.inc b/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler_factory.inc index b3819c2c..189107f5 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler_factory.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/includes/translation.handler_factory.inc @@ -87,10 +87,7 @@ class EntityTranslationHandlerFactory { if (!isset($this->handlers[$entity_type][$id])) { $entity_info = entity_get_info($entity_type); $class = $entity_info['translation']['entity_translation']['class']; - // @todo Remove the fourth parameter once 3rd-party translation handlers - // have been fixed and no longer require the deprecated entity_id - // parameter. - $handler = new $class($entity_type, $entity_info, $entity, NULL); + $handler = new $class($entity_type, $entity_info, $entity); $handler->setFactory($this); $this->handlers[$entity_type][$id] = $handler; } diff --git a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation.test b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation.test index b552ed17..de069a12 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation.test +++ b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation.test @@ -14,6 +14,9 @@ class EntityTranslationTestCase extends DrupalWebTestCase { protected $admin_user; protected $translator_user; + /** + * {@inheritdoc} + */ function setUp() { $args = func_get_args(); call_user_func_array(array('parent', 'setUp'), $args); @@ -133,6 +136,19 @@ class EntityTranslationTestCase extends DrupalWebTestCase { } } + /** + * Disable a language which is in the language list. + * + * @param string $langcode + * The code of the language to disable, which must exist. + */ + function disableLanguage($langcode) { + $edit = array( + 'enabled[' . $langcode . ']' => FALSE, + ); + $this->drupalPost('admin/config/regional/language', $edit, 'Save configuration'); + } + /** * Install a specified language if it has not been already, otherwise make sure that the language is enabled. * @@ -190,7 +206,7 @@ class EntityTranslationTestCase extends DrupalWebTestCase { // Check if the setting works. $this->drupalGet('node/add/page'); - $this->assertFieldById('edit-body-und-add-more', t('Add another item'), t('Add another item button found.')); + $this->assertFieldById('edit-body-en-add-more', t('Add another item'), t('Add another item button found.')); } /** @@ -205,9 +221,8 @@ class EntityTranslationTestCase extends DrupalWebTestCase { */ function createPage($title, $body, $langcode) { $edit = array(); - $language_none = LANGUAGE_NONE; $edit["title"] = $title; - $edit["body[$language_none][0][value]"] = $body; + $edit["body[$langcode][0][value]"] = $body; $edit['language'] = $langcode; $this->drupalPost('node/add/page', $edit, t('Save')); $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.')); @@ -270,10 +285,27 @@ class EntityTranslationTranslationTestCase extends EntityTranslationTestCase { $this->login($this->getAdminUser()); $this->addLanguage('en'); $this->addLanguage('es'); + $this->addLanguage('fr'); + $this->disableLanguage('fr'); $this->configureContentType(); $this->login($this->getTranslatorUser()); } + /** + * Test disabled languages. + * + * Make sure disabled languages are not accessible in the language list when + * the option entity_translation_languages_enabled is enabled. + */ + function testDisabledLanguages() { + $this->drupalGet('node/add/page'); + $this->assertRaw('value="fr"', 'French is available even if the language is disabled'); + + variable_set('entity_translation_languages_enabled', TRUE); + $this->drupalGet('node/add/page'); + $this->assertNoRaw('value="fr"', 'French is not available when the language is disabled and the option entity_translation_languages_enabled is enabled.'); + } + /** * Test if field based translation works. * @@ -525,3 +557,788 @@ class EntityTranslationHookTestCase extends EntityTranslationTestCase { return $info; } } + +/** + * Tests that entity translation handler hierarchy works properly. + */ +class EntityTranslationHierarchyTestCase extends EntityTranslationTestCase { + + /** + * Return the test information. + */ + public static function getInfo() { + return array( + 'name' => 'Entity translation hierarchy', + 'description' => 'Tests that entity translation handler hierarchy works properly.', + 'group' => 'Entity translation', + ); + } + + /** + * {@inheritdoc} + */ + function setUp() { + parent::setUp('locale', 'entity_translation'); + } + + /** + * Tests the handler hierarchy. + */ + public function testHierarchy() { + $entity_type = 'node'; + $node = $this->drupalCreateNode(); + $factory = EntityTranslationHandlerFactory::getInstance(); + $handler = $factory->getHandler($entity_type, $node); + + $children = array(); + foreach (range(0, 4) as $index) { + $children[$index] = $this->drupalCreateNode(); + $handler->addChild($entity_type, $children[$index]); + } + + $langcode = 'it'; + $handler->setActiveLanguage($langcode); + foreach ($children as $child) { + $child_handler = $factory->getHandler($entity_type, $child); + $this->assertEqual($child_handler->getActiveLanguage(), $langcode); + } + + $rm_index = mt_rand(0, count($children) - 1); + $handler->removeChild($entity_type, $children[$rm_index]); + + $langcode = 'fr'; + $handler->setActiveLanguage($langcode); + foreach ($children as $index => $child) { + $child_handler = $factory->getHandler($entity_type, $child); + $this->assertEqual($child_handler->getActiveLanguage() == $langcode, $index != $rm_index); + } + + // @todo Test the other properties. + } + +} + +/** + * Basic tests for nodes using both content and entity translation. + */ +class EntityTranslationContentTranslationTestCase extends EntityTranslationTestCase { + + /** + * Return the test information. + */ + public static function getInfo() { + return array( + 'name' => 'Content and entity translation', + 'description' => 'Basic tests for nodes using both content and entity translatio.', + 'group' => 'Entity translation', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + // Activate modules and unset users. + parent::setUp('locale', 'translation', 'translation_test', 'entity_translation'); + // Create admin and translator users with one extra permission, + // namely the 'translate content' permission. + // These getters works also as setters. + $this->getAdminUser(array( + 'translate content', + )); + $this->getTranslatorUser(array( + 'translate content', + )); + $this->login($this->getAdminUser()); + $this->addLanguage('en'); + $this->addLanguage('es'); + $this->enableUrlLanguageDetection(); + $this->configureContentType(); + $this->login($this->getTranslatorUser()); + } + + /** + * Configure the "Basic page" content type for entity translation tests. + */ + public function configureContentType() { + // Configure the "Basic page" content type to use multilingual support with + // content translation. + $edit = array(); + $edit['language_content_type'] = TRANSLATION_ENABLED; + $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.')); + + // Toggle body field's translatability. + $edit = array(); + $edit['field[translatable]'] = 1; + $this->drupalPost('admin/structure/types/manage/page/fields/body', $edit, t('Save settings')); + $this->assertRaw(t('Saved %field configuration.', array('%field' => 'Body')), t('Body field settings have been updated.')); + } + + /** + * @see TranslationTestCase::createPage() + */ + function createPage($title, $body, $language = NULL) { + $edit = array(); + $langcode = LANGUAGE_NONE; + $edit["title"] = $title; + $edit["body[$langcode][0][value]"] = $body; + if (!empty($language)) { + $edit['language'] = $language; + } + $this->drupalPost('node/add/page', $edit, t('Save')); + $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), 'Basic page created.'); + + // Check to make sure the node was created. + $node = $this->drupalGetNodeByTitle($title); + $this->assertTrue($node, 'Node found in database.'); + + return $node; + } + + /** + * Tests copying of source node's body value in the add translation form page. + */ + public function testCopyFieldsUsingContentTranslation() { + // Create Basic page in English. + $node_title = $this->randomName(); + $node_body = $this->randomName(); + $node = $this->createPage($node_title, $node_body, 'en'); + + // Check that the edit form correctly copies over the field's values from + // the source node. + $target_language = 'es'; + $this->drupalGet('node/add/page', array('query' => array('translation' => $node->nid, 'target' => $target_language))); + $body_key = "body[${target_language}][0][value]"; + $this->assertFieldByXPath("//textarea[@name='$body_key']", $node_body, "Body field correctly instantiated with the value of the source language."); + } + +} + +/** + * Tests for integration of Entity Translation with other modules. + */ +class EntityTranslationIntegrationTestCase extends EntityTranslationTestCase { + + /** + * Return the test information. + */ + public static function getInfo() { + return array( + 'name' => 'Integration with other modules', + 'description' => 'Tests for integration of Entity Translation with other modules.', + 'group' => 'Entity translation', + // We need to add this to the test_dependencies[] as well. + 'dependencies' => array('pathauto'), + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + // Activate modules. + parent::setUp('locale', 'entity_translation'); + // Create admin and translator users with one extra permission, + // namely the 'administer content' permission for the admin, to + // allow enabling the pathauto module during testing. The + // Translator user needs to be able to create url aliases. + $this->getAdminUser(array( + 'administer modules', + )); + $this->getTranslatorUser(array( + 'create url aliases', + )); + $this->login($this->getAdminUser()); + $this->addLanguage('en'); + $this->addLanguage('es'); + $this->enableUrlLanguageDetection(); + $this->configureContentType(); + $this->login($this->getTranslatorUser()); + } + + /** + * Returns the role id of an $account object. + */ + protected function getUserRole($account) { + return reset($account->roles); + } + + /** + * Tests Pathauto integration. + */ + public function testPathautoIntegration() { + $languages = language_list(); + + // Enable the path module to add aliases manually. + $this->login($this->getAdminUser()); + if (!module_exists('path')) { + module_enable(array('path')); + } + $this->login($this->getTranslatorUser()); + + // Create Basic page in English. + $node_title = $this->randomName(); + $node_body = $this->randomName(); + $node = $this->createPage($node_title, $node_body, 'en'); + $node_alias = $this->randomName(); + $edit = array( + 'path[alias]' => $node_alias, + ); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); + + // Submit translation in Spanish. + $node_translation_body = $this->randomName(); + $this->createTranslation($node, $node_title, $node_translation_body, 'es'); + $node_translation_alias = $this->randomName(); + $edit = array( + 'path[alias]' => $node_translation_alias, + ); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'), array('language' => $languages['es'])); + + // Enable the pathauto module. + $this->login($this->getAdminUser()); + if (!module_exists('pathauto')) { + module_enable(array('pathauto')); + } + $admin_rid = $this->getUserRole($this->getAdminUser()); + user_role_grant_permissions($admin_rid, array('administer url aliases', 'administer pathauto')); + $translator_rid = $this->getUserRole($this->getTranslatorUser()); + user_role_grant_permissions($translator_rid, array('create url aliases')); + $this->login($this->getTranslatorUser()); + + // Create pathauto alias for source node. + $edit = array( + 'path[pathauto]' => TRUE, + ); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); + // Clear the static caches in case they interfere. + drupal_lookup_path('wipe'); + $node_pathauto_alias = pathauto_node_update_alias($node, 'return'); + $node_translation_pathauto_alias = pathauto_node_update_alias($node, 'return', array('language' => 'es')); + + // Check that the new alias for the translation matches the + // pathauto's logic. + $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_pathauto_alias), array('absolute' => TRUE))); + + // Check that a pathauto alias was created for the source and + // matches the pathauto's logic. + $this->drupalGet('node/' . $node->nid, array('language' => $languages['es'])); + $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_translation_pathauto_alias), array('absolute' => TRUE, 'language' => $languages['es']))); + + // Delete the two aliases. + path_delete(array('source' => 'node/' . $node->nid)); + + // Create pathauto alias for the translation of the node. + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'), array('language' => $languages['es'])); + // Clear the static caches in case they interfere. + drupal_lookup_path('wipe'); + $node_pathauto_alias = pathauto_node_update_alias($node, 'return'); + $node_translation_pathauto_alias = pathauto_node_update_alias($node, 'return', array('language' => 'es')); + + // Check that the new alias for the translation matches the + // pathauto's logic. + $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_translation_pathauto_alias), array('absolute' => TRUE, 'language' => $languages['es']))); + + // Check that a pathauto alias was created for the source and + // matches the pathauto's logic. + $this->drupalGet('node/' . $node->nid); + $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_pathauto_alias), array('absolute' => TRUE))); + } + +} + +/** + * Tests for enabling fields to use Entity Translation or disabling them. + */ +class EntityTranslationToggleFieldsTranslatabilityTestCase extends EntityTranslationTestCase { + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'name' => 'Fields translatability toggling', + 'description' => 'Tests for enabling fields to use Entity Translation or disabling them.', + 'group' => 'Entity translation', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + // Activate modules. + parent::setUp('locale', 'taxonomy', 'entity_translation', 'entity_translation_test'); + $this->login($this->getAdminUser(array( + 'administer taxonomy', + 'toggle field translatability', + ))); + $this->login($this->getTranslatorUser(array( + 'administer taxonomy', + ))); + } + + /** + * Configure the "Basic page" content type for entity translation tests. + */ + protected function configureContentTypeForRevisions() { + // Configure the "Basic page" content type to use revisions. + $edit = array( + 'node_options[revision]' => 1, + ); + $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.')); + } + + /** + * Create a "Basic page" in the specified language. + * + * @param $title + * Title of the basic page in the specified language. + * @param $body + * Body of the basic page in the specified language. + */ + protected function createUntranslatedPage($title, $body) { + $edit = array( + 'title' => $title, + 'body[und][0][value]' => $body, + ); + $this->drupalPost('node/add/page', $edit, t('Save')); + $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.')); + + // Check to make sure the node was created. + $node = $this->drupalGetNodeByTitle($title); + $this->assertTrue($node, t('Node found in database.')); + + return $node; + } + + /** + * Create a "Tags" term in the specified language. + * + * @param $name + * Name of the term. + * @param $description + * Description of the term. + * @param $text + * Content for the field_simple_text field. + */ + protected function createUntranslatedTag($name, $description, $text) { + $edit = array( + 'name' => $name, + 'description[value]' => $description, + "field_simple_text[und][0][value]" => $text, + ); + $this->drupalPost('admin/structure/taxonomy/tags/add', $edit, t('Save')); + + // Check to make sure the term was created. + $term = current(entity_load('taxonomy_term', FALSE, array('name' => $name), TRUE)); + $this->assertTrue($term, t('Term found in database.')); + + return $term; + } + + /** + * Tests toggling translatability on fields with data (non-revisionable). + */ + public function testTogglingFieldsWithDataNonRevisionable() { + // Create an untranslated Basic page. + $node_title = $this->randomName(); + $node_body = $this->randomName(); + $node = $this->createUntranslatedPage($node_title, $node_body); + $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found body field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body); + + // Create an untranslated Tags term. + $term_name = $this->randomName(); + $term_description = $this->randomName(); + $term_simple_text = $this->randomName(); + $term = $this->createUntranslatedTag($term_name, $term_description, $term_simple_text); + $this->assert(isset($term->field_simple_text[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($term->field_simple_text[LANGUAGE_NONE][0]['value'], $term_simple_text); + + // Enable translation for field body and check field migration. + $this->login($this->getAdminUser()); + $this->drupalGet('admin/structure/types/manage/page/fields/body'); + $this->clickLink('Enable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + $node = current(entity_load('node', FALSE, array('title' => $node_title), TRUE)); + $this->assert(isset($node->body['en']), t('Found field data in English as expected.')); + $this->assertEqual($node->body['en'][0]['value'], $node_body); + $this->assert(!isset($node->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.')); + + // Disable translation for body field and check field reverse migration. + $this->drupalGet('admin/structure/types/manage/page/fields/body'); + $this->clickLink('Disable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + $node = current(entity_load('node', FALSE, array('title' => $node_title), TRUE)); + $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body); + $this->assert(!isset($node->body['en']), t('No field data in English found.')); + + // Enable translation for field_simple_text and check field migration. + $this->drupalGet('admin/structure/taxonomy/tags/fields/field_simple_text'); + $this->clickLink('Enable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + // Clear the field cache in order to load current field data. + field_info_cache_clear(); + // Load the term and check that the fields data are under 'en'. + $term = current(entity_load('taxonomy_term', FALSE, array('name' => $term_name), TRUE)); + $this->assert(isset($term->field_simple_text['en']), t('Found field data in English as expected.')); + $this->assertEqual($term->field_simple_text['en'][0]['value'], $term_simple_text); + $this->assert(!isset($term->field_simple_text[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.')); + + // Disable translation for field_simple_text. + $this->drupalGet('admin/structure/taxonomy/tags/fields/field_simple_text'); + $this->clickLink('Disable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + + // Load the term and check that the fields data are under LANGUAGE_NONE. + $term = current(entity_load('taxonomy_term', FALSE, array('name' => $term_name), TRUE)); + $this->assert(isset($term->field_simple_text[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($term->field_simple_text[LANGUAGE_NONE][0]['value'], $term_simple_text); + $this->assert(!isset($term->field_simple_text['en']), t('No field data in English found.')); + } + + /** + * Tests toggling translatability on fields with data (revisionable). + */ + public function testTogglingFieldsWithDataRevisionable() { + // Enable revisions for Basic pages. + $this->login($this->getAdminUser()); + $this->configureContentTypeForRevisions(); + + // Create an untranslated Basic page. + $this->login($this->getTranslatorUser()); + $node_title = $this->randomName(); + $node_body = $this->randomName(); + $node = $this->createUntranslatedPage($node_title, $node_body); + $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body); + + // Create a new revision for the page. + $edit_revision = array( + 'title' => $this->randomName(), + ); + $this->drupalPost('node/' . $node->nid . '/edit', $edit_revision, t('Save')); + $node = node_load($node->nid, NULL, TRUE); + $this->assert($node->vid == $node->nid + 1, t('Correct vid attached to the node object.')); + + // Enable translation for field body and check field migration on all + // revisions. + $this->login($this->getAdminUser()); + $this->drupalGet('admin/structure/types/manage/page/fields/body'); + $this->clickLink('Enable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + $node_current_revision = current(entity_load('node', FALSE, array('vid' => $node->vid), TRUE)); + $this->assert(isset($node_current_revision->body['en']), t('Found field data in English as expected.')); + $this->assertEqual($node_current_revision->body['en'][0]['value'], $node_body); + $this->assert(!isset($node_current_revision->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.')); + $node_previous_revision = current(entity_load('node', FALSE, array('vid' => ($node->vid - 1)), TRUE)); + $this->assert(isset($node_previous_revision->body['en']), t('Found field data in English as expected.')); + $this->assertEqual($node_previous_revision->body['en'][0]['value'], $node_body); + $this->assert(!isset($node_previous_revision->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.')); + + // Disable translation for field_body. + $this->drupalGet('admin/structure/types/manage/page/fields/body'); + $this->clickLink('Disable translation'); + $this->drupalPost(NULL, array(), t('Confirm')); + + // Disable translation for field body and check field reverse migration on + // all revisions. + $node_current_revision = current(entity_load('node', FALSE, array('vid' => $node->vid), TRUE)); + $this->assert(isset($node_current_revision->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($node_current_revision->body[LANGUAGE_NONE][0]['value'], $node_body); + $this->assert(!isset($node_current_revision->body['en']), t('No field data in English found.')); + $node_previous_revision = current(entity_load('node', FALSE, array('vid' => ($node->vid - 1)), TRUE)); + $this->assert(isset($node_previous_revision->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.')); + $this->assertEqual($node_previous_revision->body[LANGUAGE_NONE][0]['value'], $node_body); + $this->assert(!isset($node_previous_revision->body['en']), t('No field data in English found.')); + } + +} + +/** + * Tests for the taxonomy autocomplete translation modes. + */ +class EntityTranslationTaxonomyAutocompleteTestCase extends EntityTranslationTestCase { + + /** + * Returns the test information. + */ + public static function getInfo() { + return array( + 'name' => 'Entity translation taxonomy autocomplete', + 'description' => 'Tests for the taxonomy autocomplete translation modes.', + 'group' => 'Entity translation', + 'dependencies' => array('title'), + ); + } + + /** + * {@inheritdoc} + */ + function setUp() { + parent::setUp('locale', 'entity_translation', 'taxonomy', 'title'); + $this->login($this->getAdminUser(array( + 'administer taxonomy', + 'administer entity translation', + ))); + $this->addLanguage('en'); + $this->addLanguage('it'); + $this->addLanguage('fr'); + $this->enableUrlLanguageDetection(); + $this->configureVocabulary(); + $this->configureContentType(); + } + + /** + * Makes the "Tags" vocabulary translatable. + */ + function configureVocabulary() { + $edit = array( + 'entity_translation_entity_types[taxonomy_term]' => TRUE, + ); + $this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration')); + + $edit = array( + 'entity_translation_taxonomy' => TRUE, + ); + $this->drupalPost('admin/structure/taxonomy/tags/edit', $edit, t('Save')); + + $edit = array( + 'enabled' => TRUE, + ); + $this->drupalPost('admin/structure/taxonomy/tags/fields/replace/name', $edit, t('Save settings')); + + $edit = array( + 'enabled' => TRUE, + ); + $this->drupalPost('admin/structure/taxonomy/tags/fields/replace/description', $edit, t('Save settings')); + } + + /** + * {@inheritdoc} + */ + function configureContentType() { + parent::configureContentType(); + + // Create an untranslatable term reference field with unlimited cardinality. + $edit = array( + 'fields[_add_new_field][label]' => 'Test tags', + 'fields[_add_new_field][field_name]' => 'test_tags', + 'fields[_add_new_field][type]' => 'taxonomy_term_reference', + 'fields[_add_new_field][widget_type]' => 'taxonomy_autocomplete', + ); + $this->drupalPost('admin/structure/types/manage/page/fields', $edit, t('Save')); + + $edit = array( + 'field[settings][allowed_values][0][vocabulary]' => 'tags', + ); + $this->drupalPost('admin/structure/types/manage/page/fields/field_test_tags/field-settings', $edit, t('Save field settings')); + + // Verify the in-place translation option is available. + $this->drupalGet('admin/structure/types/manage/page/fields/field_test_tags'); + $this->assertRaw(t('Enable in-place translation of terms')); + + $edit = array( + 'field[cardinality]' => FIELD_CARDINALITY_UNLIMITED, + ); + $this->drupalPost(NULL, $edit, t('Save settings')); + + // Ensure entity info is up-to-date. + drupal_flush_all_caches(); + } + + /** + * Enables in-place translation. + */ + function enableInPlaceTranslation() { + $edit = array( + 'instance[settings][entity_translation_taxonomy_autocomplete_translate]' => TRUE, + ); + $this->drupalPost('admin/structure/types/manage/page/fields/field_test_tags', $edit, t('Save settings')); + } + + /** + * Tests that in-place translation works as expected. + */ + function testInPlaceTranslation() { + $this->enableInPlaceTranslation(); + $this->login($this->getTranslatorUser(array( + 'administer taxonomy', + ))); + + $values = array( + 'Red' => 'Rosso', + 'Green' => 'Verde', + 'Blue' => 'Blu', + ); + + // Create an English node with a few new tags. + $edit = array( + 'title' => 'Test 1', + 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', array_keys($values)), + 'language' => 'en', + ); + $this->drupalPost('node/add/page', $edit, t('Save')); + $node = $this->drupalGetNodeByTitle($edit['title']); + + // Create an Italian translation and translate the English tags. + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->clickLink('add', 1); + $edit = array(); + foreach (array_values($values) as $delta => $value) { + $edit['field_test_tags[' . LANGUAGE_NONE . '][' . $delta . ']'] = $value; + } + $this->drupalPost(NULL, $edit, t('Save')); + + // Verify that the Italian values are correctly stored/displayed. + foreach ($values as $original => $translation) { + $this->assertRaw($translation); + } + + // Verify that the original English values were correctly retained. + $this->drupalGet('node/' . $node->nid); + foreach ($values as $original => $translation) { + $this->assertRaw($original); + } + } + + /** + * That the autocomplete works with translated terms. + */ + function testTranslatedAutocomplete() { + $this->login($this->getTranslatorUser(array( + 'administer taxonomy', + ))); + + $vocabulary = taxonomy_vocabulary_machine_name_load('tags'); + $entity_type = 'taxonomy_term'; + $existing_values = array(); + $translated_values = array( + 'en' => array( + 'Red' => 'Rosso', + 'Green' => 'Verde', + ), + 'it' => array( + 'Blu' => 'Blue', + ), + ); + $langcodes = array_keys($translated_values); + + // Create a few existing tags with different original language and translate + // them accordingly. + foreach ($translated_values as $langcode => $values) { + title_active_language($langcode); + $translation_langcode = current(array_diff($langcodes, array($langcode))); + + foreach ($values as $original => $translation) { + $term = (object) array( + 'vid' => $vocabulary->vid, + 'vocabulary_machine_name' => $vocabulary->machine_name, + 'name' => $original, + 'name_field' => array( + $langcode => array(array('value' => $original)), + $translation_langcode => array(array('value' => $translation)), + ), + ); + $translation = array( + 'language' => $translation_langcode, + 'source' => $langcode, + 'status' => TRUE, + ); + + $handler = entity_translation_get_handler($entity_type, $term); + $handler->setOriginalLanguage($langcode); + $handler->initTranslations(); + $handler->setTranslation($translation); + taxonomy_term_save($term); + + $existing_values[$term->name_field['en'][0]['value']] = $term->name_field['it'][0]['value']; + } + } + + // Verify that the English autocomplete route returns results for terms + // originally created in English. + $this->autocompleteGet('en', 'Re'); + $this->assertRaw('Red'); + $this->assertRaw('Green'); + + // Verify that the English autocomplete route returns results for terms + // translated into English. + $this->autocompleteGet('en', 'Blu'); + $this->assertRaw('Blue'); + + // Verify that the Italian autocomplete route returns results for terms + // originally created in Italian. + $this->autocompleteGet('it', 'Blu'); + $this->assertRaw('Blu'); + $this->assertNoRaw('Blue'); + + // Verify that the Italian autocomplete route returns results for terms + // translated into Italian. + $this->autocompleteGet('it', 'R'); + $this->assertRaw('Rosso'); + $this->assertRaw('Verde'); + + // Verify that existing tags are correctly referenced and new tags are + // correctly created, when saving an English node. + $new_values = array( + 'Cyan' => 'Ciano', + 'Magenta' => 'Magenta', + 'Yellow' => 'Giallo', + 'Black' => 'Nero', + ); + $all_values = $existing_values + $new_values; + + $edit = array( + 'title' => 'Test 1', + 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', array_keys($all_values)), + 'language' => 'en', + ); + $this->drupalPost('node/add/page', $edit, t('Save')); + foreach ($all_values as $original => $translation) { + $this->assertRaw($original); + } + + // Verify that existing translated tags are correctly referenced and new + // tags are correctly created, when translated the node into Italian. + $node = $this->drupalGetNodeByTitle($edit['title']); + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->clickLink('add', 1); + $edit = array( + 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', $all_values), + ); + $this->drupalPost(NULL, $edit, t('Save')); + foreach ($all_values as $original => $translation) { + $this->assertRaw($translation); + } + + // Verify that existing (translated) tags were preserved, while new Italian + // tags replaced the corresponding English versions. + $this->drupalGet('node/' . $node->nid); + foreach ($existing_values as $original => $translation) { + $this->assertRaw($original); + } + foreach ($new_values as $original => $translation) { + $this->assertRaw($translation); + } + } + + /** + * Performs a GET request to the autocomplete path. + * + * @param string $langcode + * The language to use to query results. + * @param string $query + * The search query string. + */ + protected function autocompleteGet($langcode, $query) { + $path = 'entity_translation/taxonomy_term/autocomplete/' . $langcode . '/field_test_tags/' . $query; + $languages = language_list(); + $this->drupalGet($path, array('language' => $languages[$langcode])); + } + +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.info b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.info index 6e671219..54462985 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.info +++ b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.info @@ -4,11 +4,11 @@ core = 7.x package = Testing hidden = TRUE dependencies[] = entity_translation + files[] = entity_translation_test.module -; Information added by Drupal.org packaging script on 2016-09-28 -version = "7.x-1.0-beta5+15-dev" +; Information added by Drupal.org packaging script on 2019-01-20 +version = "7.x-1.0+5-dev" core = "7.x" project = "entity_translation" -datestamp = "1475057941" - +datestamp = "1548022384" diff --git a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.install b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.install index a8ec2306..004b3ada 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.install +++ b/sites/all/modules/contrib/localisation/entity_translation/tests/entity_translation_test.install @@ -5,3 +5,34 @@ * Installation functionality for Entity Translation testing module. */ +/** + * Implements hook_install(). + */ +function entity_translation_test_install() { + // Create a simple text field, attached to taxonomy_terms. + field_info_cache_clear(); + + $field = array( + 'field_name' => 'field_simple_text', + 'type' => 'text', + 'cardinality' => 1, + ); + field_create_field($field); + + $instance = array( + 'field_name' => $field['field_name'], + 'label' => ucfirst(str_replace('_', ' ', $field['field_name'])), + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'widget' => array( + 'type' => 'text_textfield', + ), + 'display' => array( + 'default' => array( + 'type' => 'text_default', + ), + ), + ); + field_create_instance($instance); + +} diff --git a/sites/all/modules/contrib/localisation/entity_translation/views/entity_translation_handler_relationship.inc b/sites/all/modules/contrib/localisation/entity_translation/views/entity_translation_handler_relationship.inc index a88132b4..f346364b 100644 --- a/sites/all/modules/contrib/localisation/entity_translation/views/entity_translation_handler_relationship.inc +++ b/sites/all/modules/contrib/localisation/entity_translation/views/entity_translation_handler_relationship.inc @@ -1,7 +1,8 @@ table; // We need to add a condition on entity type to the join to avoid getting // relationships to entities with other types. - $join->extra = "$alias.entity_type = '{$def['entity type']}'"; + $join->extra = array( + array('field' => 'entity_type', 'value' => $def['entity type']), + ); $this->alias = $this->query->add_relationship($alias, $join, 'entity_translation', $this->relationship); } + }