From e89ec060acdf5709d6d6ffab674da568604c2e74 Mon Sep 17 00:00:00 2001 From: Chris Gross <gross.364@osu.edu> Date: Mon, 14 Jan 2019 11:38:21 -0500 Subject: [PATCH] 7.x-1.10 Release Candidate 3 --- profiles/wcm_base/CHANGELOG.txt | 5 + .../modules/contrib/admin_menu/PATCHES.txt | 4 + .../modules/contrib/admin_menu/admin_menu.inc | 2 +- .../wcm_base/modules/contrib/apps/PATCHES.txt | 4 + .../modules/contrib/apps/apps.profile.inc | 2 +- .../contrib/defaultcontent/PATCHES.txt | 1 + .../defaultcontent/defaultcontent.info | 1 + .../defaultcontent/defaultcontent.module | 5 +- .../modules/contrib/libraries/CHANGELOG.txt | 23 +- .../contrib/libraries/css/libraries.admin.css | 3 + .../contrib/libraries/libraries.admin.inc | 141 ++++++++++-- .../contrib/libraries/libraries.api.php | 2 + .../contrib/libraries/libraries.drush.inc | 80 +++++-- .../modules/contrib/libraries/libraries.info | 7 +- .../contrib/libraries/libraries.install | 10 + .../contrib/libraries/libraries.module | 148 +++++++++++- .../contrib/libraries/libraries.theme.inc | 36 +++ .../tests/LibrariesAdminWebTest.test | 27 ++- .../example_info_file.libraries.info | 7 +- .../libraries_test_module.info | 7 +- .../libraries_test_theme.info | 7 +- .../panels_breadcrumbs.info | 7 +- .../panels_breadcrumbs.module | 108 +++++---- .../modules/contrib/search_api/CHANGELOG.txt | 22 ++ .../search_api_facetapi.info | 6 +- .../contrib/search_api_views/README.txt | 15 ++ .../includes/handler_filter_date.inc | 47 +++- .../includes/handler_filter_numeric.inc | 217 ++++++++++++++++++ .../includes/handler_filter_options.inc | 1 + .../includes/plugin_cache.inc | 11 +- .../includes/plugin_content_cache.inc | 146 ++++++++++++ .../search_api_views/search_api_views.info | 8 +- .../search_api_views.views.inc | 13 ++ .../includes/callback_add_aggregation.inc | 8 +- .../contrib/search_api/search_api.admin.inc | 49 +++- .../contrib/search_api/search_api.drush.inc | 80 +++++++ .../contrib/search_api/search_api.info | 6 +- .../contrib/search_api/search_api.install | 45 ++++ .../contrib/search_api/search_api.module | 127 +++++++++- .../search_api/tests/search_api_test.info | 6 +- .../search_api/tests/search_api_test_2.info | 6 +- .../contrib/search_api_db/CHANGELOG.txt | 11 + .../contrib/search_api_db/search_api_db.info | 7 +- .../search_api_db/search_api_db.install | 10 +- .../modules/contrib/search_api_db/service.inc | 84 ++++--- .../modules/contrib/uuid/uuid.features.inc | 1 + .../wcm_base/modules/contrib/uuid/uuid.info | 6 +- .../contrib/uuid/uuid_path/uuid_path.info | 6 +- .../uuid_services/uuid_services.admin.inc | 8 + .../uuid/uuid_services/uuid_services.info | 12 +- .../uuid/uuid_services/uuid_services.install | 14 ++ .../uuid/uuid_services/uuid_services.module | 23 +- .../uuid_services_example.info | 6 +- .../modules/custom/news_client/README.md | 9 + .../panopoly/panopoly_admin/CHANGELOG.txt | 8 + .../panopoly_admin/panopoly_admin.info | 6 +- .../panopoly_admin/panopoly_admin.make | 1 + .../panopoly/panopoly_core/CHANGELOG.txt | 18 ++ .../panopoly/panopoly_core/panopoly_core.info | 6 +- .../panopoly/panopoly_core/panopoly_core.make | 16 +- .../panopoly_core/panopoly_core.profile.inc | 4 +- .../panopoly/panopoly_magic/CHANGELOG.txt | 9 + .../panopoly_magic/panopoly_magic.info | 6 +- .../panopoly_magic/panopoly_magic.module | 16 +- .../panopoly/panopoly_pages/CHANGELOG.txt | 8 + .../panopoly_pages/panopoly_pages.info | 6 +- .../panopoly/panopoly_search/CHANGELOG.txt | 8 + .../panopoly_search/panopoly_search.info | 6 +- .../panopoly_search/panopoly_search.make | 4 +- .../panopoly/panopoly_test/CHANGELOG.txt | 8 + .../panopoly/panopoly_test/panopoly_test.info | 6 +- .../panopoly/panopoly_theme/CHANGELOG.txt | 8 + .../panopoly_theme/panopoly_theme.info | 6 +- .../panopoly/panopoly_widgets/CHANGELOG.txt | 11 + ...nopoly_widgets.features.field_instance.inc | 8 +- .../panopoly_widgets/panopoly_widgets.info | 6 +- .../panopoly_widgets/panopoly_widgets.install | 54 +++++ .../panopoly_widgets/panopoly_widgets.make | 4 +- .../panopoly_widgets.spotlight.inc | 26 ++- .../fieldable-panels-pane.preprocess.inc | 4 +- .../wcm_omega/preprocess/page.preprocess.inc | 8 +- profiles/wcm_base/wcm_base.make | 16 +- 82 files changed, 1646 insertions(+), 288 deletions(-) create mode 100644 profiles/wcm_base/modules/contrib/admin_menu/PATCHES.txt create mode 100644 profiles/wcm_base/modules/contrib/apps/PATCHES.txt create mode 100644 profiles/wcm_base/modules/contrib/libraries/css/libraries.admin.css create mode 100644 profiles/wcm_base/modules/contrib/libraries/libraries.theme.inc create mode 100644 profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc create mode 100644 profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_content_cache.inc create mode 100644 profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.install diff --git a/profiles/wcm_base/CHANGELOG.txt b/profiles/wcm_base/CHANGELOG.txt index 647c98fa..3c7aed04 100644 --- a/profiles/wcm_base/CHANGELOG.txt +++ b/profiles/wcm_base/CHANGELOG.txt @@ -1,3 +1,8 @@ +WCM Base 7.x-1.10-rc3, 2019-01-14 +--------------------------------- +- WCM Base: Updated Panopoly to 1.58. +- WCM Omega: Updated FPP preprocess for PHP 7.1 compatability. + WCM Base 7.x-1.10-rc2, 2019-01-02 --------------------------------- - WCM Base: Added SMTP module patch for webform email attachments. diff --git a/profiles/wcm_base/modules/contrib/admin_menu/PATCHES.txt b/profiles/wcm_base/modules/contrib/admin_menu/PATCHES.txt new file mode 100644 index 00000000..fc460af5 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/admin_menu/PATCHES.txt @@ -0,0 +1,4 @@ +The following patches have been applied to this project: +- https://www.drupal.org/files/issues/admin-menu-2929025-each-function-deprecated-php-7.2.patch + +This file was automatically generated by Drush Make (http://drupal.org/project/drush). diff --git a/profiles/wcm_base/modules/contrib/admin_menu/admin_menu.inc b/profiles/wcm_base/modules/contrib/admin_menu/admin_menu.inc index 2eab789b..e6169df7 100644 --- a/profiles/wcm_base/modules/contrib/admin_menu/admin_menu.inc +++ b/profiles/wcm_base/modules/contrib/admin_menu/admin_menu.inc @@ -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); diff --git a/profiles/wcm_base/modules/contrib/apps/PATCHES.txt b/profiles/wcm_base/modules/contrib/apps/PATCHES.txt new file mode 100644 index 00000000..b8df8029 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/apps/PATCHES.txt @@ -0,0 +1,4 @@ +The following patches have been applied to this project: +- https://www.drupal.org/files/issues/apps-php7-compat-2945929.patch + +This file was automatically generated by Drush Make (http://drupal.org/project/drush). diff --git a/profiles/wcm_base/modules/contrib/apps/apps.profile.inc b/profiles/wcm_base/modules/contrib/apps/apps.profile.inc index 78376f71..91d23a3b 100644 --- a/profiles/wcm_base/modules/contrib/apps/apps.profile.inc +++ b/profiles/wcm_base/modules/contrib/apps/apps.profile.inc @@ -509,7 +509,7 @@ function apps_profile_check_dependencies($module_list) { // Create an associative array with weights as values. $module_list = array_flip(array_values($module_list)); - while (list($module) = each($module_list)) { + foreach ($module_list as $module => $info) { if (!isset($module_data[$module])) { // This module is not found in the filesystem, abort. return FALSE; diff --git a/profiles/wcm_base/modules/contrib/defaultcontent/PATCHES.txt b/profiles/wcm_base/modules/contrib/defaultcontent/PATCHES.txt index 0d26fb08..f4435d04 100644 --- a/profiles/wcm_base/modules/contrib/defaultcontent/PATCHES.txt +++ b/profiles/wcm_base/modules/contrib/defaultcontent/PATCHES.txt @@ -1,5 +1,6 @@ The following patches have been applied to this project: - http://drupal.org/files/1754428-allow-node-export-alter.patch - http://drupal.org/files/1757782-cannot-import-menu-hierarchy-8.patch +- https://www.drupal.org/files/issues/defaultcontent-php7-compat-2946138.patch This file was automatically generated by Drush Make (http://drupal.org/project/drush). diff --git a/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.info b/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.info index e18aaa6f..ef9fb68b 100644 --- a/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.info +++ b/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.info @@ -2,6 +2,7 @@ name = Default Content description = Allows import/export of default content. core = 7.x package = Features +php = 5.3 dependencies[] = features dependencies[] = ctools dependencies[] = menu diff --git a/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.module b/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.module index 93e1e8e5..d295e7ae 100644 --- a/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.module +++ b/profiles/wcm_base/modules/contrib/defaultcontent/defaultcontent.module @@ -428,7 +428,10 @@ function defaultcontent_get_alter_plugins($use = FALSE) { } if ($use) { - usort($plugins, create_function('$a, $b', "return \$a['$use weight'] - \$b['$use weight'];")); + usort($plugins, function ($a, $b) use ($use) { + $weight_key = $use . ' weight'; + return $a[$weight_key] - $b[$weight_key]; + }); } return $plugins; diff --git a/profiles/wcm_base/modules/contrib/libraries/CHANGELOG.txt b/profiles/wcm_base/modules/contrib/libraries/CHANGELOG.txt index 33fa5e8a..bec30401 100644 --- a/profiles/wcm_base/modules/contrib/libraries/CHANGELOG.txt +++ b/profiles/wcm_base/modules/contrib/libraries/CHANGELOG.txt @@ -1,4 +1,21 @@ +Libraries 7.x-2.5, 2018-10-5 +----------------------------- +#2815965 by plach, Manav, tstoeckler, Proteo: Base theme is not loaded when checking for theme library info +#2999116 by Anghelu, joshbrown81: Finds no library after update + +Libraries 7.x-2.4, 2018-09-10 +----------------------------- +#2779591 by mark_fullmer, cglauren, improved PHP 7.x.x support. +#2699799 by flaviovs, hanoii: Support reading version from package.json. +#2816781 by joelstein: Add a 'access library reports' permission. +#2823735 by amanaplan, tstoeckler: Add admin_menu cache clear integration. +#2745763 by Albert Volkman, tstoeckler: Allow downloading all libraries at once. +#2310753 by tstoeckler: Avoid libraries_get_libraries() scanning the root. +#2341955 by sadashiv, tstoeckler: Clear library cache on library report. +#819610 by tstoeckler: Show variants and dependencies in the UI. +#2724925 by ron_s, tstoeckler: Separate installed from uninstalled libraries. + Libraries 7.x-2.3, 2016-05-12 ----------------------------- #1884246 by BR0kEN, tstoeckler et al: Allow downloading libraries via Drush. @@ -94,17 +111,11 @@ by sun: Fixed testbot breaks upon .info file without .module file. #719896 by tstoeckler, sun: Added starting point for hook_libraries_info(). -Libraries 7.x-1.x, xxxx-xx-xx ------------------------------ - Libraries 7.x-1.0, 2010-01-27 ----------------------------- #743522 by sun: Ported to D7. -Libraries 6.x-1.x, xxxx-xx-xx ------------------------------ - Libraries 6.x-1.0, 2010-01-27 ----------------------------- #1028744 by tstoeckler: Code clean-up. diff --git a/profiles/wcm_base/modules/contrib/libraries/css/libraries.admin.css b/profiles/wcm_base/modules/contrib/libraries/css/libraries.admin.css new file mode 100644 index 00000000..f344ff0c --- /dev/null +++ b/profiles/wcm_base/modules/contrib/libraries/css/libraries.admin.css @@ -0,0 +1,3 @@ +.libraries-table { + margin-bottom: 2em; +} diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.admin.inc b/profiles/wcm_base/modules/contrib/libraries/libraries.admin.inc index 8d9e0fbd..29ddec14 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.admin.inc +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.admin.inc @@ -20,41 +20,112 @@ * The form array for the overview form. */ function libraries_admin_overview(array $form, array &$form_state) { - $header = array(t('Name'), t('Status'), t('Installed version'), t('Provider'), t('Links')); - $rows = array(); - - $libraries = libraries_detect(); - uasort($libraries, 'libraries_admin_sort_title'); - - foreach ($libraries as $machine_name => $library) { + // Only show variants for installed libraries. + $header_installed = array(t('Name'), t('Version'), t('Variants'), t('Dependencies'), t('Provider'), t('Links')); + // Only show status for libraries with an error. + $header_error = array(t('Name'), t('Status'), t('Version'), t('Dependencies'), t('Provider'), t('Links')); + // For unregistered libraries the only information we can show is the path. + $header_unregistered = array(t('Name'), t('Path')); + + $rows_installed = array(); + $rows_error = array(); + $rows_unregistered = array(); + + // Registered libraries: we prefer to use libraries_detect() since it provides + // library metadata. + $libraries_registered = libraries_detect(); + uasort($libraries_registered, 'libraries_admin_sort_title'); + + // Unregistered libraries: modules can depend on Libraries API without sharing + // metadata by using libraries_get_path(). Libraries can also be placed in the + // filesystem that are incorrectly installed, a wrong version, or a standalone + // not connected to any module. In these cases, libraries_get_libraries() + // provides a full library list. Libraries found by libraries_get_libraries(), + // but not identified by libraries_detect, are displayed in a separate table. + $libraries_unregistered = libraries_get_libraries(); + natcasesort($libraries_unregistered); + + foreach ($libraries_registered as $machine_name => $library) { $actions = array(); + $row = array(); if ($library['vendor url']) { - $actions[] = l('Homepage', $library['vendor url']); + $actions[] = l(t('Homepage'), $library['vendor url']); } if ($library['download url']) { - $actions[] = l('Download', $library['download url']); + $actions[] = l(t('Download'), $library['download url']); + } + + $row['data'][] = l($library['name'], 'admin/reports/libraries/' . $machine_name); + // Only show status for libraries with an error. See above. + if (!$library['installed']) { + $row['data'][] = drupal_ucfirst($library['error']); + } + $row['data'][] = isset($library['version']) ? $library['version'] : ''; + if ($library['installed']) { + $row['data'][] = implode(', ', array_keys($library['variants'])); + } + $row['data'][] = libraries_admin_get_dependencies($library); + $row['data'][] = libraries_admin_get_provider_with_type($library); + $row['data'][] = implode(' | ', $actions); + $row['class'] = $library['installed'] ? array('ok') : array('warning'); + + if ($library['installed']) { + $rows_installed[] = $row; } + else { + $rows_error[] = $row; + } + + // Filter registered libraries from unregistered libraries. + unset($libraries_unregistered[$library['machine name']]); + } + + // Build table of registered libraries with installed status. + $form['libraries']['installed'] = array( + '#theme' => 'libraries_table_with_title', + '#title' => t('Installed'), + '#header' => $header_installed, + '#rows' => $rows_installed, + '#description' => t('These libraries are registered and installed correctly.'), + '#empty' => t('There are currently no libraries that are registered and installed.'), + ); + + // Build table of registered libraries with error status. + $form['libraries']['error'] = array( + '#theme' => 'libraries_table_with_title', + '#title' => t('Uninstalled'), + '#header' => $header_error, + '#rows' => $rows_error, + '#description' => t('These libraries are registered but not installed. They may not need to be installed in case a module or theme provides optional integration with a library.'), + '#empty' => t('There are currently no libraries that are registered but not installed.'), + ); - $rows[] = array( + // Build table of unregistered libraries. + foreach ($libraries_unregistered as $name => $path) { + $rows_unregistered[] = array( 'data' => array( - l($library['name'], 'admin/reports/libraries/' . $machine_name), - ($library['installed'] ? t('OK') : drupal_ucfirst($library['error'])), - (isset($library['version']) ? $library['version'] : ''), - libraries_admin_get_provider_with_type($library), - implode(' | ', $actions), + $name, + $path, ), - 'class' => ($library['installed'] ? array('ok') : array('error')), ); } - - $form['libraries']['list'] = array( - '#theme' => 'table', - '#header' => $header, - '#rows' => $rows, - '#empty' => t('There are currently no libraries installed'), + $form['libraries']['unregistered'] = array( + '#theme' => 'libraries_table_with_title', + '#title' => t('Unregistered'), + '#header' => $header_unregistered, + '#rows' => $rows_unregistered, + '#description' => t('These libraries were found in the filesystem but there is no metadata about them.'), + // Do not show the table at all, if there are no unregistered libraries. + '#access' => (bool) $libraries_unregistered, ); + // Clear the cached library information so that the library can be loaded if + // it was just downloaded. Because these instructions use libraries_detect() + // directly, they will never use the cached information, but this avoids the + // overview showing a library as installed but it not being loadable. + libraries_cache_clear(); + return $form; } @@ -99,11 +170,11 @@ function libraries_admin_library_status_form(array $form, array &$form_state, $l break; case 'missing dependency': - $form['instructions']['instruction']['#markup'] = t('There a missing dependency in your configuration that prevent this library to work properly.') . '<br>'; + $form['instructions']['instruction']['#markup'] = t('There is a missing dependency in your configuration that prevents this library from working properly.') . '<br>'; break; case 'incompatible dependency': - $form['instructions']['instruction']['#markup'] = t('There an incompatible dependency in your configuration that prevent this library to work properly.') . '<br>'; + $form['instructions']['instruction']['#markup'] = t('There is an incompatible dependency in your configuration that prevents this library from working properly.') . '<br>'; break; } } @@ -483,6 +554,28 @@ function libraries_admin_sort_title(array $a, array $b) { return strnatcasecmp($a['name'], $b['name']); } +/** + * Returns the library's dependencies, if any. + * + * @param array $library + * A library information array. + * + * @return string + * The dependencies. + */ +function libraries_admin_get_dependencies($library) { + $dependencies = array(); + foreach ($library['dependencies'] as $dependency_name) { + if ($dependency = libraries_info($dependency_name)) { + $dependencies[] = $dependency['name']; + } + else { + $dependencies[] = $dependency_name; + } + } + return implode(', ', $dependencies); +} + /** * Returns the library's provider. * diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.api.php b/profiles/wcm_base/modules/contrib/libraries/libraries.api.php index 71e90e0c..fe0c2418 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.api.php +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.api.php @@ -47,6 +47,8 @@ * Unless 'version' is declared or libraries_get_version() is being used as * a version callback, 'version callback' must be declared. In the latter * case, however, 'version arguments' must be declared in the specified way. + * For libraries that provide a package.json file, use + * 'libraries_get_package_json_version' as the version callback. * - version arguments: (optional) A list of arguments to pass to the version * callback. Version arguments can be declared either as an associative * array whose keys are the argument names or as an indexed array without diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.drush.inc b/profiles/wcm_base/modules/contrib/libraries/libraries.drush.inc index 32587135..550b7af5 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.drush.inc +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.drush.inc @@ -23,7 +23,9 @@ function libraries_drush_command() { 'arguments' => array( 'libraries' => 'A comma delimited list of library machine names.', ), - 'required-arguments' => TRUE, + 'options' => array( + 'all' => 'Download all registered libraries.', + ), ); return $items; @@ -42,10 +44,7 @@ function libraries_drush_cache_clear(array &$types) { * Clears the library cache. */ function libraries_drush_invalidate_cache() { - // @see drupal_flush_all_caches() - foreach (libraries_flush_caches() as $table) { - cache_clear_all('*', $table, TRUE); - } + libraries_cache_clear(); } /** @@ -109,28 +108,61 @@ function drush_libraries_list() { function drush_libraries_download() { drush_command_include('pm-download'); - $libraries = libraries_info(); + $all_libraries = libraries_detect(); - // @todo Consider supporting downloading all downloadable libraries. - // @todo Consider offering a selection if no library is specified. - foreach (pm_parse_arguments(func_get_args(), FALSE) as $machine_name) { - if (!isset($libraries[$machine_name])) { - $message = dt("The !library library is not registered with Libraries API.\n", array('!library' => $machine_name)); - $message .= dt("Provide an info file for it or implement hook_libraries_info().\n"); - $message .= dt("See hook_libraries_info() for more information.\n"); - drush_set_error('DRUSH_LIBRARY_UKNOWN', $message); - continue; + // Prepare a list of names of downloadable libraries. + $downloadable_names = array(); + foreach ($all_libraries as $machine_name => $library) { + // Skip libraries that are already installed. + // @todo Allow (optionally) re-downloading installing libraries. + if (!empty($library['download file url']) && !$library['installed']) { + $downloadable_names[] = $machine_name; } - $library = $libraries[$machine_name]; + } - if (empty($library['download file url'])) { - $message = dt("The !library library cannot be downloaded.\n", array('!library' => $machine_name)); - $message .= dt("Libraries need to specify a download file URL to support being downloaded via Drush.\n"); - $message .= dt("See hook_libraries_info() for more information.\n"); - drush_set_error('DRUSH_LIBRARY_NOT_DOWNLOADABLE', $message); - continue; + // Gather a list of libraries to download. If '--all' was specified, that + // takes precedence over any other arguments. Otherwise and if no arguments + // are specified, we present a choice of all downloadable libraries. + if (drush_get_option('all', FALSE) && $downloadable_names) { + $machine_names = $downloadable_names; + } + elseif (pm_parse_arguments(func_get_args(), FALSE)) { + $machine_names = array(); + foreach (pm_parse_arguments(func_get_args(), FALSE) as $machine_name) { + // If there was an error with with one of the libraries, continue to try + // to install any remaining libraries. + if (!isset($all_libraries[$machine_name])) { + $message = dt("The !library library is not registered with Libraries API.\n", array('!library' => $machine_name)); + $message .= dt("Provide an info file for it or implement hook_libraries_info().\n"); + $message .= dt("See hook_libraries_info() for more information.\n"); + drush_set_error('DRUSH_LIBRARY_UKNOWN', $message); + continue; + } + if (empty($all_libraries[$machine_name]['download file url'])) { + $message = dt("The !library library cannot be downloaded.\n", array('!library' => $machine_name)); + $message .= dt("Libraries need to specify a download file URL to support being downloaded via Drush.\n"); + $message .= dt("See hook_libraries_info() for more information.\n"); + drush_set_error('DRUSH_LIBRARY_NOT_DOWNLOADABLE', $message); + continue; + } + $machine_names[] = $machine_name; + } + } + elseif ($downloadable_names) { + $machine_names = drush_choice_multiple(drupal_map_assoc($downloadable_names), FALSE, 'Select which libraries to download.'); + // If the operation was cancelled by the user, or if no libraries were + // selected, bail out without any further error message. + if (!$machine_names) { + return; } - $download_url = $library['download file url']; + } + else { + drush_log(dt('There are no registered, uninstalled libraries that can be downloaded.'), 'warning'); + return; + } + + foreach ($machine_names as $machine_name) { + $download_url = $all_libraries[$machine_name]['download file url']; drush_log(dt('Downloading library !name ...', array('!name' => $machine_name))); @@ -205,7 +237,7 @@ function drush_libraries_download() { drush_delete_dir($install_location, TRUE); } else { - drush_log(dt("Skip installation of !project to !dest.", array('!project' => $library['machine name'], '!dest' => $install_location)), 'warning'); + drush_log(dt("Skip installation of !project to !dest.", array('!project' => $machine_name, '!dest' => $install_location)), 'warning'); continue; } } diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.info b/profiles/wcm_base/modules/contrib/libraries/libraries.info index dcd2d486..e721cb4c 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.info +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.info @@ -8,9 +8,8 @@ files[] = tests/LibrariesLoadWebTest.test files[] = tests/LibrariesUnitTest.test files[] = tests/LibrariesWebTestBase.test -; Information added by Drupal.org packaging script on 2016-05-12 -version = "7.x-2.3" +; Information added by Drupal.org packaging script on 2018-10-05 +version = "7.x-2.5" core = "7.x" project = "libraries" -datestamp = "1463077450" - +datestamp = "1538770685" diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.install b/profiles/wcm_base/modules/contrib/libraries/libraries.install index ebc4087b..e8c795ff 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.install +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.install @@ -34,3 +34,13 @@ function libraries_update_7201() { // during the 7.x-2.x cycle. registry_rebuild(); } + +/** + * Grant the "View library reports" permission to roles with the "View site reports" permission. + */ +function libraries_update_7202() { + $rids = array_keys(user_roles(FALSE, 'access site reports')); + foreach ($rids as $rid) { + _update_7000_user_role_grant_permissions($rid, array('access library reports'), 'libraries'); + } +} diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.module b/profiles/wcm_base/modules/contrib/libraries/libraries.module index 48275250..480289cd 100644 --- a/profiles/wcm_base/modules/contrib/libraries/libraries.module +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.module @@ -25,6 +25,29 @@ function libraries_flush_caches() { } } +/** + * Implements hook_admin_menu_cache_info(). + */ +function libraries_admin_menu_cache_info() { + $caches['libraries'] = array( + 'title' => t('Libraries'), + 'callback' => 'libraries_cache_clear', + ); + return $caches; +} + +/** + * Clears the cached library information. + */ +function libraries_cache_clear() { + foreach (libraries_flush_caches() as $bin) { + // Using the wildcard argument leads to DrupalDatabaseCache::clear() + // truncating the libraries cache table which is more performant that + // deleting the rows. + cache_clear_all('*', $bin, TRUE); + } +} + /** * Gets the path of a library. * @@ -56,6 +79,52 @@ function libraries_get_path($name, $base_path = FALSE) { return $path; } +/** + * Returns all enabled themes. + * + * Themes are sorted so that base themes always precede their child themes. + * + * @return array + * An associative array of theme objects keyed by theme name. + */ +function libraries_get_enabled_themes() { + $themes = array(); + foreach (list_themes() as $name => $theme) { + if ($theme->status) { + $themes[$name] = $theme; + } + } + + return libraries_sort_themes($themes); +} + +/** + * Sort a themes array. + * + * @param array $themes + * Array of themes as objects, keyed by theme name. + * @param string $base + * A base theme (internal use only). + * + * @return array + * A similar array to $themes, but sorted in such a way that subthemes are + * always located after its base theme. + */ +function libraries_sort_themes($themes, $base = '') { + $output = array(); + foreach ($themes as $name => $theme) { + if (!isset($theme->base_theme) || $theme->base_theme == $base) { + $output[$name] = $theme; + unset($themes[$name]); + $subthemes = libraries_sort_themes($themes, $name); + foreach ($subthemes as $sub_name => $subtheme) { + $output[$sub_name] = $subtheme; + } + } + } + return $output; +} + /** * Returns an array of library directories. * @@ -77,6 +146,13 @@ function libraries_get_libraries() { $profile = drupal_get_path('profile', drupal_get_profile()); $config = conf_path(); + // $config and $profile should never be empty in a proper Drupal setup. + // However, we should never search into the root filesystem under any + // circumstances, so just bail out in that case. + if (!$profile && !$config) { + return array(); + } + // Similar to 'modules' and 'themes' directories in the root directory, // certain distributions may want to place libraries into a 'libraries' // directory in Drupal's root directory. @@ -358,10 +434,12 @@ function &libraries_info($name = NULL) { } } - // Gather information from hook_libraries_info() in enabled themes. + // Gather information from hook_libraries_info() in enabled themes. Themes + // are sorted to ensure that a base theme's template.php is included before + // its children's ones. $themes = array(); - foreach (list_themes() as $theme_name => $theme_info) { - if ($theme_info->status && file_exists(drupal_get_path('theme', $theme_name) . '/template.php')) { + foreach (libraries_get_enabled_themes() as $theme_name => $theme_info) { + if (file_exists(drupal_get_path('theme', $theme_name) . '/template.php')) { // Collect a list of viable themes for re-use when calling the alter // hook. $themes[] = $theme_name; @@ -546,7 +624,7 @@ function libraries_detect($name = NULL) { $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments'])); } else { - $library['version'] = call_user_func($library['version callback'], $library, $library['version arguments']); + $library['version'] = call_user_func_array($library['version callback'], array(&$library, $library['version arguments'])); } if (empty($library['version'])) { $library['error'] = 'not detected'; @@ -887,16 +965,56 @@ function libraries_get_version($library, $options) { fclose($file); } +/** + * Gets the version information from a library's package.json file. + * + * @param $library + * An associative array containing all information about the library. + * @param $options + * This callback expects no option. + * @return + * A string containing the version of the library. + * + * @see libraries_get_path() + */ +function libraries_get_package_json_version($library, $options) { + $file = DRUPAL_ROOT . '/' . $library['library path'] . '/package.json'; + if (!file_exists($file)) { + return; + } + + $content = file_get_contents($file); + if (!$content) { + return; + } + + $data = drupal_json_decode($content); + if (isset($data['version'])) { + return $data['version']; + } +} + /** * Implements hook_help(). */ function libraries_help($path, $arg) { switch ($path) { case 'admin/reports/libraries': - return t('Click on a library for a status report or detailed installation instructions in case the library is not installed correctly.'); + return t('Click on a library for a status report or detailed installation instructions.'); } } +/** + * Implements hook_permission(). + */ +function libraries_permission() { + return array( + 'access library reports' => array( + 'title' => t('View library reports'), + ), + ); +} + /** * Implements hook_menu(). */ @@ -907,7 +1025,7 @@ function libraries_menu() { 'description' => 'An overview of libraries installed on this site.', 'page callback' => 'drupal_get_form', 'page arguments' => array('libraries_admin_overview'), - 'access arguments' => array('access site reports'), + 'access arguments' => array('access library reports'), 'file' => 'libraries.admin.inc' ); $items['admin/reports/libraries/%libraries_ui'] = array( @@ -915,7 +1033,7 @@ function libraries_menu() { 'description' => 'Status overview for a single library', 'page callback' => 'drupal_get_form', 'page arguments' => array('libraries_admin_library_status_form', 3), - 'access arguments' => array('access site reports'), + 'access arguments' => array('access library reports'), 'file' => 'libraries.admin.inc' ); return $items; @@ -944,3 +1062,19 @@ function libraries_menu() { function libraries_ui_load($name) { return libraries_detect($name); } + +/** + * Implements hook_theme(). + */ +function libraries_theme($existing, $type, $theme, $path) { + // Because we extend the 'table' theme function, fetch the respective + // variables dynamically. + $common_theme = drupal_common_theme(); + $variables = $common_theme['table']['variables'] + array('title' => '', 'description' => ''); + return array( + 'libraries_table_with_title' => array( + 'variables' => $variables, + 'file' => 'libraries.theme.inc', + ), + ); +} diff --git a/profiles/wcm_base/modules/contrib/libraries/libraries.theme.inc b/profiles/wcm_base/modules/contrib/libraries/libraries.theme.inc new file mode 100644 index 00000000..ff3ed719 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/libraries/libraries.theme.inc @@ -0,0 +1,36 @@ +<?php + +/** + * @file + * Provides theme and preprocess functions for Libraries API. + */ + +/** + * Prepare variables for theming a table with a title. + * + * @param array $variables + * An array of theme variables, passed by reference. + */ +function template_preprocess_libraries_table_with_title(&$variables) { + drupal_add_css(drupal_get_path('module', 'libraries') . '/css/libraries.admin.css'); + + $variables['attributes'] += array('class' => array()); + $variables['attributes']['class'][] = 'libraries-table'; +} + +/** + * Returns HTML for a table with a title. + * + * @param array $variables + * An array theme variables. + * + * @return string + * The HTML output for this table with a title. + */ +function theme_libraries_table_with_title(array $variables) { + $output = ''; + $output .= '<h2>' . $variables['title'] . '</h2>'; + $output .= '<div class="description">' . $variables['description'] . '</div>'; + $output .= theme_table($variables); + return $output; +} diff --git a/profiles/wcm_base/modules/contrib/libraries/tests/LibrariesAdminWebTest.test b/profiles/wcm_base/modules/contrib/libraries/tests/LibrariesAdminWebTest.test index a4d2188b..87c9de0e 100644 --- a/profiles/wcm_base/modules/contrib/libraries/tests/LibrariesAdminWebTest.test +++ b/profiles/wcm_base/modules/contrib/libraries/tests/LibrariesAdminWebTest.test @@ -40,8 +40,20 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { * Tests the libraries report at /admin/reports/libraries. */ public function testLibrariesReportOverview() { - $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries'); - $this->assertRaw('Libraries'); + $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries'); + // Assert the page title and table titles show up. + $this->assertText('Libraries'); + $this->assertRaw('<h2>Installed</h2>'); + $this->assertRaw('<h2>Uninstalled</h2>'); + + // Make sure the table headings show up. + $this->assertText('Name'); + $this->assertText('Status'); + $this->assertText('Version'); + $this->assertText('Variants'); + $this->assertText('Dependencies'); + $this->assertText('Provider'); + $this->assertText('Links'); // Make sure that all the libraries are listed. $libraries = libraries_info(); @@ -51,8 +63,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { $this->assertLinkByHref('admin/reports/libraries/' . $library['machine name']); } - // Make sure that all possible statuses are displayed. - $this->assertText('OK'); + // Make sure that all possible error statuses are displayed. $this->assertText('Not found'); $this->assertText('Not detected'); $this->assertText('Not supported'); @@ -73,7 +84,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { * Tests the libraries report for an installed library. */ public function testLibrariesReportInstalled() { - $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_files'); + $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_files'); $this->assertRaw('Status report for library <em class="placeholder">Example files</em>'); $this->assertRaw('The <em class="placeholder">Example files</em> library is installed correctly.'); // Check that the information in the status report is displayed. @@ -88,7 +99,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { * Tests the libraries report for a missing library. */ public function testLibrariesReportMissing() { - $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_missing'); + $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_missing'); $this->assertRaw('Status report for library <em class="placeholder">Example missing</em>'); $this->assertRaw('The <em class="placeholder">Example missing</em> library could not be found.'); // Check that the download link is being displayed. @@ -100,7 +111,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { * Tests the libraries report for a missing library. */ public function testLibrariesReportNotDetected() { - $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_undetected_version'); + $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_undetected_version'); $this->assertRaw('Status report for library <em class="placeholder">Example undetected version</em>'); $this->assertRaw('The version of the <em class="placeholder">Example undetected version</em> library could not be detected.'); } @@ -109,7 +120,7 @@ class LibrariesAdminWebTest extends LibrariesWebTestBase { * Tests the libraries report for a missing library. */ public function testLibrariesReportNotSupported() { - $this->getWithPermissions(array('access site reports'), 'admin/reports/libraries/example_unsupported_version'); + $this->getWithPermissions(array('access library reports'), 'admin/reports/libraries/example_unsupported_version'); $this->assertRaw('Status report for library <em class="placeholder">Example unsupported version</em>'); $this->assertRaw('The installed version <em class="placeholder">1</em> of the <em class="placeholder">Example unsupported version</em> library is not supported.'); // Check that the download link is being displayed. diff --git a/profiles/wcm_base/modules/contrib/libraries/tests/libraries/example_info_file.libraries.info b/profiles/wcm_base/modules/contrib/libraries/tests/libraries/example_info_file.libraries.info index 11152731..83ba8a83 100644 --- a/profiles/wcm_base/modules/contrib/libraries/tests/libraries/example_info_file.libraries.info +++ b/profiles/wcm_base/modules/contrib/libraries/tests/libraries/example_info_file.libraries.info @@ -2,9 +2,8 @@ name = Example info file -; Information added by Drupal.org packaging script on 2016-05-12 -version = "7.x-2.3" +; Information added by Drupal.org packaging script on 2018-10-05 +version = "7.x-2.5" core = "7.x" project = "libraries" -datestamp = "1463077450" - +datestamp = "1538770685" diff --git a/profiles/wcm_base/modules/contrib/libraries/tests/modules/libraries_test_module/libraries_test_module.info b/profiles/wcm_base/modules/contrib/libraries/tests/modules/libraries_test_module/libraries_test_module.info index 7ad319a2..756d6a8f 100644 --- a/profiles/wcm_base/modules/contrib/libraries/tests/modules/libraries_test_module/libraries_test_module.info +++ b/profiles/wcm_base/modules/contrib/libraries/tests/modules/libraries_test_module/libraries_test_module.info @@ -5,9 +5,8 @@ package = Testing dependencies[] = libraries hidden = TRUE -; Information added by Drupal.org packaging script on 2016-05-12 -version = "7.x-2.3" +; Information added by Drupal.org packaging script on 2018-10-05 +version = "7.x-2.5" core = "7.x" project = "libraries" -datestamp = "1463077450" - +datestamp = "1538770685" diff --git a/profiles/wcm_base/modules/contrib/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info b/profiles/wcm_base/modules/contrib/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info index 255d1040..194954e7 100644 --- a/profiles/wcm_base/modules/contrib/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info +++ b/profiles/wcm_base/modules/contrib/libraries/tests/themes/libraries_test_theme/libraries_test_theme.info @@ -3,9 +3,8 @@ description = Tests that themes can provide and alter library information. core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2016-05-12 -version = "7.x-2.3" +; Information added by Drupal.org packaging script on 2018-10-05 +version = "7.x-2.5" core = "7.x" project = "libraries" -datestamp = "1463077450" - +datestamp = "1538770685" diff --git a/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.info b/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.info index 87032aca..bca184fd 100644 --- a/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.info +++ b/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.info @@ -5,9 +5,8 @@ package = Panels dependencies[] = ctools dependencies[] = page_manager dependencies[] = panels -; Information added by Drupal.org packaging script on 2014-09-12 -version = "7.x-2.2" +; Information added by Drupal.org packaging script on 2018-08-27 +version = "7.x-2.3" core = "7.x" project = "panels_breadcrumbs" -datestamp = "1410481728" - +datestamp = "1535382184" diff --git a/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.module b/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.module index d009364c..04939dc0 100644 --- a/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.module +++ b/profiles/wcm_base/modules/contrib/panels_breadcrumbs/panels_breadcrumbs.module @@ -18,7 +18,7 @@ function panels_breadcrumbs_page_manager_variant_operations_alter(&$operations, // Use this obnoxious construct to safely insert our item. reset($operations['children']); $children_operations = array(); - while (list($key, $value) = each($operations['children'])) { + foreach ($operations['children'] as $key => $value) { $children_operations[$key] = $value; if ($key == 'context') { $children_operations['breadcrumb'] = array( @@ -156,62 +156,74 @@ function panels_breadcrumbs_partial_configuration_form($conf, $contexts) { * FALSE if the breadcrumb could not be built with the given configuration. */ function panels_breadcrumbs_build_breadcrumb($conf, $contexts, $override = FALSE) { - $breadcrumbs = array(); - - // If no titles or paths are defined, bail out. - if (!isset($conf['panels_breadcrumbs_titles']) || !isset($conf['panels_breadcrumbs_paths'])) { - return; - } - - // Look for placeholder tokens in paths and convert them for this display - $titles = $conf['panels_breadcrumbs_titles']; - $paths = ctools_context_keyword_substitute($conf['panels_breadcrumbs_paths'], array(), $contexts); + $breadcrumbs = &drupal_static(__FUNCTION__); + + if (empty($breadcrumbs)) { + // If no titles or paths are defined, bail out. + if (!isset($conf['panels_breadcrumbs_titles']) || !isset($conf['panels_breadcrumbs_paths'])) { + // Do not store anything in the static $breadcrumbs variable, in order to + // allow a possible fallback with another breadcrumb configuration. + return; + } - // Break titles and paths into arrays and remove empty keys - $titles = array_filter(array_map('trim', explode(PHP_EOL, $titles)), 'strlen'); - $paths = array_filter(array_map('trim', explode(PHP_EOL, $paths)), 'strlen'); + // The configuration is active and is the first triggered, so we don't allow + // another breadcrumb configuration to override it by setting the static + // variable. + $breadcrumbs = array(); + + // Look for placeholder tokens in paths and convert them for this display + $titles = $conf['panels_breadcrumbs_titles']; + $paths = ctools_context_keyword_substitute($conf['panels_breadcrumbs_paths'], array(), $contexts); + + // Break titles and paths into arrays and remove empty keys + $titles = array_filter(array_map('trim', explode("\n", $titles)), 'strlen'); + $paths = array_filter(array_map('trim', explode("\n", $paths)), 'strlen'); + + // We add in path as although it is not used to render breadcrumbs, it is + // required by user_menu_breadcrumb_alter(). + $default_breadcrumb_info = array( + 'title' => '', + 'href' => '', + 'localized_options' => array(), + 'path' => '', + ); - $default_breadcrumb_info = array( - 'title' => '', - 'href' => '', - 'localized_options' => array(), - ); + $breadcrumbs_info = array(); - $breadcrumbs_info = array(); + // Set the first crumb to home + if (!isset($conf['panels_breadcrumbs_home']) || $conf['panels_breadcrumbs_home'] == TRUE) { + $breadcrumbs_info[] = array('title' => t('Home'), 'href' => '<front>') + $default_breadcrumb_info; + } - // Set the first crumb to home - if (!isset($conf['panels_breadcrumbs_home']) || $conf['panels_breadcrumbs_home'] == TRUE) { - $breadcrumbs_info[] = array('title' => t('Home'), 'href' => '<front>') + $default_breadcrumb_info; - } + // Iterate through all crumbs and add them to the breadcrumb + foreach ($titles as $key => $title) { - // Iterate through all crumbs and add them to the breadcrumb - foreach ($titles as $key => $title) { + // Translate the title and convert existing placeholder tokens afterwards. + $translated_title = t($title); + $translated_title = ctools_context_keyword_substitute($translated_title, array(), $contexts); - // Translate the title and convert existing placeholder tokens afterwards. - $translated_title = t($title); - $translated_title = ctools_context_keyword_substitute($translated_title, array(), $contexts); + if (empty($translated_title)) { + continue; + } - if (empty($translated_title)) { - continue; + $translated_title = html_entity_decode(trim($translated_title), ENT_QUOTES, 'UTF-8'); + $path = empty($paths[$key]) ? '<none>' : trim($paths[$key]); + $breadcrumbs_info[] = array('title' => $translated_title, 'href' => $path) + $default_breadcrumb_info; } - $translated_title = html_entity_decode(trim($translated_title), ENT_QUOTES, 'UTF-8'); - $path = empty($paths[$key]) ? '<none>' : trim($paths[$key]); - $breadcrumbs_info[] = array('title' => $translated_title, 'href' => $path) + $default_breadcrumb_info; - } - - // Allow other modules to intercept and operate changes in the breadcrumb - $breadcrumb_info_end = end($breadcrumbs_info); - drupal_alter('menu_breadcrumb', $breadcrumbs_info, $breadcrumb_info_end); - - // Finally, render the breadcrumb - foreach ($breadcrumbs_info as $crumb) { - if (isset($crumb['href']) && $crumb['href'] == '<none>') { - $crumb['localized_options'] += array('attributes' => array(), 'html' => TRUE); - $breadcrumbs[] = '<span ' . drupal_attributes($crumb['localized_options']['attributes']) . '>' . ($crumb['localized_options']['html'] ? $crumb['title'] : check_plain($crumb['title'])) . '</span>'; - } - else { - $breadcrumbs[] = l($crumb['title'], $crumb['href'], $crumb['localized_options']); + // Allow other modules to intercept and operate changes in the breadcrumb + $breadcrumb_info_end = end($breadcrumbs_info); + drupal_alter('menu_breadcrumb', $breadcrumbs_info, $breadcrumb_info_end); + + // Finally, render the breadcrumb + foreach ($breadcrumbs_info as $crumb) { + if (isset($crumb['href']) && $crumb['href'] == '<none>') { + $crumb['localized_options'] += array('attributes' => array(), 'html' => TRUE); + $breadcrumbs[] = '<span ' . drupal_attributes($crumb['localized_options']['attributes']) . '>' . ($crumb['localized_options']['html'] ? $crumb['title'] : check_plain($crumb['title'])) . '</span>'; + } + else { + $breadcrumbs[] = l($crumb['title'], $crumb['href'], $crumb['localized_options']); + } } } diff --git a/profiles/wcm_base/modules/contrib/search_api/CHANGELOG.txt b/profiles/wcm_base/modules/contrib/search_api/CHANGELOG.txt index 24c120fe..1b61a9a1 100644 --- a/profiles/wcm_base/modules/contrib/search_api/CHANGELOG.txt +++ b/profiles/wcm_base/modules/contrib/search_api/CHANGELOG.txt @@ -1,3 +1,25 @@ +Search API 1.25 (2018-09-17): +----------------------------- +- #2408727 by swim, drunken monkey: Added a batch operation for executing + pending tasks. +- #2325917 by guillaumev, drunken monkey: Added a Views cache plugin based on + Views Content Cache. +- #2989578 by KarlShea, drunken monkey: Fixed Views exposed form fields for + "not between" operator. +- #2982167 by osopolar, drunken monkey: Added a Drush command for re-indexing + specific entities. +- #1783746 by das-peter, sammys, SpadXIII, drunken monkey, ruloweb, KarlShea, + heshanlk, Anas_maw, pinkonomy, Damien Tournoud, rudiedirkx: Added support + for the "(not) between" operator. +- #2408727 by drunken monkey, OliverColeman: Fixed out-of-memory errors when + executing pending tasks. +- Issue #2948820 by capysara, drunken monkey: Added a link to the "need to + reindex" message on the Filters tab. +- #2828883 by JorgenSandstrom, drunken monkey: Fixed property type for + string-typed aggregated fields. +- #2949899 by drunken monkey, DamienMcKenna: Added a warning against using + particular processors with Solr servers to the "Workflow" tab. + Search API 1.24 (2018-04-05): ----------------------------- - #2958201 by jcnventura, drunken monkey: Reverted issue #2566529: Added diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_facetapi/search_api_facetapi.info b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_facetapi/search_api_facetapi.info index 9c80f6e6..2fd1c653 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_facetapi/search_api_facetapi.info +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_facetapi/search_api_facetapi.info @@ -9,8 +9,8 @@ files[] = plugins/facetapi/adapter.inc files[] = plugins/facetapi/query_type_term.inc files[] = plugins/facetapi/query_type_date.inc -; Information added by Drupal.org packaging script on 2018-04-05 -version = "7.x-1.24" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.25" core = "7.x" project = "search_api" -datestamp = "1522913891" +datestamp = "1537171099" diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/README.txt b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/README.txt index b36a7b55..50cfce1c 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/README.txt +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/README.txt @@ -40,6 +40,21 @@ in that position. If the query is sorted in this way, then the random sort, as an associative array with any of the following keys: - seed: A numeric seed value to use for the random sort. +"BETWEEN operator" feature +-------------------------- +This module defines the "BETWEEN operator" feature (feature key: +"search_api_between") that adds the "BETWEEN" and "NOT BETWEEN" filter +operators to search queries. If your search server supports this feature, you +can use the "Is between" and "Is not between" operators when adding Views +filters for numeric, string or date types. + +For developers: +A service class that wants to support this feature has to accept "BETWEEN" and +"NOT BETWEEN" as additional $operator values in query conditions. The value in +both cases is an array with the keys 0 and 1, with the value under key 0 being +the lower and the value under key 1 being the upper bound for the range in which +the field's value should ("BETWEEN") or should not ("NOT BETWEEN") be. + "Facets block" display ---------------------- Most features should be clear to users of Views. However, the module also diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_date.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_date.inc index c7897245..1259aa0b 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_date.inc +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_date.inc @@ -6,9 +6,9 @@ */ /** - * Views filter handler base class for handling all "normal" cases. + * Views filter handler base class for handling date fields. */ -class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter { +class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilterNumeric { /** * Add a "widget type" option. @@ -88,9 +88,22 @@ class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter { public function value_form(&$form, &$form_state) { parent::value_form($form, $form_state); + $is_date_popup = ($this->options['widget_type'] == 'date_popup' && module_exists('date_popup')); + + // If the operator is between + if ($this->operator == 'between') { + if ($is_date_popup) { + $form['value']['min']['#type'] = 'date_popup'; + $form['value']['min']['#date_format'] = $this->options['date_popup_format']; + $form['value']['min']['#date_year_range'] = $this->options['year_range']; + $form['value']['max']['#type'] = 'date_popup'; + $form['value']['max']['#date_format'] = $this->options['date_popup_format']; + $form['value']['max']['#date_year_range'] = $this->options['year_range']; + } + } // If we are using the date popup widget, overwrite the settings of the form // according to what date_popup expects. - if ($this->options['widget_type'] == 'date_popup' && module_exists('date_popup')) { + elseif ($is_date_popup) { $form['value']['#type'] = 'date_popup'; $form['value']['#date_format'] = $this->options['date_popup_format']; $form['value']['#date_year_range'] = $this->options['year_range']; @@ -115,11 +128,31 @@ class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter { elseif ($this->operator === 'not empty') { $this->query->condition($this->real_field, NULL, '<>', $this->options['group']); } - else { - while (is_array($this->value)) { - $this->value = $this->value ? reset($this->value) : NULL; + elseif (in_array($this->operator, array('between', 'not between'), TRUE)) { + $min = isset($this->value[0]['min']) ? $this->value[0]['min'] : ''; + if ($min !== '') { + $min = is_numeric($min) ? $min : strtotime($min, REQUEST_TIME); + } + $max = isset($this->value[0]['max']) ? $this->value[0]['max'] : ''; + if ($max !== '') { + $max = is_numeric($max) ? $max : strtotime($max, REQUEST_TIME); } - $v = is_numeric($this->value) ? $this->value : strtotime($this->value, REQUEST_TIME); + + if (is_numeric($min) && is_numeric($max)) { + $this->query->condition($this->real_field, array($min, $max), strtoupper($this->operator), $this->options['group']); + } + elseif (is_numeric($min)) { + $operator = $this->operator === 'between' ? '>=' : '<'; + $this->query->condition($this->real_field, $min, $operator, $this->options['group']); + } + elseif (is_numeric($max)) { + $operator = $this->operator === 'between' ? '<=' : '>'; + $this->query->condition($this->real_field, $min, $operator, $this->options['group']); + } + } + else { + $value = isset($this->value[0]) ? $this->value[0]['value'] : $this->value['value']; + $v = is_numeric($value) ? $value : strtotime($value, REQUEST_TIME); if ($v !== FALSE) { $this->query->condition($this->real_field, $v, $this->operator, $this->options['group']); } diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc new file mode 100644 index 00000000..f29a3e6e --- /dev/null +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc @@ -0,0 +1,217 @@ +<?php + +/** + * @file + * Contains SearchApiViewsHandlerFilterNumeric. + */ + +/** + * Views filter handler class for handling numeric and "string" fields. + */ +class SearchApiViewsHandlerFilterNumeric extends SearchApiViewsHandlerFilter { + + /** + * {@inheritdoc} + */ + public function option_definition() { + $options = parent::option_definition(); + $options['value'] = array( + 'contains' => array( + 'value' => array('default' => ''), + 'min' => array('default' => ''), + 'max' => array('default' => ''), + ), + ); + + return $options; + } + + /** + * {@inheritdoc} + */ + public function operator_options() { + $operators = parent::operator_options(); + + $index = search_api_index_load(substr($this->table, 17)); + $server = NULL; + try { + if ($index) { + $server = $index->server(); + } + } + catch (SearchApiException $e) { + // Ignore. + } + if ($server && $server->supportsFeature('search_api_between')) { + $operators += array( + 'between' => t('Is between'), + 'not between' => t('Is not between'), + ); + } + + return $operators; + } + + /** + * Provides a form for setting the filter value. + * + * Heavily borrowed from views_handler_filter_numeric. + * + * @see views_handler_filter_numeric::value_form() + */ + public function value_form(&$form, &$form_state) { + $form['value']['#tree'] = TRUE; + + $single_field_operators = $this->operator_options(); + unset( + $single_field_operators['empty'], + $single_field_operators['not empty'], + $single_field_operators['between'], + $single_field_operators['not between'] + ); + $between_operators = array('between', 'not between'); + + // We have to make some choices when creating this as an exposed + // filter form. For example, if the operator is locked and thus + // not rendered, we can't render dependencies; instead we only + // render the form items we need. + $which = 'all'; + $source = NULL; + if (!empty($form['operator'])) { + $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator'; + } + + $identifier = NULL; + if (!empty($form_state['exposed'])) { + $identifier = $this->options['expose']['identifier']; + if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) { + // Exposed and locked. + $which = in_array($this->operator, $between_operators) ? 'minmax' : 'value'; + } + else { + $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']); + } + } + + // Hide the value box if the operator is 'empty' or 'not empty'. + // Radios share the same selector so we have to add some dummy selector. + if ($which == 'all') { + $form['value']['value'] = array( + '#type' => 'textfield', + '#title' => empty($form_state['exposed']) ? t('Value') : '', + '#size' => 30, + '#default_value' => $this->value['value'], + '#dependency' => array($source => array_keys($single_field_operators)), + ); + if ($identifier && !isset($form_state['input'][$identifier]['value'])) { + $form_state['input'][$identifier]['value'] = $this->value['value']; + } + } + elseif ($which == 'value') { + // When exposed we drop the value-value and just do value if + // the operator is locked. + $form['value'] = array( + '#type' => 'textfield', + '#title' => empty($form_state['exposed']) ? t('Value') : '', + '#size' => 30, + '#default_value' => isset($this->value['value']) ? $this->value['value'] : '', + ); + if ($identifier && !isset($form_state['input'][$identifier])) { + $form_state['input'][$identifier] = isset($this->value['value']) ? $this->value['value'] : ''; + } + } + + if ($which == 'all' || $which == 'minmax') { + $form['value']['min'] = array( + '#type' => 'textfield', + '#title' => empty($form_state['exposed']) ? t('Min') : '', + '#size' => 30, + '#default_value' => $this->value['min'], + ); + $form['value']['max'] = array( + '#type' => 'textfield', + '#title' => empty($form_state['exposed']) ? t('And max') : t('And'), + '#size' => 30, + '#default_value' => $this->value['max'], + ); + + if ($which == 'all') { + $form['value']['min']['#dependency'] = array($source => $between_operators); + $form['value']['max']['#dependency'] = array($source => $between_operators); + } + + if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min'])) { + $form_state['input'][$identifier]['min'] = $this->value['min']; + } + if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max'])) { + $form_state['input'][$identifier]['max'] = $this->value['max']; + } + + if (!isset($form['value']['value'])) { + // Ensure there is something in the 'value'. + $form['value']['value'] = array( + '#type' => 'value', + '#value' => NULL, + ); + } + } + } + + /** + * {@inheritdoc} + */ + public function admin_summary() { + if (!empty($this->options['exposed'])) { + return t('exposed'); + } + + if ($this->operator === 'empty') { + return t('is empty'); + } + if ($this->operator === 'not empty') { + return t('is not empty'); + } + + $value = isset($this->value[0]) ? $this->value[0] : $this->value; + + if (in_array($this->operator, array('between', 'not between'), TRUE)) { + // This is of course wrong for translation purposes, but copied from + // views_handler_filter_numeric::admin_summary() so probably still better + // to re-use this than to do it correctly. + $operator = $this->operator === 'between' ? t('between') : t('not between'); + $vars = array( + '@min' => (string) $value['min'], + '@max' => (string) $value['max'], + ); + return $operator . ' ' . t('@min and @max', $vars); + } + + return check_plain((string) $this->operator) . ' ' . check_plain((string) $value['value']); + + } + + /** + * {@inheritdoc} + */ + public function query() { + if (in_array($this->operator, array('between', 'not between'), TRUE)) { + $min = isset($this->value[0]['min']) ? $this->value[0]['min'] : ''; + $max = isset($this->value[0]['max']) ? $this->value[0]['max'] : ''; + if ($min !== '' && $max !== '') { + $this->query->condition($this->real_field, array($min, $max), strtoupper($this->operator), $this->options['group']); + } + elseif ($min !== '') { + $operator = $this->operator === 'between' ? '>=' : '<'; + $this->query->condition($this->real_field, $min, $operator, $this->options['group']); + } + elseif ($max !== '') { + $operator = $this->operator === 'between' ? '<=' : '>'; + $this->query->condition($this->real_field, $min, $operator, $this->options['group']); + } + } + else { + parent::query(); + } + } + +} diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_options.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_options.inc index 3040fb0f..2184fc85 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_options.inc +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/handler_filter_options.inc @@ -121,6 +121,7 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter { */ public function option_definition() { $options = parent::option_definition(); + $options['value'] = array('default' => ''); $options['expose']['contains']['reduce'] = array('default' => FALSE); return $options; } diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_cache.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_cache.inc index c6bd41d4..c63aed5e 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_cache.inc +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_cache.inc @@ -35,11 +35,16 @@ class SearchApiViewsCache extends views_plugin_cache_time { } $cid = $this->get_results_key(); + $results = NULL; + $query_plugin = $this->view->query; + if ($query_plugin instanceof SearchApiViewsQuery) { + $results = $query_plugin->getSearchApiResults(); + } $data = array( 'result' => $this->view->result, 'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0, 'current_page' => $this->view->get_current_page(), - 'search_api results' => $this->view->query->getSearchApiResults(), + 'search_api results' => $results, ); cache_set($cid, $data, $this->table, $this->cache_set_expire($type)); } @@ -80,7 +85,7 @@ class SearchApiViewsCache extends views_plugin_cache_time { * Overrides views_plugin_cache::get_cache_key(). * * Use the Search API query as the main source for the key. Note that in - * Views < 3.8, this function does not exist. + * Views < 3.8, this method does not exist. */ public function get_cache_key($key_data = array()) { global $user; @@ -121,7 +126,7 @@ class SearchApiViewsCache extends views_plugin_cache_time { } /** - * Get the Search API query object associated with the current view. + * Retrieves the Search API query object associated with the current view. * * @return SearchApiQueryInterface|null * The Search API query object associated with the current view; or NULL if diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_content_cache.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_content_cache.inc new file mode 100644 index 00000000..555fe89a --- /dev/null +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/includes/plugin_content_cache.inc @@ -0,0 +1,146 @@ +<?php + +/** + * @file + * Contains the SearchApiViewsContentCache class. + */ + +/** + * Plugin class for caching Search API views, with additional invalidation. + */ +class SearchApiViewsContentCache extends views_content_cache_plugin_cache { + + /** + * Static cache for get_results_key(). + * + * @var string + */ + protected $_results_key = NULL; + + /** + * Static cache for getSearchApiQuery(). + * + * @var SearchApiQueryInterface + */ + protected $search_api_query = NULL; + + /** + * Overrides views_plugin_cache::cache_set(). + * + * Also stores Search API's internal search results. + */ + public function cache_set($type) { + if ($type != 'results') { + return parent::cache_set($type); + } + + $cid = $this->get_results_key(); + $results = NULL; + $query_plugin = $this->view->query; + if ($query_plugin instanceof SearchApiViewsQuery) { + $results = $query_plugin->getSearchApiResults(); + } + $data = array( + 'result' => $this->view->result, + 'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0, + 'current_page' => $this->view->get_current_page(), + 'search_api results' => $results, + ); + cache_set($cid, $data, $this->table, $this->cache_set_expire($type)); + } + + /** + * Overrides views_plugin_cache::cache_get(). + * + * Additionally stores successfully retrieved results with + * search_api_current_search(). + */ + public function cache_get($type) { + if ($type != 'results') { + return parent::cache_get($type); + } + + // Values to set: $view->result, $view->total_rows, $view->execute_time, + // $view->current_page. + if ($cache = cache_get($this->get_results_key(), $this->table)) { + $cutoff = $this->cache_expire($type); + if (!$cutoff || $cache->created > $cutoff) { + $this->view->result = $cache->data['result']; + $this->view->total_rows = $cache->data['total_rows']; + $this->view->set_current_page($cache->data['current_page']); + $this->view->execute_time = 0; + + // Trick Search API into believing a search happened, to make facetting + // et al. work. + $query = $this->getSearchApiQuery(); + search_api_current_search($query->getOption('search id'), $query, $cache->data['search_api results']); + + return TRUE; + } + } + return FALSE; + } + + /** + * Overrides views_plugin_cache::get_cache_key(). + * + * Use the Search API query as the main source for the key. Note that in + * Views < 3.8, this method does not exist. + */ + public function get_cache_key($key_data = array()) { + global $user; + + if (!isset($this->_results_key)) { + $query = $this->getSearchApiQuery(); + $query->preExecute(); + $key_data += array( + 'query' => $query, + 'roles' => array_keys($user->roles), + 'super-user' => $user->uid == 1, // special caching for super user. + 'language' => $GLOBALS['language']->language, + 'base_url' => $GLOBALS['base_url'], + 'offset' => $this->view->get_current_page() . '*' . $this->view->get_items_per_page() . '+' . $this->view->get_offset(), + ); + // Not sure what gets passed in exposed_info, so better include it. All + // other parameters used in the parent method are already reflected in the + // Search API query object we use. + if (isset($_GET['exposed_info'])) { + $key_data['exposed_info'] = $_GET['exposed_info']; + } + } + $key = drupal_hash_base64(serialize($key_data)); + return $key; + } + + /** + * Overrides views_plugin_cache::get_results_key(). + * + * This is unnecessary for Views >= 3.8. + */ + public function get_results_key() { + if (!isset($this->_results_key)) { + $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . $this->get_cache_key(); + } + + return $this->_results_key; + } + + /** + * Retrieves the Search API query object associated with the current view. + * + * @return SearchApiQueryInterface|null + * The Search API query object associated with the current view; or NULL if + * there is none. + */ + protected function getSearchApiQuery() { + if (!isset($this->search_api_query)) { + $this->search_api_query = FALSE; + if (isset($this->view->query) && $this->view->query instanceof SearchApiViewsQuery) { + $this->search_api_query = $this->view->query->getSearchApiQuery(); + } + } + + return $this->search_api_query ? $this->search_api_query : NULL; + } + +} diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.info b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.info index 82c2f8f3..ee66b2fb 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.info +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.info @@ -19,16 +19,18 @@ files[] = includes/handler_filter_date.inc files[] = includes/handler_filter_entity.inc files[] = includes/handler_filter_fulltext.inc files[] = includes/handler_filter_language.inc +files[] = includes/handler_filter_numeric.inc files[] = includes/handler_filter_options.inc files[] = includes/handler_filter_taxonomy_term.inc files[] = includes/handler_filter_text.inc files[] = includes/handler_filter_user.inc files[] = includes/handler_sort.inc files[] = includes/plugin_cache.inc +files[] = includes/plugin_content_cache.inc files[] = includes/query.inc -; Information added by Drupal.org packaging script on 2018-04-05 -version = "7.x-1.24" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.25" core = "7.x" project = "search_api" -datestamp = "1522913891" +datestamp = "1537171099" diff --git a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.views.inc b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.views.inc index ff52d692..cc1cf4e5 100644 --- a/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.views.inc +++ b/profiles/wcm_base/modules/contrib/search_api/contrib/search_api_views/search_api_views.views.inc @@ -219,6 +219,9 @@ function _search_api_views_add_handlers($id, array $field, EntityMetadataWrapper $table[$id]['filter']['vocabulary'] = $vocabulary; } } + elseif (in_array($inner_type, array('integer', 'decimal', 'duration', 'string'))) { + $table[$id]['filter']['handler'] = 'SearchApiViewsHandlerFilterNumeric'; + } else { $table[$id]['filter']['handler'] = 'SearchApiViewsHandlerFilter'; } @@ -285,6 +288,16 @@ function search_api_views_views_plugins() { ); } + if (module_exists('views_content_cache')) { + $ret['cache']['search_api_views_content_cache'] = array( + 'title' => t('Search-specific content-based'), + 'help' => t("Cache Search API views based on content updates. (Requires Views Content Cache)"), + 'base' => $bases, + 'handler' => 'SearchApiViewsContentCache', + 'uses options' => TRUE, + ); + } + return $ret; } diff --git a/profiles/wcm_base/modules/contrib/search_api/includes/callback_add_aggregation.inc b/profiles/wcm_base/modules/contrib/search_api/includes/callback_add_aggregation.inc index 2e744f60..55ed611c 100644 --- a/profiles/wcm_base/modules/contrib/search_api/includes/callback_add_aggregation.inc +++ b/profiles/wcm_base/modules/contrib/search_api/includes/callback_add_aggregation.inc @@ -328,10 +328,10 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback { 'count' => 'integer', 'max' => 'integer', 'min' => 'integer', - 'first' => 'string', - 'first_char' => 'string', - 'last' => 'string', - 'list' => 'list<string>', + 'first' => 'token', + 'first_char' => 'token', + 'last' => 'token', + 'list' => 'list<token>', ); case 'description': return array( diff --git a/profiles/wcm_base/modules/contrib/search_api/search_api.admin.inc b/profiles/wcm_base/modules/contrib/search_api/search_api.admin.inc index 3afbaa78..89680dbf 100644 --- a/profiles/wcm_base/modules/contrib/search_api/search_api.admin.inc +++ b/profiles/wcm_base/modules/contrib/search_api/search_api.admin.inc @@ -528,7 +528,7 @@ function theme_search_api_server(array $variables) { } /** - * Form constructor for completely clearing a server. + * Form constructor for server operations. * * @param SearchApiServer $server * The server for which the form is displayed. @@ -543,15 +543,39 @@ function search_api_server_status_form(array $form, array &$form_state, SearchAp $form['clear'] = array( '#type' => 'submit', '#value' => t('Delete all indexed data on this server'), + '#submit' => array('search_api_server_status_form_clear_submit') ); + $count = $server->enabled ? search_api_server_tasks_count($server) : 0; + if ($count) { + $message = format_plural($count, '@count pending task must be executed before indexing.', '@count pending tasks must be executed before indexing.'); + drupal_set_message($message, 'warning', FALSE); + $form['execute_pending_tasks'] = array( + '#type' => 'submit', + '#value' => t('Execute all pending tasks on this server'), + '#submit' => array('search_api_server_status_form_execute_pending_tasks_submit') + ); + } + return $form; } /** -* Form submission handler for search_api_server_status_form(). -*/ -function search_api_server_status_form_submit(array $form, array &$form_state) { + * Form submission handler for search_api_server_status_form(). + * + * Used for the "Execute all pending tasks" button. + */ +function search_api_server_status_form_execute_pending_tasks_submit($form, &$form_state) { + $server_id = $form_state['server']->machine_name; + $form_state['redirect'] = "admin/config/search/search_api/server/$server_id/execute-tasks"; +} + +/** + * Form submission handler for search_api_server_status_form(). + * + * Used for the "Delete all indexed data" button. + */ +function search_api_server_status_form_clear_submit(array $form, array &$form_state) { $server_id = $form_state['server']->machine_name; $form_state['redirect'] = "admin/config/search/search_api/server/$server_id/clear"; } @@ -1566,10 +1590,13 @@ function search_api_admin_index_workflow(array $form, array &$form_state, Search $form['processors'] = array( '#type' => 'fieldset', '#title' => t('Processors'), - '#description' => t('Select processors which will pre- and post-process data at index and search time, and their order. ' . - 'Most processors will only influence fulltext fields, but refer to their individual descriptions for details regarding their effect.'), + '#description' => '<p>' . t("Select processors which will pre- and post-process data at index and search time, and their order. Most processors will only influence fulltext fields, but refer to their individual descriptions for details regarding their effect.<br />Also, some processors shouldn't be used with more advanced search engines (like Solr or Elasticsearch), since the search engine already provides this functionality.") . '</p>', '#collapsible' => TRUE, ); + if ($index->server) { + $form['processors']['#description'] .= '<p>' . t("Check the <a href='@server-url'>server's</a> service class description for details.", + array('@server-url' => url('admin/config/search/search_api/server/' . $index->server . '/edit'))) . '</p>'; + } // Processor status. $form['processors']['status'] = array( @@ -1696,6 +1723,7 @@ function search_api_admin_index_workflow_submit(array $form, array &$form_state) unset($values['callbacks']['settings']); unset($values['processors']['settings']); $index = $form_state['index']; + $index_path = 'admin/config/search/search_api/index/' . $index->machine_name; $options = empty($index->options) ? array() : $index->options; @@ -1761,13 +1789,14 @@ function search_api_admin_index_workflow_submit(array $form, array &$form_state) $index->save(); $index->reindex(); - drupal_set_message(t("The indexing workflow was successfully edited. All content was scheduled for re-indexing so the new settings can take effect.")); + $vars = array('@url' => url($index_path)); + drupal_set_message(t('The indexing workflow was successfully edited. All content was scheduled for <a href="@url">re-indexing</a> so the new settings can take effect.', $vars)); } else { drupal_set_message(t('No values were changed.')); } - $form_state['redirect'] = 'admin/config/search/search_api/index/' . $index->machine_name . '/workflow'; + $form_state['redirect'] = $index_path . '/workflow'; } /** @@ -1822,8 +1851,8 @@ function search_api_admin_index_fields(array $form, array &$form_state, SearchAp 'In any case, fields of type "Fulltext" will always be fulltext-searchable.</p>'), ); if ($index->server) { - $form['description']['#description'] .= '<p>' . t('Check the <a href="@server-url">' . "server's</a> service class description for details.", - array('@server-url' => url('admin/config/search/search_api/server/' . $index->server))) . '</p>'; + $form['description']['#description'] .= '<p>' . t("Check the <a href='@server-url'>server's</a> service class description for details.", + array('@server-url' => url('admin/config/search/search_api/server/' . $index->server . '/edit'))) . '</p>'; } foreach ($fields as $key => $info) { $form['fields'][$key]['title']['#markup'] = check_plain($info['name']); diff --git a/profiles/wcm_base/modules/contrib/search_api/search_api.drush.inc b/profiles/wcm_base/modules/contrib/search_api/search_api.drush.inc index 61957b9a..8c995b17 100644 --- a/profiles/wcm_base/modules/contrib/search_api/search_api.drush.inc +++ b/profiles/wcm_base/modules/contrib/search_api/search_api.drush.inc @@ -95,6 +95,18 @@ function search_api_drush_command() { 'aliases' => array('sapi-r'), ); + $items['search-api-reindex-items'] = array( + 'description' => 'Force re-indexing of one or more specific items.', + 'examples' => array( + 'drush search-api-reindex-items node 12,34,56' => dt('Schedule the nodes with ID 12, 34 and 56 for re-indexing.'), + ), + 'arguments' => array( + 'entity_type' => dt('The entity type whose items should be re-indexed.'), + 'entities' => dt('The entities of the given entity type to be re-indexed.'), + ), + 'aliases' => array('sapi-ri'), + ); + $items['search-api-clear'] = array( 'description' => 'Clear one or all search indexes and mark them for re-indexing.', 'examples' => array( @@ -109,6 +121,19 @@ function search_api_drush_command() { 'aliases' => array('sapi-c'), ); + $items['search-api-execute-tasks'] = array( + 'description' => 'Execute all pending tasks or all for a given server.', + 'examples' => array( + 'drush search-api-execute-tasks my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')), + 'drush sapi-et my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')), + 'drush sapi-et' => dt('Execute all pending tasks on all servers.') + ), + 'arguments' => array( + 'server_id' => dt('The numeric ID or machine name of a server to execute tasks on.'), + ), + 'aliases' => array('sapi-et') + ); + $items['search-api-set-index-server'] = array( 'description' => 'Set the search server used by a given index.', 'examples' => array( @@ -448,6 +473,33 @@ function drush_search_api_reindex($index_id = NULL) { } } +/** + * Marks the given entities as needing to be re-indexed. + */ +function drush_search_api_reindex_items($entity_type, $entities) { + if (search_api_drush_static(__FUNCTION__)) { + return; + } + + // Validate list of entity ids. + if (!empty($entities) && !preg_match('#^[0-9]*(,[0-9]*)*$#', $entities)) { + drush_log(dt('Entities should be a single numeric entity ID or a list with the numeric entity IDs separated by comma.'), 'error'); + return; + } + + $ids = explode(',', $entities); + + if (!empty($ids)) { + search_api_track_item_change($entity_type, $ids); + + $combined_ids = array(); + foreach ($ids as $id) { + $combined_ids[] = $entity_type . '/' . $id; + } + search_api_track_item_change('multiple', $combined_ids); + } +} + /** * Clear an index. */ @@ -466,6 +518,34 @@ function drush_search_api_clear($index_id = NULL) { } } +/** + * Execute all pending tasks or all for a given server. + */ +function drush_search_api_execute_tasks($server_id = NULL) { + if (search_api_drush_static(__FUNCTION__)) { + return; + } + + // Attempt to load the associated server. + $server = NULL; + if ($server_id) { + $servers = search_api_drush_get_server($server_id); + if (!$servers) { + return; + } + $server = reset($servers); + } + + // Process batch op with drush. + try { + search_api_execute_pending_tasks($server); + drush_log(dt('!server tasks have been successfully executed.', array('!server' => $server->machine_name ? $server->machine_name : 'All')), 'ok'); + } + catch (SearchApiException $e) { + drush_log($e->getMessage(), 'error'); + } +} + /** * Set the server for a given index. */ diff --git a/profiles/wcm_base/modules/contrib/search_api/search_api.info b/profiles/wcm_base/modules/contrib/search_api/search_api.info index 1c85bdad..201c3db4 100644 --- a/profiles/wcm_base/modules/contrib/search_api/search_api.info +++ b/profiles/wcm_base/modules/contrib/search_api/search_api.info @@ -38,8 +38,8 @@ files[] = includes/service.inc configure = admin/config/search/search_api -; Information added by Drupal.org packaging script on 2018-04-05 -version = "7.x-1.24" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.25" core = "7.x" project = "search_api" -datestamp = "1522913891" +datestamp = "1537171099" diff --git a/profiles/wcm_base/modules/contrib/search_api/search_api.install b/profiles/wcm_base/modules/contrib/search_api/search_api.install index 5dc26895..61f686d7 100644 --- a/profiles/wcm_base/modules/contrib/search_api/search_api.install +++ b/profiles/wcm_base/modules/contrib/search_api/search_api.install @@ -264,6 +264,51 @@ function search_api_schema() { return $schema; } +/** + * Implements hook_requirements(). + */ +function search_api_requirements($phase) { + $requirements = array(); + + if ($phase == 'runtime') { + // Check whether at least one server has pending tasks. + if (search_api_server_tasks_count()) { + $items = array(); + + $conditions = array('enabled' => TRUE); + foreach (search_api_server_load_multiple(FALSE, $conditions) as $server) { + $count = search_api_server_tasks_count($server); + if ($count) { + $args = array( + '@name' => $server->name, + ); + $text = format_plural($count, '@name has @count pending task.', '@name has @count pending tasks.', $args); + $items[] = l($text, "admin/config/search/search_api/server/{$server->machine_name}/execute-tasks"); + } + } + + if ($items) { + $text = t('There are pending tasks for the following servers:'); + $text .= theme('item_list', array( + 'type' => 'ul', + 'items' => $items, + )); + if (count($items) > 1) { + $label = t('Execute pending tasks on all servers'); + $text .= l($label, 'admin/config/search/search_api/execute-tasks'); + } + $requirements['search_api_pending_tasks'] = array( + 'title' => t('Search API'), + 'value' => $text, + 'severity' => REQUIREMENT_WARNING, + ); + } + } + } + + return $requirements; +} + /** * Implements hook_install(). * diff --git a/profiles/wcm_base/modules/contrib/search_api/search_api.module b/profiles/wcm_base/modules/contrib/search_api/search_api.module index 8fe3e2a7..a509302c 100644 --- a/profiles/wcm_base/modules/contrib/search_api/search_api.module +++ b/profiles/wcm_base/modules/contrib/search_api/search_api.module @@ -72,6 +72,15 @@ function search_api_menu() { 'type' => MENU_LOCAL_TASK, 'context' => MENU_CONTEXT_INLINE | MENU_CONTEXT_PAGE, ); + $items[$pre . '/server/%search_api_server/execute-tasks'] = array( + 'title' => 'Execute pending tasks', + 'description' => 'Attempt to process pending tasks for a given server.', + 'page callback' => 'search_api_execute_pending_tasks', + 'page arguments' => array(5), + 'access callback' => 'search_api_access_execute_tasks_batch', + 'access arguments' => array(5), + 'type' => MENU_CALLBACK, + ); $items[$pre . '/server/%search_api_server/disable'] = array( 'title' => 'Disable', 'description' => 'Disable index.', @@ -98,6 +107,13 @@ function search_api_menu() { 'context' => MENU_CONTEXT_INLINE, 'weight' => 10, ); + $items[$pre . '/execute-tasks'] = array( + 'title' => 'Execute pending tasks', + 'description' => 'Attempt to process pending server tasks.', + 'page callback' => 'search_api_execute_pending_tasks', + 'access callback' => 'search_api_access_execute_tasks_batch', + 'type' => MENU_LOCAL_ACTION, + ); $items[$pre . '/index/%search_api_index'] = array( 'title' => 'View index', 'title callback' => 'search_api_admin_item_title', @@ -1409,6 +1425,10 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) { // Sometimes the order of tasks might be important, so make sure to order by // the task ID (which should be in order of insertion). $select->orderBy('t.id'); + // Only retrieve and execute 100 tasks at once, to avoid running out of memory + // or time. We just can't do anything else until all tasks have been resolved, + // but at least we shouldn't crash sites, or keep piling up tasks, that way. + $select->range(0, 100); $tasks = $select->execute(); $executed_tasks = array(); @@ -1465,11 +1485,116 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) { if (!$executed_tasks) { return TRUE; } - // Otherwise, delete the executed tasks and check if new tasks were created. + // Otherwise, delete the executed tasks and check if new tasks were created + // (or if we didn't even fetch all due to the 100 tasks limit). search_api_server_tasks_delete($executed_tasks); return $count_query->execute()->fetchField() === 0; } +/** + * Provides a batch wrapper for search_api_server_tasks_check(). + * + * @param SearchApiServer|null $server + * (optional) The server whose tasks should be executed, or NULL to execute + * tasks for all servers. + */ +function search_api_execute_pending_tasks(SearchApiServer $server = NULL) { + batch_set(array( + 'title' => t('Processing pending tasks'), + 'operations' => array( + array( + 'search_api_execute_pending_tasks_batch', + array( + $server, + ), + ), + ), + 'finished' => 'search_api_execute_pending_tasks_finished' + )); + if ($server) { + $path = 'admin/config/search/search_api/server/' . $server->machine_name; + } + else { + $path = 'admin/config/search/search_api'; + } + + if (function_exists('drush_backend_batch_process')) { + drush_backend_batch_process(); + } + else { + batch_process($path); + } +} + +/** + * Executes pending server tasks as part of a batch operation. + */ +function search_api_execute_pending_tasks_batch(SearchApiServer $server = NULL, &$context) { + if (!isset($context['results']['total'])) { + $context['results']['total'] = search_api_server_tasks_count($server); + } + $total = $context['results']['total']; + + search_api_server_tasks_check($server); + + $remaining = search_api_server_tasks_count($server); + $executed = max($total - $remaining, 0); + + $args['@remaining'] = $remaining; + $context['message'] = format_plural($executed, 'Successfully executed @count task, @remaining remaining.', 'Successfully executed @count tasks, @remaining remaining.', $args); + $context['finished'] = $executed / $total; +} + +/** + * Batch finish callback for pending server tasks. + */ +function search_api_execute_pending_tasks_finished($success, $results, $operations) { + if ($success) { + // Clear the previous warning. + drupal_get_messages('warning'); + + // Alert user to the number of tasks executed. + drupal_set_message(format_plural($results['total'], 'Successfully executed @count task.', 'Successfully executed @count tasks.')); + } +} + +/** + * Return the number of pending tasks. + * + * @param SearchApiServer|null $server + * (optional) The server for which tasks should be counted, or NULL to count + * for all enabled servers. + * + * @return int + * The number of pending tasks for the server, or in total. + */ +function search_api_server_tasks_count(SearchApiServer $server = NULL) { + $query = db_select('search_api_task', 't') + ->fields('t'); + + if ($server) { + $query->condition('server_id', $server->machine_name); + } + else { + $query->join('search_api_server', 's', 's.machine_name = t.server_id'); + $query->condition('s.enabled', 1); + } + + return $query->countQuery()->execute()->fetchField(); +} + +/** + * Access callback: Checks whether a user can execute pending tasks. + * + * @param SearchApiServer|null $server + * (optional) The server for which tasks would be executed. + */ +function search_api_access_execute_tasks_batch(SearchApiServer $server = NULL) { + return user_access('administer search_api') + && search_api_server_tasks_count($server) + && (!$server || $server->enabled); +} + /** * Adds an entry into a server's list of pending tasks. * diff --git a/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test.info b/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test.info index 5286e5eb..e3a3695d 100644 --- a/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test.info +++ b/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test.info @@ -10,8 +10,8 @@ files[] = search_api_test.module hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-05 -version = "7.x-1.24" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.25" core = "7.x" project = "search_api" -datestamp = "1522913891" +datestamp = "1537171099" diff --git a/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test_2.info b/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test_2.info index 72d47e90..e84483ed 100644 --- a/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test_2.info +++ b/profiles/wcm_base/modules/contrib/search_api/tests/search_api_test_2.info @@ -9,8 +9,8 @@ files[] = search_api_test_service_2.module hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-05 -version = "7.x-1.24" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.25" core = "7.x" project = "search_api" -datestamp = "1522913891" +datestamp = "1537171099" diff --git a/profiles/wcm_base/modules/contrib/search_api_db/CHANGELOG.txt b/profiles/wcm_base/modules/contrib/search_api_db/CHANGELOG.txt index 4b30f594..da676895 100644 --- a/profiles/wcm_base/modules/contrib/search_api_db/CHANGELOG.txt +++ b/profiles/wcm_base/modules/contrib/search_api_db/CHANGELOG.txt @@ -1,3 +1,14 @@ +Search API Database Search 1.7 (2018-09-17): +-------------------------------------------- +- #2982443 by KarlShea, drunken monkey: Added support for the "(not) between" + operators. +- #2855634 by drunken monkey, SpadXIII, levmyshkin, chris.jichen: Fixed update + #7107. +- #2940278 by james.williams, drunken monkey: Fixed indexing of decimal values + as boolean. +- #2897548 by drunken monkey: Fixed sorting on MySQL 5.7. +- #2879881 by drunken monkey: Fixed preprocessing of autocomplete keys. + Search API Database Search 1.6 (2017-02-23): -------------------------------------------- - #2840261 by alan-ps, drunken monkey: Fixed usage of outdated hash functions. diff --git a/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.info b/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.info index df593332..3a2bd848 100644 --- a/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.info +++ b/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.info @@ -6,9 +6,8 @@ package = Search files[] = search_api_db.test files[] = service.inc -; Information added by Drupal.org packaging script on 2017-02-23 -version = "7.x-1.6" +; Information added by Drupal.org packaging script on 2018-09-17 +version = "7.x-1.7" core = "7.x" project = "search_api_db" -datestamp = "1487844786" - +datestamp = "1537173484" diff --git a/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.install b/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.install index 0202a0bf..02b6a77d 100644 --- a/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.install +++ b/profiles/wcm_base/modules/contrib/search_api_db/search_api_db.install @@ -289,6 +289,9 @@ function search_api_db_update_7107() { $options = unserialize($options); if (!empty($options['indexes'])) { + list($key, $target) = explode(':', $options['database'], 2); + $connection = Database::getConnection($target, $key); + foreach ($options['indexes'] as $index_id => $fields) { $text_table = NULL; @@ -296,7 +299,7 @@ function search_api_db_update_7107() { if (search_api_is_text_type($field['type'])) { $text_table = $field['table']; if (strlen($field_id) > 255) { - db_update($text_table) + $connection->update($text_table) ->fields(array('field_name' => drupal_hash_base64($field_id))) ->condition('field_name', md5($field_id)) ->execute(); @@ -305,8 +308,9 @@ function search_api_db_update_7107() { } // If there is a text table for this index, update its description. - if ($text_table) { - db_change_field($text_table, 'field_name', 'field_name', $spec); + if ($text_table && db_table_exists($text_table)) { + $connection->schema() + ->changeField($text_table, 'field_name', 'field_name', $spec); } } } diff --git a/profiles/wcm_base/modules/contrib/search_api_db/service.inc b/profiles/wcm_base/modules/contrib/search_api_db/service.inc index 609e5d4f..b98d5b79 100644 --- a/profiles/wcm_base/modules/contrib/search_api_db/service.inc +++ b/profiles/wcm_base/modules/contrib/search_api_db/service.inc @@ -174,6 +174,7 @@ class SearchApiDbService extends SearchApiAbstractService { public function supportsFeature($feature) { $supported = array( 'search_api_autocomplete' => TRUE, + 'search_api_between' => TRUE, 'search_api_facets' => TRUE, 'search_api_facets_operator_or' => TRUE, 'search_api_random_sort' => TRUE, @@ -1112,6 +1113,11 @@ class SearchApiDbService extends SearchApiAbstractService { return 0 + $value; case 'boolean': + // Numeric strings need to be converted to a numeric type before + // converting to a boolean, as strings like '0.00' evaluate to TRUE. + if (is_string($value) && is_numeric($value)) { + $value = 0 + $value; + } return $value ? 1 : 0; case 'date': @@ -1686,57 +1692,63 @@ class SearchApiDbService extends SearchApiAbstractService { } } else { - if (!isset($fields[$f[0]])) { - throw new SearchApiException(t('Unknown field in filter clause: @field.', array('@field' => $f[0]))); - } - $field = $fields[$f[0]]; - $not_equals = $f[2] == '<>' || $f[2] == '!='; - $text_type = search_api_is_text_type($field['type']); + list ($field, $value, $operator) = $f; + if (!isset($fields[$field])) { + throw new SearchApiException(t('Unknown field in filter clause: @field.', array('@field' => $field))); + } + $field_info = $fields[$field]; + $not_between = $operator === 'NOT BETWEEN'; + $not_equals = $not_between || $operator === '<>' || $operator === '!='; + $text_type = search_api_is_text_type($field_info['type']); // If the field is in its own table, we have to check for NULL values in // a special way (i.e., check for missing entries in that table). - if ($f[1] === NULL && ($field['column'] === 'value' || $text_type)) { - $query = $this->connection->select($field['table'], 't') + if ($value === NULL && ($field_info['column'] === 'value' || $text_type)) { + $query = $this->connection->select($field_info['table'], 't') ->fields('t', array('item_id')); if ($text_type) { - $query->condition('t.field_name', $f[0]); + $query->condition('t.field_name', $field); } $cond->condition('t.item_id', $query, $not_equals ? 'IN' : 'NOT IN'); continue; } if ($text_type) { - $keys = $this->prepareKeys($f[1]); + $keys = $this->prepareKeys($value); if (!isset($keys)) { continue; } - $query = $this->createKeysQuery($keys, array($f[0] => $field), $fields); + $query = $this->createKeysQuery($keys, array($field => $field_info), $fields); // We only want the item IDs, so we use the keys query as a nested query. $query = $this->connection->select($query, 't')->fields('t', array('item_id')); $cond->condition('t.item_id', $query, $not_equals ? 'NOT IN' : 'IN'); } else { - $new_join = search_api_is_list_type($field['type']) + $new_join = search_api_is_list_type($field_info['type']) && ($filter->getConjunction() == 'AND' - || empty($first_join[$f[0]])); - if ($new_join || empty($tables[$f[0]])) { - $tables[$f[0]] = $this->getTableAlias($field, $db_query, $new_join); - $first_join[$f[0]] = TRUE; + || empty($first_join[$field])); + if ($new_join || empty($tables[$field])) { + $tables[$field] = $this->getTableAlias($field_info, $db_query, $new_join); + $first_join[$field] = TRUE; } - $column = $tables[$f[0]] . '.' . $field['column']; - if ($f[1] === NULL) { - $method = ($f[2] == '=') ? 'isNull' : 'isNotNull'; + $column = $tables[$field] . '.' . $field_info['column']; + if ($value === NULL) { + $method = ($operator == '=') ? 'isNull' : 'isNotNull'; $cond->$method($column); } - elseif ($not_equals && search_api_is_list_type($field['type'])) { + elseif ($not_equals && search_api_is_list_type($field_info['type'])) { // The situation is more complicated for multi-valued fields, since // we must make sure that results are excluded if ANY of the field's // values equals the one given in this condition. - $query = $this->connection->select($field['table'], 't') + $sub_operator = ($not_between) ? 'BETWEEN' : '='; + $query = $this->connection->select($field_info['table'], 't') ->fields('t', array('item_id')) - ->condition($field['column'], $f[1]); + ->condition($field_info['column'], $value, $sub_operator); $cond->condition('t.item_id', $query, 'NOT IN'); } + elseif ($not_between) { + $cond->where("$column NOT BETWEEN {$value[0]} AND {$value[1]}"); + } else { - $cond->condition($column, $f[1], $f[2]); + $cond->condition($column, $value, $operator); } } } @@ -1854,7 +1866,7 @@ class SearchApiDbService extends SearchApiAbstractService { $alias = $this->getTableAlias($field, $db_query); $db_query->orderBy($alias . '.' . $fields[$field_name]['column'], $order); // PostgreSQL automatically adds a field to the SELECT list when sorting - // on it. Therefore, if we have aggregrations present we also have to + // on it. Therefore, if we have aggregations present we also have to // add the field to the GROUP BY (since Drupal won't do it for us). // However, if no aggregations are present, a GROUP BY would lead to // another error. Therefore, we only add it if there is already a GROUP @@ -1862,6 +1874,13 @@ class SearchApiDbService extends SearchApiAbstractService { if ($db_query->getGroupBy()) { $db_query->groupBy($alias . '.' . $fields[$field_name]['column']); } + // For SELECT DISTINCT queries in combination with an ORDER BY clause, + // MySQL 5.7 and higher require that the ORDER BY expressions are part + // of the field list. Ensure that all fields used for sorting are part + // of the select list. + if (empty($db_fields[$fields[$field_name]['column']])) { + $db_query->addField($alias, $fields[$field_name]['column']); + } } } else { @@ -2085,8 +2104,21 @@ class SearchApiDbService extends SearchApiAbstractService { // Decide which methods we want to use. if ($incomplete_key && $settings['suggest_suffix']) { - $passes[] = 1; - $incomplete_like = $this->connection->escapeLike($incomplete_key) . '%'; + $processed_key = $this->splitKeys($incomplete_key); + if ($processed_key) { + // In case the $incomplete_key turned out to be more than one word, add + // all but the last one to the user input. + if (is_array($processed_key)) { + unset($processed_key['#conjunction']); + $incomplete_key = array_pop($processed_key); + if ($processed_key) { + $user_input .= ' ' . implode(' ', $processed_key); + } + $processed_key = $incomplete_key; + } + $passes[] = 1; + $incomplete_like = $this->connection->escapeLike($processed_key) . '%'; + } } if ($settings['suggest_words'] && (!$incomplete_key || strlen($incomplete_key) >= $this->options['min_chars'])) { diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid.features.inc b/profiles/wcm_base/modules/contrib/uuid/uuid.features.inc index 03b7d55b..93b418ef 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid.features.inc +++ b/profiles/wcm_base/modules/contrib/uuid/uuid.features.inc @@ -168,6 +168,7 @@ function uuid_entities_rebuild($module_name = '', $op = 'rebuild') { foreach ($entities as $plan_name => $entities) { // Let other modules do things before default entities are created. module_invoke_all("uuid_entities_pre_$op", $plan_name); + drupal_alter("uuid_entities_pre_$op", $entities, $plan_name); foreach ($entities as $entity) { entity_uuid_save($entity->__metadata['type'], $entity); } diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid.info b/profiles/wcm_base/modules/contrib/uuid/uuid.info index bd1e8735..cefaf291 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid.info +++ b/profiles/wcm_base/modules/contrib/uuid/uuid.info @@ -7,8 +7,8 @@ files[] = uuid.test dependencies[] = node dependencies[] = user -; Information added by Drupal.org packaging script on 2018-07-03 -version = "7.x-1.1" +; Information added by Drupal.org packaging script on 2018-07-19 +version = "7.x-1.2" core = "7.x" project = "uuid" -datestamp = "1530614937" +datestamp = "1531990689" diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_path/uuid_path.info b/profiles/wcm_base/modules/contrib/uuid/uuid_path/uuid_path.info index 0f4fa2ba..77ad15c3 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid_path/uuid_path.info +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_path/uuid_path.info @@ -5,8 +5,8 @@ package = UUID dependencies[] = uuid -; Information added by Drupal.org packaging script on 2018-07-03 -version = "7.x-1.1" +; Information added by Drupal.org packaging script on 2018-07-19 +version = "7.x-1.2" core = "7.x" project = "uuid" -datestamp = "1530614937" +datestamp = "1531990689" diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.admin.inc b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.admin.inc index d9afe29b..28e447cf 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.admin.inc +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.admin.inc @@ -18,5 +18,13 @@ function uuid_services_settings() { '#description' => t('Check this box to automatically provide Services integration for all entity types with UUID support.'), '#default_value' => variable_get('uuid_services_support_all_entity_types', FALSE), ); + $form['uuid_services_allowed_media_mimes'] = array( + '#type' => 'textarea', + '#title' => t('Allowed Media Mime type'), + '#default_value' => variable_get('uuid_services_allowed_media_mimes', UUID_SERVICES_DEFAULT_ALLOWED_MEDIA_MIMES), + '#cols' => 40, + '#rows' => 5, + '#description' => t("Enter one mime type per line you wish to allow in the system without extension. Example mime type '<em>video/brightcove</em>'."), + ); return system_settings_form($form); } diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.info b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.info index 911f2965..dd1ae423 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.info +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.info @@ -7,8 +7,14 @@ dependencies[] = services dependencies[] = uuid dependencies[] = entity -; Information added by Drupal.org packaging script on 2018-07-03 -version = "7.x-1.1" +test_dependencies[] = services +test_dependencies[] = entity +test_dependencies[] = file +test_dependencies[] = field +test_dependencies[] = file_entity + +; Information added by Drupal.org packaging script on 2018-07-19 +version = "7.x-1.2" core = "7.x" project = "uuid" -datestamp = "1530614937" +datestamp = "1531990689" diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.install b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.install new file mode 100644 index 00000000..1dfeb6cc --- /dev/null +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.install @@ -0,0 +1,14 @@ +<?php + +/** + * @file + * UUID module installation functions. + */ + +/** + * Implements hook_uninstall(). + */ +function uuid_services_uninstall() { + variable_del('uuid_services_support_all_entity_types'); + variable_del('uuid_services_allowed_media_mimes'); +} diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.module b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.module index a43160c8..5a0e6289 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.module +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_services/uuid_services.module @@ -5,6 +5,14 @@ * UUID Services module functions. */ +/** + * Defines defaults for UUID_SERVICES_ALLOWED_MEDIA_MIMES. + */ +define('UUID_SERVICES_DEFAULT_ALLOWED_MEDIA_MIMES', +'video/brightcove +video/youtube' +); + /** * Implements hook_menu(). */ @@ -147,12 +155,19 @@ function _uuid_services_entity_update($entity_type, $uuid, $entity) { $entity = (object) $entity; } $entity->uuid_services = TRUE; + // Check that the mime type is whitelisted. + $valid_media_mimes = variable_get('uuid_services_allowed_media_mimes', UUID_SERVICES_DEFAULT_ALLOWED_MEDIA_MIMES); + // Sanitize file user input. if ($entity_type == 'file') { - $entity->filename = _services_file_check_name_extension($entity->filename); - $entity->uri = _services_file_check_destination_uri($entity->uri); - if (!empty($entity->filepath)) { - $entity->filepath = _services_file_check_destination($entity->filepath); + // We have to make sure to whitelist mime types, to avoid the video files + // getting converted into text files, when deployed from one env to other. + if (!in_array($entity->filemime, preg_split('/\r?\n/', $valid_media_mimes))) { + $entity->filename = _services_file_check_name_extension($entity->filename); + $entity->uri = _services_file_check_destination_uri($entity->uri); + if (!empty($entity->filepath)) { + $entity->filepath = _services_file_check_destination($entity->filepath); + } } } entity_uuid_save($entity_type, $entity); diff --git a/profiles/wcm_base/modules/contrib/uuid/uuid_services_example/uuid_services_example.info b/profiles/wcm_base/modules/contrib/uuid/uuid_services_example/uuid_services_example.info index 65cd2df1..5874051f 100644 --- a/profiles/wcm_base/modules/contrib/uuid/uuid_services_example/uuid_services_example.info +++ b/profiles/wcm_base/modules/contrib/uuid/uuid_services_example/uuid_services_example.info @@ -11,8 +11,8 @@ features[ctools][] = services:services:3 features[features_api][] = api:2 features[services_endpoint][] = uuid_services_example -; Information added by Drupal.org packaging script on 2018-07-03 -version = "7.x-1.1" +; Information added by Drupal.org packaging script on 2018-07-19 +version = "7.x-1.2" core = "7.x" project = "uuid" -datestamp = "1530614937" +datestamp = "1531990689" diff --git a/profiles/wcm_base/modules/custom/news_client/README.md b/profiles/wcm_base/modules/custom/news_client/README.md index 6e9424e4..38815543 100644 --- a/profiles/wcm_base/modules/custom/news_client/README.md +++ b/profiles/wcm_base/modules/custom/news_client/README.md @@ -74,3 +74,12 @@ At admin/config/services/news_client/import there are two tools. ## Purge The button at admin/config/services/news_client/purge is the nuclear option for dealing with the cache. It will obliterate everything. It will probably only help in extreme circumstances and its use should be avoided... + +## Tokens + +News Client defines several tokens that can be used wherever necessary: + +* **[node:news_client_body_summary]** Resolves to the summary of the current body of the News Client Cached Article. +* **[node:news_client_featured_image_url]** Resolves to the URL of the featured image in the News Client Cached Article. +* **[node:news_client_featured_image_alt]** Resolves to the alt text for the featured image in the News Client Cached Article. + diff --git a/profiles/wcm_base/modules/panopoly/panopoly_admin/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_admin/CHANGELOG.txt index 6cc41fb0..d90a041d 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_admin/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_admin/CHANGELOG.txt @@ -1,3 +1,11 @@ +7.x-1.58, 2018-12-11 +------------------- +- Patch admin_menu to remove PHP 7 deprecation warning. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.info b/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.info index 398e14bf..f19dc6c2 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.info @@ -37,8 +37,8 @@ features[page_manager_pages][] = panopoly_admin_layout_library features[page_manager_pages][] = panopoly_admin_page_library features[page_manager_pages][] = panopoly_admin_pane_library -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_admin" -datestamp = "1539206885" +datestamp = "1544590687" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.make b/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.make index d644c0aa..181d0616 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.make +++ b/profiles/wcm_base/modules/panopoly/panopoly_admin/panopoly_admin.make @@ -42,6 +42,7 @@ projects[breakpoints][subdir] = contrib projects[admin_menu][version] = 3.0-rc5 projects[admin_menu][subdir] = contrib +projects[admin_menu][patch][2929025] = https://www.drupal.org/files/issues/admin-menu-2929025-each-function-deprecated-php-7.2.patch ; jQuery Update was moved to Panopoly Core, but is left in Panopoly Admin's ; .make file to retain a stable 1.x branch of Panopoly. See the following URL diff --git a/profiles/wcm_base/modules/panopoly/panopoly_core/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_core/CHANGELOG.txt index c8c82cd0..517e8552 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_core/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_core/CHANGELOG.txt @@ -1,3 +1,21 @@ +7.x-1.58, 2018-12-11 +------------------- +- Patch defaultcontent module to remove PHP7 deprecation warning. +- Allow overriding "more" text on Views-based widgets. +- Update uuid module to 1.2. +- Patch panels breadcrumb module to remove deprecation notice in PHP 7.2. +- Patch/update views bulk operations to remove deprecation warnings in PHP 7.2. +- Patch features to remove deprecation warning in PHP 7.2. +- Upgrade & patch migrate module to make it compatible with PHP 7. +- Patch Views for PHP 7.1 issue. +- Patch apps to remove PHP 7 deprecation warning. +- Update libraries module to resolve deprecation warning for PHP 7. +- Out-of-date dependency processing in panopoly_core. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.info b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.info index 662d1075..4600bfa4 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.info @@ -82,8 +82,8 @@ features_exclude[variable][panelizer_taxonomy_term:panopoly_categories_allowed_t features_exclude[variable][panelizer_defaults_taxonomy_term_panopoly_categories] = panelizer_defaults_taxonomy_term_panopoly_categories features_exclude[variable][pathauto_taxonomy_term_panopoly_categories_pattern] = pathauto_taxonomy_term_panopoly_categories_pattern -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_core" -datestamp = "1539206899" +datestamp = "1544590701" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.make b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.make index 6472558d..27a1e999 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.make +++ b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.make @@ -7,13 +7,14 @@ core = 7.x projects[ctools][version] = 1.14 projects[ctools][subdir] = contrib +projects[ctools][patch][1000146] = https://www.drupal.org/files/issues/2018-03-26/views_panes-more_link_text-1000146-28.patch projects[panels][version] = 3.9 projects[panels][subdir] = contrib projects[panels][patch][1570120] = https://www.drupal.org/files/issues/move-image-1570120-31.patch projects[panels][patch][2897658] = https://www.drupal.org/files/issues/panels-menu-block-ipe-2897658-3.patch -projects[panels_breadcrumbs][version] = 2.2 +projects[panels_breadcrumbs][version] = 2.3 projects[panels_breadcrumbs][subdir] = contrib projects[panelizer][version] = 3.4 @@ -36,6 +37,8 @@ projects[fape][subdir] = contrib projects[views][version] = 3.20 projects[views][subdir] = contrib projects[views][patch][2037469] = https://www.drupal.org/files/issues/views-exposed-sorts-2037469-26.patch +projects[views][patch][2885660] = https://www.drupal.org/files/issues/2018-06-28/2885660-13.patch +projects[views][patch][2977851] = https://www.drupal.org/files/issues/2018-06-06/2977851-views-php72-count-2.patch projects[views_autocomplete_filters][version] = 1.2 projects[views_autocomplete_filters][subdir] = contrib @@ -43,7 +46,7 @@ projects[views_autocomplete_filters][patch][2374709] = http://www.drupal.org/fil projects[views_autocomplete_filters][patch][2317351] = http://www.drupal.org/files/issues/views_autocomplete_filters-content-pane-2317351-4.patch projects[views_autocomplete_filters][patch][2404893] = https://www.drupal.org/files/issues/2404893-grammar_correction-11.patch -projects[views_bulk_operations][version] = 3.4 +projects[views_bulk_operations][version] = 3.5 projects[views_bulk_operations][subdir] = contrib ; The Usual Suspects @@ -57,7 +60,7 @@ projects[token][subdir] = contrib projects[entity][version] = 1.9 projects[entity][subdir] = contrib -projects[libraries][version] = 2.3 +projects[libraries][version] = 2.5 projects[libraries][subdir] = contrib projects[transliteration][version] = 3.2 @@ -82,9 +85,11 @@ projects[link][patch][2666912] = https://www.drupal.org/files/issues/revert-url- projects[apps][version] = 1.1 projects[apps][subdir] = contrib +projects[apps][patch][2945929] = https://www.drupal.org/files/issues/apps-php7-compat-2945929.patch projects[features][version] = 2.10 projects[features][subdir] = contrib +projects[features][patch][2931464] = "https://www.drupal.org/files/issues/features-create_function-is-deprecated-2931464-5.patch" projects[strongarm][version] = 2.0 projects[strongarm][subdir] = contrib @@ -97,8 +102,9 @@ projects[defaultcontent][version] = 1.0-alpha9 projects[defaultcontent][subdir] = contrib projects[defaultcontent][patch][1754428] = http://drupal.org/files/1754428-allow-node-export-alter.patch projects[defaultcontent][patch][1757782] = http://drupal.org/files/1757782-cannot-import-menu-hierarchy-8.patch +projects[defaultcontent][patch][2946138] = https://www.drupal.org/files/issues/defaultcontent-php7-compat-2946138.patch -projects[migrate][version] = "2.9" +projects[migrate][version] = "2.11" projects[migrate][type] = "module" projects[migrate][subdir] = "contrib" @@ -122,5 +128,5 @@ projects[distro_update][subdir] = contrib projects[features_override][version] = 2.0-rc3 projects[features_override][subdir] = contrib -projects[uuid][version] = 1.1 +projects[uuid][version] = 1.2 projects[uuid][subdir] = contrib diff --git a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.profile.inc b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.profile.inc index aa919e45..f064b346 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.profile.inc +++ b/profiles/wcm_base/modules/panopoly/panopoly_core/panopoly_core.profile.inc @@ -26,8 +26,8 @@ function panopoly_core_install_load_profile(&$install_state) { $module_info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); if (!empty($module_info['dependencies'])) { foreach ($module_info['dependencies'] as $dependency) { - $parts = explode(' (', $dependency, 2); - $dependencies[] = array_shift($parts); + $parts = drupal_parse_dependency($dependency); + $dependencies[] = $parts['name']; } } } diff --git a/profiles/wcm_base/modules/panopoly/panopoly_magic/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_magic/CHANGELOG.txt index 569e8162..a197e9dd 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_magic/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_magic/CHANGELOG.txt @@ -1,3 +1,12 @@ +7.x-1.58, 2018-12-11 +------------------- +- Allow overriding "more" text on Views-based widgets. +- Swap order of "Save" and "Update Preview" buttons when in manual preview mode. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - PHP notices when previewing widgets. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.info b/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.info index 5f27405d..36cbb348 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.info @@ -15,8 +15,8 @@ stylesheets[all][] = css/panopoly-modal.css features[features_api][] = api:2 files[] = plugins/views/panopoly_magic_plugin_display_panel_pane.inc -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_magic" -datestamp = "1539206939" +datestamp = "1544590743" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.module b/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.module index fd5b5536..cd98ac64 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.module +++ b/profiles/wcm_base/modules/panopoly/panopoly_magic/panopoly_magic.module @@ -492,6 +492,7 @@ function panopoly_magic_form_alter(&$form, &$form_state, $form_id) { '#type' => 'button', '#value' => t('Update Preview'), '#attributes' => $preview_attributes, + '#weight' => -100, '#ajax' => array( 'callback' => 'panopoly_magic_ajax_update_preview', 'wrapper' => 'panopoly-form-widget-preview', @@ -904,8 +905,19 @@ function panopoly_magic_form_views_content_views_panes_content_type_edit_form_al $form['exposed']['more_link']['#parents'] = array('more_link'); unset($form['more_link']); } - - + + // Add an option to the more link text if views allows this to happen + if (!empty($form['more_text'])) { + $form['exposed']['more_text'] = $form['more_text']; + $form['exposed']['more_text']['#parents'] = array('more_text'); + unset($form['more_text']); + $form['exposed']['more_text']['#states'] = array( + 'visible' => array( + ':input[name="more_link"]' => array('checked' => TRUE), + ), + ); + } + // Update the field settings for pagers if (!empty($form['use_pager']) && !empty($form['pager_id'])) { $form['use_pager']['#prefix'] = '<div class="form-item container-inline">'; diff --git a/profiles/wcm_base/modules/panopoly/panopoly_pages/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_pages/CHANGELOG.txt index a53f624a..0040e704 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_pages/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_pages/CHANGELOG.txt @@ -1,3 +1,11 @@ +7.x-1.58, 2018-12-11 +------------------- +- No changes since last release. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_pages/panopoly_pages.info b/profiles/wcm_base/modules/panopoly/panopoly_pages/panopoly_pages.info index 572414b1..8e6f1755 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_pages/panopoly_pages.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_pages/panopoly_pages.info @@ -81,8 +81,8 @@ features_exclude[variable][pathauto_node_panopoly_landing_page_pattern] = pathau features_exclude[variable][pathauto_node_panopoly_page_pattern] = pathauto_node_panopoly_page_pattern features_exclude[variable][pathauto_taxonomy_term_panopoly_categories_pattern] = pathauto_taxonomy_term_panopoly_categories_pattern -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_pages" -datestamp = "1539206950" +datestamp = "1544590755" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_search/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_search/CHANGELOG.txt index f46d2f5a..1b2e6271 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_search/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_search/CHANGELOG.txt @@ -1,3 +1,11 @@ +7.x-1.58, 2018-12-11 +------------------- +- Update search_api to 1.25 and search_api_db to 1.7. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - Update to search_api_solr 1.14 for SA-CONTRIB-2018-065. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.info b/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.info index ea7d6a50..586a2159 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.info @@ -54,8 +54,8 @@ features[variable][] = search_cron_limit features[views_view][] = panopoly_database_search features[views_view][] = panopoly_search -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_search" -datestamp = "1539206962" +datestamp = "1544590768" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.make b/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.make index 74110952..69efd15b 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.make +++ b/profiles/wcm_base/modules/panopoly/panopoly_search/panopoly_search.make @@ -8,13 +8,13 @@ core = 7.x projects[facetapi][version] = 1.5 projects[facetapi][subdir] = contrib -projects[search_api][version] = 1.24 +projects[search_api][version] = 1.25 projects[search_api][subdir] = contrib projects[search_api_solr][version] = 1.14 projects[search_api_solr][subdir] = contrib -projects[search_api_db][version] = 1.6 +projects[search_api_db][version] = 1.7 projects[search_api_db][subdir] = contrib ; Solr PHP Client Library diff --git a/profiles/wcm_base/modules/panopoly/panopoly_test/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_test/CHANGELOG.txt index 322e9070..d05a5ed9 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_test/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_test/CHANGELOG.txt @@ -1,3 +1,11 @@ +7.x-1.58, 2018-12-11 +------------------- +- No changes since last release. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_test/panopoly_test.info b/profiles/wcm_base/modules/panopoly/panopoly_test/panopoly_test.info index ca0e1535..ac0cc919 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_test/panopoly_test.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_test/panopoly_test.info @@ -99,8 +99,8 @@ features_exclude[dependencies][panopoly_pages] = panopoly_pages features_exclude[dependencies][panelizer] = panelizer hidden = 1 -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_test" -datestamp = "1539206981" +datestamp = "1544590782" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_theme/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_theme/CHANGELOG.txt index a02debcc..a1048d20 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_theme/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_theme/CHANGELOG.txt @@ -1,3 +1,11 @@ +7.x-1.58, 2018-12-11 +------------------- +- No changes since last release. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_theme/panopoly_theme.info b/profiles/wcm_base/modules/panopoly/panopoly_theme/panopoly_theme.info index 25f09c99..879dcac2 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_theme/panopoly_theme.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_theme/panopoly_theme.info @@ -11,8 +11,8 @@ stylesheets[all][] = css/panopoly-accordian.css stylesheets[all][] = css/panopoly-layouts.css features[features_api][] = api:2 -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_theme" -datestamp = "1539207184" +datestamp = "1544590793" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/CHANGELOG.txt b/profiles/wcm_base/modules/panopoly/panopoly_widgets/CHANGELOG.txt index fde4d11a..621a7f19 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/CHANGELOG.txt +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/CHANGELOG.txt @@ -1,3 +1,14 @@ +7.x-1.58, 2018-12-11 +------------------- +- File entity overwriting slide title on spotlight widgets. +- Normalize "Slide duration" for Spotlight widgets. +- Update Media to 2.21. +- Update file_entity to 2.22. + +7.x-1.57, 2018-10-18 +------------------- +- No changes since last release. + 7.x-1.56, 2018-10-10 ------------------- - No changes since last release. diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.features.field_instance.inc b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.features.field_instance.inc index 57ea2cd8..c1f5ec1a 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.features.field_instance.inc +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.features.field_instance.inc @@ -387,7 +387,11 @@ function panopoly_widgets_field_default_field_instances() { // 'fieldable_panels_pane-spotlight-field_basic_spotlight_duration'. $field_instances['fieldable_panels_pane-spotlight-field_basic_spotlight_duration'] = array( 'bundle' => 'spotlight', - 'default_value' => NULL, + 'default_value' => array( + 0 => array( + 'value' => 5, + ), + ), 'deleted' => 0, 'description' => '', 'display' => array( @@ -401,7 +405,7 @@ function panopoly_widgets_field_default_field_instances() { 'entity_type' => 'fieldable_panels_pane', 'field_name' => 'field_basic_spotlight_duration', 'label' => 'Slide Duration', - 'required' => 0, + 'required' => 1, 'settings' => array( 'max' => 60, 'min' => 1, diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.info b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.info index 91b7b9ba..338c8eaf 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.info +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.info @@ -125,8 +125,8 @@ features[linkit_profiles][] = content_fields features[views_view][] = panopoly_widgets_general_content features_exclude[dependencies][linkit] = linkit -; Information added by Drupal.org packaging script on 2018-10-10 -version = "7.x-1.56" +; Information added by Drupal.org packaging script on 2018-12-12 +version = "7.x-1.58" core = "7.x" project = "panopoly_widgets" -datestamp = "1539207784" +datestamp = "1544590822" diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.install b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.install index 7465dc06..1536a95e 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.install +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.install @@ -485,3 +485,57 @@ function panopoly_widgets_update_7022() { } } } + +/** + * Make sure that "Slide duration" on Spotlight widgets always has a value. + */ +function panopoly_widgets_update_7023(&$sandbox) { + if (!isset($sandbox['fpids'])) { + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'fieldable_panels_pane') + ->entityCondition('bundle', 'spotlight'); + $result = $query->execute(); + if (isset($result['fieldable_panels_pane'])) { + $sandbox['fpids'] = array_keys($result['fieldable_panels_pane']); + } + } + else { + $count = 10; + while (!empty($sandbox['fpids']) && $count >= 0) { + $fpp = fieldable_panels_panes_load(array_shift($sandbox['fpids'])); + $wrapper = entity_metadata_wrapper('fieldable_panels_pane', $fpp); + if (!$wrapper->field_basic_spotlight_duration->value()) { + $wrapper->field_basic_spotlight_duration->set(variable_get('panopoly_widgets_spotlight_rotation_time', 5)); + $wrapper->save(); + } + } + } + + $sandbox['#finished'] = empty($sandbox['fpids']); + + if ($sandbox['#finished']) { + variable_del('panopoly_widgets_spotlight_rotation_time'); + } +} + +/** + * Update field instance settings for duration fields on Spotlight widgets. + */ +function panopoly_widgets_update_7024() { + // Remove legacy field if it's still around. + if ($instance_info = field_info_instance('fieldable_panels_pane', 'field_spotlight_rotation_time', 'spotlight')) { + field_delete_instance($instance_info); + } + + // Make the default value 5 and mark as required. + if ($instance_info = field_info_instance('fieldable_panels_pane', 'field_basic_spotlight_duration', 'spotlight')) { + $instance_info['default_value'] = array( + 0 => array( + 'value' => 5, + ), + ); + $instance_info['required'] = 1; + field_update_instance($instance_info); + } +} diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.make b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.make index 29e83641..25bad686 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.make +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.make @@ -20,10 +20,10 @@ projects[menu_block][subdir] = contrib ; Panopoly - Contrib - Files & Media -projects[file_entity][version] = 2.21 +projects[file_entity][version] = 2.22 projects[file_entity][subdir] = contrib -projects[media][version] = 2.19 +projects[media][version] = 2.21 projects[media][subdir] = contrib projects[media_youtube][version] = 3.7 diff --git a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.spotlight.inc b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.spotlight.inc index fb50364f..ec4fffab 100644 --- a/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.spotlight.inc +++ b/profiles/wcm_base/modules/panopoly/panopoly_widgets/panopoly_widgets.spotlight.inc @@ -159,7 +159,7 @@ function panopoly_widgets_field_formatter_view($entity_type, $entity, $field, $i $duration = $duration_field['value']; } if (empty($duration)) { - $duration = variable_get('panopoly_widgets_spotlight_rotation_time', 4); + $duration = variable_get('panopoly_widgets_spotlight_rotation_time', 5); } $pager_style = 'full'; // Default to the Full pager if field isn't filled out (i.e., legacy data). @@ -208,6 +208,12 @@ function panopoly_widgets_field_formatter_view($entity_type, $entity, $field, $i // Assemble the spotlight items (rendered in panopoly_spotlight_wrapper()) foreach ($items as $delta => $item_data) { + if (isset($item_data['field_title'])) { + $item_data['title'] = $item_data['field_title']; + } + if (isset($item_data['field_alt'])) { + $item_data['alt'] = $item_data['field_alt']; + } $element[0]['slides'][] = array( '#theme' => 'panopoly_spotlight_view', '#items' => $item_data, @@ -235,7 +241,7 @@ function panopoly_widgets_field_widget_form(&$form, &$form_state, $field, $insta $element['title'] = array( '#title' => t('Title'), '#type' => 'textfield', - '#default_value' => isset($items[$delta]['title']) ? $items[$delta]['title'] : NULL, + '#default_value' => isset($items[$delta]['field_title']) ? $items[$delta]['field_title'] : NULL, ); $element['link'] = array( @@ -283,7 +289,7 @@ function panopoly_widgets_field_widget_form(&$form, &$form_state, $field, $insta $element['alt'] = array( '#title' => t('Alt text'), '#type' => 'textfield', - '#default_value' => isset($items[$delta]['alt']) ? $items[$delta]['alt'] : NULL, + '#default_value' => isset($items[$delta]['field_alt']) ? $items[$delta]['field_alt'] : NULL, ); $element['description'] = array( @@ -327,6 +333,12 @@ function panopoly_widgets_field_presave($entity_type, $entity, $field, $instance $item['fid'] = $fid; } } + if (isset($item['field_title'])) { + $item['title'] = $item['field_title']; + } + if (isset($item['field_alt'])) { + $item['alt'] = $item['field_alt']; + } } image_field_presave($entity_type, $entity, $field, $instance, $langcode, $items); } @@ -338,11 +350,13 @@ function panopoly_widgets_field_presave($entity_type, $entity, $field, $instance function panopoly_widgets_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) { $entity_items_copy = $items; image_field_load($entity_type, $entities, $field, $instances, $langcode, $items, $age); - // image_field_load() will overwrite 'title' with the image title. Here we - // return it to the item title. + // Both image_field_load() and file_entity_entity_load() will overwrite the + // 'title' and 'alt' with the one from the file. Here we save the originals + // for later. foreach ($entity_items_copy as $entity_id => $items_copy) { foreach ($items_copy as $delta => $item) { - $items[$entity_id][$delta]['title'] = $item['title']; + $items[$entity_id][$delta]['field_title'] = $item['title']; + $items[$entity_id][$delta]['field_alt'] = $item['alt']; } } } diff --git a/profiles/wcm_base/themes/wcm_omega/preprocess/fieldable-panels-pane.preprocess.inc b/profiles/wcm_base/themes/wcm_omega/preprocess/fieldable-panels-pane.preprocess.inc index aa66d361..65d6032b 100644 --- a/profiles/wcm_base/themes/wcm_omega/preprocess/fieldable-panels-pane.preprocess.inc +++ b/profiles/wcm_base/themes/wcm_omega/preprocess/fieldable-panels-pane.preprocess.inc @@ -60,8 +60,8 @@ function wcm_omega_preprocess_fieldable_panels_pane(&$vars) { // Image panes elseif ($type == 'image') { - if (!empty($vars['content']['field_basic_image_image'])) { - $vars['content']['field_basic_image_image'][0]['#path']['path'] = !empty($vars['elements']['#fieldable_panels_pane']->field_ocio_link) ? $vars['elements']['#fieldable_panels_pane']->field_ocio_link['und'][0]['display_url'] : NULL; + if (!empty($vars['content']['field_basic_image_image']) && !empty($vars['elements']['#fieldable_panels_pane']->field_ocio_link)) { + $vars['content']['field_basic_image_image'][0]['#path'] = array('path' => $vars['elements']['#fieldable_panels_pane']->field_ocio_link['und'][0]['display_url']); } } } diff --git a/profiles/wcm_base/themes/wcm_omega/preprocess/page.preprocess.inc b/profiles/wcm_base/themes/wcm_omega/preprocess/page.preprocess.inc index 7960fb8a..8d3ac908 100644 --- a/profiles/wcm_base/themes/wcm_omega/preprocess/page.preprocess.inc +++ b/profiles/wcm_base/themes/wcm_omega/preprocess/page.preprocess.inc @@ -11,7 +11,7 @@ function wcm_omega_preprocess_page(&$vars) { $vars['main_classes'] = join(' ', $classes); - //render landing page top and bottom banner images in regions outside of 'content' + //render landing page top and bottom banner images in regions outside of 'content' $vars['landing_page'] = isset($vars['node']) && $vars['node']->type == 'ocio_landing_page'; if ($vars['landing_page']) { @@ -36,9 +36,9 @@ function wcm_omega_preprocess_page(&$vars) { $top_banner_text['#label_display'] = 'hidden'; $top_banner_url = field_view_field('node', $vars['node'], 'field_banner_image_text_link'); - if (!empty($top_banner_url)) { - $top_banner_text[0]['#markup'] = l($top_banner_text['#items'][0]['value'], $top_banner_url['#items'][0]['url']); - } + if (!empty($top_banner_url)) { + $top_banner_text[0]['#markup'] = l($top_banner_text['#items'][0]['value'], $top_banner_url['#items'][0]['url']); + } $vars['page']['hero']['top_banner']['#markup'] .= drupal_render($top_banner_text); } diff --git a/profiles/wcm_base/wcm_base.make b/profiles/wcm_base/wcm_base.make index 418b3974..f0d12313 100644 --- a/profiles/wcm_base/wcm_base.make +++ b/profiles/wcm_base/wcm_base.make @@ -485,31 +485,31 @@ libraries[ocio_modernizr][download][branch] = 7.x-1.x ; The Panopoly Foundation -projects[panopoly_core][version] = 1.56 +projects[panopoly_core][version] = 1.58 projects[panopoly_core][subdir] = panopoly -projects[panopoly_theme][version] = 1.56 +projects[panopoly_theme][version] = 1.58 projects[panopoly_theme][subdir] = panopoly -projects[panopoly_magic][version] = 1.56 +projects[panopoly_magic][version] = 1.58 projects[panopoly_magic][subdir] = panopoly -projects[panopoly_widgets][version] = 1.56 +projects[panopoly_widgets][version] = 1.58 projects[panopoly_widgets][subdir] = panopoly -projects[panopoly_admin][version] = 1.56 +projects[panopoly_admin][version] = 1.58 projects[panopoly_admin][subdir] = panopoly ; The Panopoly Toolset -projects[panopoly_pages][version] = 1.56 +projects[panopoly_pages][version] = 1.58 projects[panopoly_pages][subdir] = panopoly -projects[panopoly_search][version] = 1.56 +projects[panopoly_search][version] = 1.58 projects[panopoly_search][subdir] = panopoly ; For running the automated tests. -projects[panopoly_test][version] = 1.56 +projects[panopoly_test][version] = 1.58 projects[panopoly_test][subdir] = panopoly -- GitLab