Revert "Issue #2085243 by dawehner: Rename Menu module into Menu UI module."
This reverts commit 07f63fe6f3
.
8.0.x
parent
f122f87451
commit
62ba47d26a
|
@ -422,8 +422,8 @@ function menu_secondary_menu() {
|
|||
* Returns menu name, if exist
|
||||
*/
|
||||
function _menu_get_links_source($name, $default) {
|
||||
$config = \Drupal::config('menu_ui.settings');
|
||||
return \Drupal::moduleHandler()->moduleExists('menu_ui') ? $config->get($name) : $default;
|
||||
$config = \Drupal::config('menu.settings');
|
||||
return \Drupal::moduleHandler()->moduleExists('menu') ? $config->get($name) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,7 @@ class BlockLanguageCacheTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'language', 'menu_ui');
|
||||
public static $modules = array('block', 'language', 'menu');
|
||||
|
||||
/**
|
||||
* List of langcodes.
|
||||
|
|
|
@ -30,7 +30,7 @@ class ConfigTranslationListUiTest extends WebTestBase {
|
|||
'custom_block',
|
||||
'field',
|
||||
'field_ui',
|
||||
'menu_ui',
|
||||
'menu',
|
||||
'node',
|
||||
'shortcut',
|
||||
'taxonomy',
|
||||
|
|
|
@ -20,7 +20,7 @@ class ForumTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('taxonomy', 'comment', 'forum', 'node', 'block', 'menu_ui', 'help');
|
||||
public static $modules = array('taxonomy', 'comment', 'forum', 'node', 'block', 'menu', 'help');
|
||||
|
||||
/**
|
||||
* A user with various administrative privileges.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Schema for configuration files of the Menu module.
|
||||
|
||||
menu_ui.settings:
|
||||
menu.settings:
|
||||
type: mapping
|
||||
label: 'Menu settings'
|
||||
mapping:
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Controller\MenuController.
|
||||
* Contains \Drupal\menu\Controller\MenuController.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Controller;
|
||||
namespace Drupal\menu\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
@ -34,7 +34,7 @@ class MenuController extends ControllerBase {
|
|||
$available_menus[$menu] = $menu;
|
||||
}
|
||||
}
|
||||
$options = _menu_ui_get_options(menu_ui_get_menus(), $available_menus, array('mlid' => 0));
|
||||
$options = _menu_get_options(menu_get_menus(), $available_menus, array('mlid' => 0));
|
||||
|
||||
return new JsonResponse($options);
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Form\MenuDeleteForm.
|
||||
* Contains \Drupal\menu\Form\MenuDeleteForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Form;
|
||||
namespace Drupal\menu\Form;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Entity\EntityConfirmFormBase;
|
||||
|
@ -66,7 +66,7 @@ class MenuDeleteForm extends EntityConfirmFormBase {
|
|||
*/
|
||||
public function getCancelRoute() {
|
||||
return array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $this->entity->id(),
|
||||
),
|
||||
|
@ -97,7 +97,7 @@ class MenuDeleteForm extends EntityConfirmFormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function submit(array $form, array &$form_state) {
|
||||
$form_state['redirect_route']['route_name'] = 'menu_ui.overview_page';
|
||||
$form_state['redirect_route']['route_name'] = 'menu.overview_page';
|
||||
|
||||
// Locked menus may not be deleted.
|
||||
if ($this->entity->isLocked()) {
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Form\MenuLinkDeleteForm.
|
||||
* Contains \Drupal\menu\Form\MenuLinkDeleteForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Form;
|
||||
namespace Drupal\menu\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityConfirmFormBase;
|
||||
|
||||
|
@ -26,7 +26,7 @@ class MenuLinkDeleteForm extends EntityConfirmFormBase {
|
|||
*/
|
||||
public function getCancelRoute() {
|
||||
return array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $this->entity->menu_name,
|
||||
),
|
||||
|
@ -42,7 +42,7 @@ class MenuLinkDeleteForm extends EntityConfirmFormBase {
|
|||
drupal_set_message(t('The menu link %title has been deleted.', $t_args));
|
||||
watchdog('menu', 'Deleted menu link %title.', $t_args, WATCHDOG_NOTICE);
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $this->entity->menu_name,
|
||||
),
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Form\MenuLinkResetForm.
|
||||
* Contains \Drupal\menu\Form\MenuLinkResetForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Form;
|
||||
namespace Drupal\menu\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityConfirmFormBase;
|
||||
|
||||
|
@ -26,7 +26,7 @@ class MenuLinkResetForm extends EntityConfirmFormBase {
|
|||
*/
|
||||
public function getCancelRoute() {
|
||||
return array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $this->entity->menu_name,
|
||||
),
|
||||
|
@ -54,7 +54,7 @@ class MenuLinkResetForm extends EntityConfirmFormBase {
|
|||
$new_menu_link = $this->entity->reset();
|
||||
drupal_set_message(t('The menu link was reset to its default settings.'));
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $new_menu_link->menu_name,
|
||||
),
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\MenuFormController.
|
||||
* Contains \Drupal\menu\MenuFormController.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui;
|
||||
namespace Drupal\menu;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Entity\EntityFormController;
|
||||
|
@ -240,7 +240,7 @@ class MenuFormController extends EntityFormController {
|
|||
*
|
||||
* This form constructor can be integrated as a section into another form. It
|
||||
* relies on the following keys in $form_state:
|
||||
* - menu: A loaded menu definition, as returned by menu_ui_load().
|
||||
* - menu: A loaded menu definition, as returned by menu_load().
|
||||
* - menu_overview_form_parents: An array containing the parent keys to this
|
||||
* form.
|
||||
* Forms integrating this section should call menu_overview_form_submit() from
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\MenuListBuilder.
|
||||
* Contains \Drupal\menu\MenuListBuilder.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui;
|
||||
namespace Drupal\menu;
|
||||
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\MenuSettingsForm.
|
||||
* Contains \Drupal\menu\MenuSettingsForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui;
|
||||
namespace Drupal\menu;
|
||||
|
||||
use Drupal\Core\Form\ConfigFormBase;
|
||||
|
||||
|
@ -25,13 +25,13 @@ class MenuSettingsForm extends ConfigFormBase {
|
|||
* Implements \Drupal\Core\Form\FormInterface::buildForm().
|
||||
*/
|
||||
public function buildForm(array $form, array &$form_state) {
|
||||
$config = $this->configFactory->get('menu_ui.settings');
|
||||
$config = $this->configFactory->get('menu.settings');
|
||||
$form['intro'] = array(
|
||||
'#type' => 'item',
|
||||
'#markup' => t('The menu module allows on-the-fly creation of menu links in the content authoring forms. To configure these settings for a particular content type, visit the <a href="@content-types">Content types</a> page, click the <em>edit</em> link for the content type, and go to the <em>Menu settings</em> section.', array('@content-types' => url('admin/structure/types'))),
|
||||
);
|
||||
|
||||
$menu_options = menu_ui_get_menus();
|
||||
$menu_options = menu_get_menus();
|
||||
|
||||
$main = $config->get('main_links');
|
||||
$form['menu_main_links_source'] = array(
|
||||
|
@ -61,7 +61,7 @@ class MenuSettingsForm extends ConfigFormBase {
|
|||
* Implements \Drupal\Core\Form\FormInterface::submitForm().
|
||||
*/
|
||||
public function submitForm(array &$form, array &$form_state) {
|
||||
$this->configFactory->get('menu_ui.settings')
|
||||
$this->configFactory->get('menu.settings')
|
||||
->set('main_links', $form_state['values']['menu_main_links_source'])
|
||||
->set('secondary_links', $form_state['values']['menu_secondary_links_source'])
|
||||
->save();
|
|
@ -5,7 +5,7 @@
|
|||
* Contains \Drupal\menu\Tests\MenuCacheTagsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\system\Tests\Cache\PageCacheTagsTestBase;
|
||||
|
||||
|
@ -17,7 +17,7 @@ class MenuCacheTagsTest extends PageCacheTagsTestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('menu_ui', 'block', 'test_page_test');
|
||||
public static $modules = array('menu', 'block', 'test_page_test');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Tests for menu_ui language settings.
|
||||
* Tests for menu language settings.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Language\Language;
|
||||
|
@ -174,7 +174,7 @@ class MenuLanguageTest extends MenuWebTestBase {
|
|||
$this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
|
||||
|
||||
// Check that the language settings were saved.
|
||||
$menu = menu_ui_load($menu_name);
|
||||
$menu = menu_load($menu_name);
|
||||
$this->assertEqual($menu->langcode, 'en');
|
||||
|
||||
// Remove English language. To do that another language has to be set as
|
||||
|
@ -186,7 +186,7 @@ class MenuLanguageTest extends MenuWebTestBase {
|
|||
|
||||
// Save the menu again and check if the language is still the same.
|
||||
$this->drupalPostForm("admin/structure/menu/manage/$menu_name", array(), t('Save'));
|
||||
$menu = menu_ui_load($menu_name);
|
||||
$menu = menu_load($menu_name);
|
||||
$this->assertEqual($menu->langcode, 'en');
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\menu_ui\Tests\MenuNodeTest.
|
||||
* Definition of Drupal\menu\Tests\MenuNodeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
|
@ -19,7 +19,7 @@ class MenuNodeTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('menu_ui', 'test_page_test', 'node');
|
||||
public static $modules = array('menu', 'test_page_test', 'node');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\menu_ui\Tests\MenuTest.
|
||||
* Definition of Drupal\menu\Tests\MenuTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Json;
|
||||
|
||||
|
@ -199,7 +199,7 @@ class MenuTest extends MenuWebTestBase {
|
|||
|
||||
// Enable the block.
|
||||
$this->drupalPlaceBlock('system_menu_block:' . $menu_name);
|
||||
return menu_ui_load($menu_name);
|
||||
return menu_load($menu_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,7 +216,7 @@ class MenuTest extends MenuWebTestBase {
|
|||
$this->drupalPostForm("admin/structure/menu/manage/$menu_name/delete", array(), t('Delete'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $label)), 'Custom menu was deleted');
|
||||
$this->assertFalse(menu_ui_load($menu_name), 'Custom menu was deleted');
|
||||
$this->assertFalse(menu_load($menu_name), 'Custom menu was deleted');
|
||||
// Test if all menu links associated to the menu were removed from database.
|
||||
$result = entity_load_multiple_by_properties('menu_link', array('menu_name' => $menu_name));
|
||||
$this->assertFalse($result, 'All menu links associated to the custom menu were deleted.');
|
||||
|
@ -477,7 +477,7 @@ class MenuTest extends MenuWebTestBase {
|
|||
$response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-page')));
|
||||
$this->assertResponse(200);
|
||||
$json = Json::decode($response);
|
||||
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="menu-ui-edit"><a href="' . base_path() . 'admin/structure/menu/manage/tools">Edit menu</a></li></ul>');
|
||||
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="menu-edit"><a href="' . base_path() . 'admin/structure/menu/manage/tools">Edit menu</a></li></ul>');
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Tests\MenuUninstallTest.
|
||||
* Contains \Drupal\menu\Tests\MenuUninstallTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
|
@ -19,7 +19,7 @@ class MenuUninstallTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('menu_ui');
|
||||
public static $modules = array('menu');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
@ -33,7 +33,7 @@ class MenuUninstallTest extends WebTestBase {
|
|||
* Tests Menu uninstall.
|
||||
*/
|
||||
public function testMenuUninstall() {
|
||||
\Drupal::moduleHandler()->uninstall(array('menu_ui'));
|
||||
\Drupal::moduleHandler()->uninstall(array('menu'));
|
||||
|
||||
$this->assertTrue(entity_load('menu', 'admin', TRUE), 'The \'admin\' menu still exists after uninstalling menu module.');
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\menu_ui\Tests\MenuWebTestBase.
|
||||
* Contains \Drupal\menu\Tests\MenuWebTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu_ui\Tests;
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
|
@ -19,7 +19,7 @@ class MenuWebTestBase extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('menu_ui');
|
||||
public static $modules = array('menu');
|
||||
|
||||
/**
|
||||
* Fetchs the menu item from the database and compares it to expected item.
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Drupal.behaviors.menuUiChangeParentItems = {
|
||||
Drupal.behaviors.menuChangeParentItems = {
|
||||
attach: function (context, settings) {
|
||||
var $menu = $('#edit-menu');
|
||||
$menu.once('menu-parent', function () {
|
||||
// Update the list of available parent menu items to match the initial
|
||||
// available menus.
|
||||
Drupal.menuUiUpdateParentList();
|
||||
Drupal.menuUpdateParentList();
|
||||
|
||||
// Update list of available parent menu items.
|
||||
$menu.on('change', 'input', Drupal.menuUiUpdateParentList);
|
||||
$menu.on('change', 'input', Drupal.menuUpdateParentList);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -19,7 +19,7 @@
|
|||
/**
|
||||
* Function to set the options of the menu parent item dropdown.
|
||||
*/
|
||||
Drupal.menuUiUpdateParentList = function () {
|
||||
Drupal.menuUpdateParentList = function () {
|
||||
var $menu = $('#edit-menu');
|
||||
var values = [];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
menu_edit:
|
||||
title: 'Edit menu'
|
||||
route_name: 'menu.menu_edit'
|
||||
group: menu
|
|
@ -1,9 +1,9 @@
|
|||
name: Menu Ui
|
||||
name: Menu
|
||||
type: module
|
||||
description: 'Allows administrators to customize the site navigation menu.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
configure: menu_ui.overview_page
|
||||
configure: menu.overview_page
|
||||
dependencies:
|
||||
- menu_link
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the menu_ui module.
|
||||
* Install, update and uninstall functions for the menu module.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Uuid\Uuid;
|
||||
|
@ -10,7 +10,7 @@ use Drupal\Component\Uuid\Uuid;
|
|||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function menu_ui_install() {
|
||||
function menu_install() {
|
||||
// Rebuild all the menu data.
|
||||
// @todo - remove this when we understand why removing it breaks the
|
||||
// standard install profile, possibly need to be handled in
|
||||
|
@ -31,6 +31,6 @@ function menu_ui_install() {
|
|||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function menu_ui_uninstall() {
|
||||
function menu_uninstall() {
|
||||
\Drupal::service('router.builder')->setRebuildNeeded();
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Drupal.behaviors.menuUiDetailsSummaries = {
|
||||
Drupal.behaviors.menuDetailsSummaries = {
|
||||
attach: function (context) {
|
||||
$(context).find('.menu-link-form').drupalSetSummary(function (context) {
|
||||
var $context = $(context);
|
||||
|
@ -19,7 +19,7 @@
|
|||
/**
|
||||
* Automatically fill in a menu link title, if possible.
|
||||
*/
|
||||
Drupal.behaviors.menuUiLinkAutomaticTitle = {
|
||||
Drupal.behaviors.menuLinkAutomaticTitle = {
|
||||
attach: function (context) {
|
||||
var $context = $(context);
|
||||
$context.find('.menu-link-form').each(function () {
|
|
@ -1,16 +1,16 @@
|
|||
drupal.menu_ui:
|
||||
drupal.menu:
|
||||
version: VERSION
|
||||
js:
|
||||
menu_ui.js: {}
|
||||
menu.js: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
- core/drupal
|
||||
- core/drupal.form
|
||||
|
||||
drupal.menu_ui.admin:
|
||||
drupal.menu.admin:
|
||||
version: VERSION
|
||||
js:
|
||||
menu_ui.admin.js: {}
|
||||
menu.admin.js: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
- core/drupal
|
|
@ -0,0 +1,11 @@
|
|||
menu_link_add:
|
||||
route_name: menu.link_add
|
||||
title: 'Add link'
|
||||
appears_on:
|
||||
- menu.menu_edit
|
||||
|
||||
menu.menu_add:
|
||||
route_name: menu.menu_add
|
||||
title: 'Add menu'
|
||||
appears_on:
|
||||
- menu.overview_page
|
|
@ -0,0 +1,15 @@
|
|||
menu.menu_edit:
|
||||
title: 'Edit menu'
|
||||
route_name: menu.menu_edit
|
||||
base_route: menu.menu_edit
|
||||
|
||||
menu.overview_page:
|
||||
title: 'List'
|
||||
route_name: menu.overview_page
|
||||
base_route: menu.overview_page
|
||||
|
||||
menu.settings:
|
||||
title: 'Settings'
|
||||
route_name: menu.settings
|
||||
base_route: menu.overview_page
|
||||
weight: 100
|
|
@ -1,5 +1,5 @@
|
|||
menu_ui.overview_page:
|
||||
menu.overview_page:
|
||||
title: Menus
|
||||
description: 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.'
|
||||
route_name: menu_ui.overview_page
|
||||
route_name: menu.overview_page
|
||||
parent: system.admin_structure
|
|
@ -30,16 +30,16 @@ const MENU_MAX_MENU_NAME_LENGTH_UI = 27;
|
|||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function menu_ui_help($path, $arg) {
|
||||
function menu_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/help#menu_ui':
|
||||
case 'admin/help#menu':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Menu module provides an interface for managing menus. A menu is a hierarchical collection of links, which can be within or external to the site, generally used for navigation. For more information, see the <a href="!menu">online documentation for the Menu module</a>.', array('!menu' => 'https://drupal.org/documentation/modules/menu/')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Managing menus') . '</dt>';
|
||||
$output .= '<dd>' . t('Users with the <em>Administer menus and menu items</em> permission can add, edit, and delete custom menus on the <a href="!menu">Menus page</a>. Custom menus can be special site menus, menus of external links, or any combination of internal and external links. You may create an unlimited number of additional menus, each of which will automatically have an associated block (if you have the <a href="!block_help">Block module</a> installed). By selecting <em>Edit menu</em>, you can add, edit, or delete links for a given menu. The links listing page provides a drag-and-drop interface for controlling the order of links, and creating a hierarchy within the menu.', array('!block_help' => \Drupal::url('help.page', array('name' => 'block')), '!menu' => \Drupal::url('menu_ui.overview_page'))) . '</dd>';
|
||||
$output .= '<dd>' . t('Users with the <em>Administer menus and menu items</em> permission can add, edit, and delete custom menus on the <a href="!menu">Menus page</a>. Custom menus can be special site menus, menus of external links, or any combination of internal and external links. You may create an unlimited number of additional menus, each of which will automatically have an associated block (if you have the <a href="!block_help">Block module</a> installed). By selecting <em>Edit menu</em>, you can add, edit, or delete links for a given menu. The links listing page provides a drag-and-drop interface for controlling the order of links, and creating a hierarchy within the menu.', array('!block_help' => \Drupal::url('help.page', array('name' => 'block')), '!menu' => \Drupal::url('menu.overview_page'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Displaying menus') . '</dt>';
|
||||
$output .= '<dd>' . t('If you have the Block module enabled, then each menu that you create is rendered in a block that you enable and position on the <a href="!blocks">Block layout page</a>. In some <a href="!themes">themes</a>, the main menu and possibly the secondary menu will be output automatically; you may be able to disable this behavior on the <a href="!themes">theme\'s settings page</a>.', array('!blocks' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#', '!themes' => \Drupal::url('system.themes_page'), '!theme_settings' => \Drupal::url('system.theme_settings'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
|
@ -56,7 +56,7 @@ function menu_ui_help($path, $arg) {
|
|||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function menu_ui_permission() {
|
||||
function menu_permission() {
|
||||
return array(
|
||||
'administer menu' => array(
|
||||
'title' => t('Administer menus and menu items'),
|
||||
|
@ -67,27 +67,27 @@ function menu_ui_permission() {
|
|||
/**
|
||||
* Implements hook_entity_type_build().
|
||||
*/
|
||||
function menu_ui_entity_type_build(array &$entity_types) {
|
||||
function menu_entity_type_build(array &$entity_types) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
$entity_types['menu']
|
||||
->setFormClass('add', 'Drupal\menu_ui\MenuFormController')
|
||||
->setFormClass('edit', 'Drupal\menu_ui\MenuFormController')
|
||||
->setFormClass('delete', 'Drupal\menu_ui\Form\MenuDeleteForm')
|
||||
->setListBuilderClass('Drupal\menu_ui\MenuListBuilder')
|
||||
->setLinkTemplate('add-form', 'menu_ui.link_add')
|
||||
->setLinkTemplate('delete-form', 'menu_ui.delete_menu')
|
||||
->setLinkTemplate('edit-form', 'menu_ui.menu_edit');
|
||||
->setFormClass('add', 'Drupal\menu\MenuFormController')
|
||||
->setFormClass('edit', 'Drupal\menu\MenuFormController')
|
||||
->setFormClass('delete', 'Drupal\menu\Form\MenuDeleteForm')
|
||||
->setListBuilderClass('Drupal\menu\MenuListBuilder')
|
||||
->setLinkTemplate('add-form', 'menu.link_add')
|
||||
->setLinkTemplate('delete-form', 'menu.delete_menu')
|
||||
->setLinkTemplate('edit-form', 'menu.menu_edit');
|
||||
|
||||
$entity_types['menu_link']
|
||||
->setFormClass('delete', 'Drupal\menu_ui\Form\MenuLinkDeleteForm')
|
||||
->setFormClass('reset', 'Drupal\menu_ui\Form\MenuLinkResetForm')
|
||||
->setLinkTemplate('delete-form', 'menu_ui.link_delete');
|
||||
->setFormClass('delete', 'Drupal\menu\Form\MenuLinkDeleteForm')
|
||||
->setFormClass('reset', 'Drupal\menu\Form\MenuLinkResetForm')
|
||||
->setLinkTemplate('delete-form', 'menu.link_delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_bundle_info().
|
||||
*/
|
||||
function menu_ui_entity_bundle_info() {
|
||||
function menu_entity_bundle_info() {
|
||||
$bundles = array();
|
||||
$config_names = \Drupal::configFactory()->listAll('system.menu.');
|
||||
foreach ($config_names as $config_name) {
|
||||
|
@ -103,10 +103,10 @@ function menu_ui_entity_bundle_info() {
|
|||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function menu_ui_theme() {
|
||||
function menu_theme() {
|
||||
return array(
|
||||
'menu_overview_form' => array(
|
||||
'file' => 'menu_ui.admin.inc',
|
||||
'file' => 'menu.admin.inc',
|
||||
'render element' => 'form',
|
||||
),
|
||||
);
|
||||
|
@ -120,14 +120,14 @@ function menu_ui_theme() {
|
|||
* @return
|
||||
* Array defining the custom menu, or NULL if the menu doesn't exist.
|
||||
*/
|
||||
function menu_ui_load($menu_name) {
|
||||
function menu_load($menu_name) {
|
||||
return entity_load('menu', $menu_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_insert()
|
||||
*/
|
||||
function menu_ui_menu_insert(Menu $menu) {
|
||||
function menu_menu_insert(Menu $menu) {
|
||||
menu_cache_clear_all();
|
||||
// Invalidate the block cache to update menu-based derivatives.
|
||||
if (\Drupal::moduleHandler()->moduleExists('block')) {
|
||||
|
@ -143,7 +143,7 @@ function menu_ui_menu_insert(Menu $menu) {
|
|||
// See menu_set_active_menu_names().
|
||||
$config = \Drupal::config('system.menu');
|
||||
|
||||
$active_menus = $config->get('active_menus_default') ?: array_keys(menu_ui_get_menus());
|
||||
$active_menus = $config->get('active_menus_default') ?: array_keys(menu_get_menus());
|
||||
if (!in_array($menu->id(), $active_menus)) {
|
||||
$active_menus[] = $menu->id();
|
||||
$config
|
||||
|
@ -155,7 +155,7 @@ function menu_ui_menu_insert(Menu $menu) {
|
|||
/**
|
||||
* Implements hook_menu_update().
|
||||
*/
|
||||
function menu_ui_menu_update(Menu $menu) {
|
||||
function menu_menu_update(Menu $menu) {
|
||||
menu_cache_clear_all();
|
||||
// Invalidate the block cache to update menu-based derivatives.
|
||||
if (\Drupal::moduleHandler()->moduleExists('block')) {
|
||||
|
@ -166,13 +166,13 @@ function menu_ui_menu_update(Menu $menu) {
|
|||
/**
|
||||
* Implements hook_menu_predelete().
|
||||
*/
|
||||
function menu_ui_menu_predelete(Menu $menu) {
|
||||
function menu_menu_predelete(Menu $menu) {
|
||||
// Delete all links from the menu.
|
||||
menu_delete_links($menu->id());
|
||||
|
||||
// Remove menu from active menus variable.
|
||||
$config = \Drupal::config('system.menu');
|
||||
$active_menus = $config->get('active_menus_default') ?: array_keys(menu_ui_get_menus());
|
||||
$active_menus = $config->get('active_menus_default') ?: array_keys(menu_get_menus());
|
||||
if (in_array($menu->id(), $active_menus)) {
|
||||
$active_menus = array_diff($active_menus, array($menu->id()));
|
||||
// Prevent the gap left by the removed menu from causing array indices to
|
||||
|
@ -187,7 +187,7 @@ function menu_ui_menu_predelete(Menu $menu) {
|
|||
/**
|
||||
* Implements hook_menu_delete().
|
||||
*/
|
||||
function menu_ui_menu_delete(Menu $menu) {
|
||||
function menu_menu_delete(Menu $menu) {
|
||||
menu_cache_clear_all();
|
||||
|
||||
// Invalidate the block cache to update menu-based derivatives.
|
||||
|
@ -201,7 +201,7 @@ function menu_ui_menu_delete(Menu $menu) {
|
|||
* menu link.
|
||||
*
|
||||
* @param array $menus
|
||||
* An array of menu names and titles, such as from menu_ui_get_menus().
|
||||
* An array of menu names and titles, such as from menu_get_menus().
|
||||
* @param \Drupal\menu_link\Entity\MenuLink $menu_link
|
||||
* The menu link for which to generate a list of parents.
|
||||
* If $menu_link->id() == 0 then the complete tree is returned.
|
||||
|
@ -216,12 +216,12 @@ function menu_ui_menu_delete(Menu $menu) {
|
|||
* @todo This has to be turned into a #process form element callback. The
|
||||
* 'override_parent_selector' variable is entirely superfluous.
|
||||
*/
|
||||
function menu_ui_parent_options(array $menus, MenuLink $menu_link = NULL, $type = NULL) {
|
||||
function menu_parent_options(array $menus, MenuLink $menu_link = NULL, $type = NULL) {
|
||||
// The menu_links table can be practically any size and we need a way to
|
||||
// allow contrib modules to provide more scalable pattern choosers.
|
||||
// hook_form_alter is too late in itself because all the possible parents are
|
||||
// retrieved here, unless override_parent_selector is set to TRUE.
|
||||
if (\Drupal::config('menu_ui.settings')->get('override_parent_selector')) {
|
||||
if (\Drupal::config('menu.settings')->get('override_parent_selector')) {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
@ -242,19 +242,19 @@ function menu_ui_parent_options(array $menus, MenuLink $menu_link = NULL, $type
|
|||
}
|
||||
}
|
||||
|
||||
return _menu_ui_get_options($menus, $available_menus, $menu_link);
|
||||
return _menu_get_options($menus, $available_menus, $menu_link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the items of the given menu.
|
||||
*/
|
||||
function _menu_ui_get_options($menus, $available_menus, $item) {
|
||||
function _menu_get_options($menus, $available_menus, $item) {
|
||||
// If the item has children, there is an added limit to the depth of valid parents.
|
||||
if (isset($item['parent_depth_limit'])) {
|
||||
$limit = $item['parent_depth_limit'];
|
||||
}
|
||||
else {
|
||||
$limit = _menu_ui_parent_depth_limit($item);
|
||||
$limit = _menu_parent_depth_limit($item);
|
||||
}
|
||||
|
||||
/** @var \Drupal\menu_link\MenuTreeInterface $menu_tree */
|
||||
|
@ -265,16 +265,16 @@ function _menu_ui_get_options($menus, $available_menus, $item) {
|
|||
if (isset($available_menus[$menu_name])) {
|
||||
$tree = $menu_tree->buildAllData($menu_name, NULL);
|
||||
$options[$menu_name . ':0'] = '<' . $title . '>';
|
||||
_menu_ui_parents_recurse($tree, $menu_name, '--', $options, $item['mlid'], $limit);
|
||||
_menu_parents_recurse($tree, $menu_name, '--', $options, $item['mlid'], $limit);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive helper function for menu_ui_parent_options().
|
||||
* Recursive helper function for menu_parent_options().
|
||||
*/
|
||||
function _menu_ui_parents_recurse($tree, $menu_name, $indent, &$options, $exclude, $depth_limit) {
|
||||
function _menu_parents_recurse($tree, $menu_name, $indent, &$options, $exclude, $depth_limit) {
|
||||
foreach ($tree as $data) {
|
||||
if ($data['link']['depth'] > $depth_limit) {
|
||||
// Don't iterate through any links on this level.
|
||||
|
@ -287,7 +287,7 @@ function _menu_ui_parents_recurse($tree, $menu_name, $indent, &$options, $exclud
|
|||
}
|
||||
$options[$menu_name . ':' . $data['link']['mlid']] = $title;
|
||||
if ($data['below']) {
|
||||
_menu_ui_parents_recurse($data['below'], $menu_name, $indent . '--', $options, $exclude, $depth_limit);
|
||||
_menu_parents_recurse($data['below'], $menu_name, $indent . '--', $options, $exclude, $depth_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ function _menu_ui_parents_recurse($tree, $menu_name, $indent, &$options, $exclud
|
|||
/**
|
||||
* Implements hook_block_view_BASE_BLOCK_ID_alter() for 'system_menu_block'.
|
||||
*/
|
||||
function menu_ui_block_view_system_menu_block_alter(array &$build, BlockPluginInterface $block) {
|
||||
function menu_block_view_system_menu_block_alter(array &$build, BlockPluginInterface $block) {
|
||||
// Add contextual links for system menu blocks.
|
||||
$menus = menu_list_system_menus();
|
||||
$menu_name = $block->getDerivativeId();
|
||||
|
@ -312,21 +312,21 @@ function menu_ui_block_view_system_menu_block_alter(array &$build, BlockPluginIn
|
|||
/**
|
||||
* Implements hook_node_insert().
|
||||
*/
|
||||
function menu_ui_node_insert(EntityInterface $node) {
|
||||
menu_ui_node_save($node);
|
||||
function menu_node_insert(EntityInterface $node) {
|
||||
menu_node_save($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_node_update().
|
||||
*/
|
||||
function menu_ui_node_update(EntityInterface $node) {
|
||||
menu_ui_node_save($node);
|
||||
function menu_node_update(EntityInterface $node) {
|
||||
menu_node_save($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_node_type_insert().
|
||||
*/
|
||||
function menu_ui_node_type_insert(NodeTypeInterface $type) {
|
||||
function menu_node_type_insert(NodeTypeInterface $type) {
|
||||
if ($type->isSyncing()) {
|
||||
return;
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ function menu_ui_node_type_insert(NodeTypeInterface $type) {
|
|||
/**
|
||||
* Implements hook_node_type_delete().
|
||||
*/
|
||||
function menu_ui_node_type_delete(NodeTypeInterface $type) {
|
||||
function menu_node_type_delete(NodeTypeInterface $type) {
|
||||
if ($type->isSyncing()) {
|
||||
return;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ function menu_ui_node_type_delete(NodeTypeInterface $type) {
|
|||
/**
|
||||
* Helper for hook_node_insert() and hook_node_update().
|
||||
*/
|
||||
function menu_ui_node_save(EntityInterface $node) {
|
||||
function menu_node_save(EntityInterface $node) {
|
||||
if (isset($node->menu)) {
|
||||
$link = &$node->menu;
|
||||
if (empty($link['enabled'])) {
|
||||
|
@ -378,7 +378,7 @@ function menu_ui_node_save(EntityInterface $node) {
|
|||
/**
|
||||
* Implements hook_node_predelete().
|
||||
*/
|
||||
function menu_ui_node_predelete(EntityInterface $node) {
|
||||
function menu_node_predelete(EntityInterface $node) {
|
||||
// Delete all menu module links that point to this node.
|
||||
$query = \Drupal::entityQuery('menu_link')
|
||||
->condition('link_path', 'node/' . $node->id())
|
||||
|
@ -393,7 +393,7 @@ function menu_ui_node_predelete(EntityInterface $node) {
|
|||
/**
|
||||
* Implements hook_node_prepare_form().
|
||||
*/
|
||||
function menu_ui_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
|
||||
function menu_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
|
||||
if (empty($node->menu)) {
|
||||
// Prepare the node for the edit form so that $node->menu always exists.
|
||||
$node_type_config = \Drupal::config('menu.entity.node.' . $node->getType());
|
||||
|
@ -407,7 +407,7 @@ function menu_ui_node_prepare_form(NodeInterface $node, $operation, array &$form
|
|||
$query = \Drupal::entityQuery('menu_link')
|
||||
->condition('link_path', 'node/' . $node->id())
|
||||
->condition('menu_name', $menu_name)
|
||||
->condition('module', 'menu_ui')
|
||||
->condition('module', 'menu')
|
||||
->sort('mlid', 'ASC')
|
||||
->range(0, 1);
|
||||
$result = $query->execute();
|
||||
|
@ -419,7 +419,7 @@ function menu_ui_node_prepare_form(NodeInterface $node, $operation, array &$form
|
|||
$query = \Drupal::entityQuery('menu_link')
|
||||
->condition('link_path', 'node/' . $node->id())
|
||||
->condition('menu_name', array_values($type_menus), 'IN')
|
||||
->condition('module', 'menu_ui')
|
||||
->condition('module', 'menu')
|
||||
->sort('mlid', 'ASC')
|
||||
->range(0, 1);
|
||||
$result = $query->execute();
|
||||
|
@ -443,14 +443,14 @@ function menu_ui_node_prepare_form(NodeInterface $node, $operation, array &$form
|
|||
}
|
||||
// Find the depth limit for the parent select.
|
||||
if (!isset($node->menu['parent_depth_limit'])) {
|
||||
$node->menu['parent_depth_limit'] = _menu_ui_parent_depth_limit($node->menu);
|
||||
$node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the depth limit for items in the parent select.
|
||||
*/
|
||||
function _menu_ui_parent_depth_limit($item) {
|
||||
function _menu_parent_depth_limit($item) {
|
||||
return MENU_MAX_DEPTH - 1 - (($item['mlid'] && $item['has_children']) ? entity_get_controller('menu_link')->findChildrenRelativeDepth($item) : 0);
|
||||
}
|
||||
|
||||
|
@ -459,15 +459,15 @@ function _menu_ui_parent_depth_limit($item) {
|
|||
*
|
||||
* Adds menu item fields to the node form.
|
||||
*
|
||||
* @see menu_ui_node_submit()
|
||||
* @see menu_node_submit()
|
||||
*/
|
||||
function menu_ui_form_node_form_alter(&$form, $form_state) {
|
||||
function menu_form_node_form_alter(&$form, $form_state) {
|
||||
// Generate a list of possible parents (not including this link or descendants).
|
||||
// @todo This must be handled in a #process handler.
|
||||
$node = $form_state['controller']->getEntity();
|
||||
$link = $node->menu;
|
||||
$type = $node->getType();
|
||||
$options = menu_ui_parent_options(menu_ui_get_menus(), $link, $type);
|
||||
$options = menu_parent_options(menu_get_menus(), $link, $type);
|
||||
// If no possible parent menu items were found, there is nothing to display.
|
||||
if (empty($options)) {
|
||||
return;
|
||||
|
@ -560,9 +560,9 @@ function menu_ui_form_node_form_alter(&$form, $form_state) {
|
|||
/**
|
||||
* Implements hook_node_submit().
|
||||
*
|
||||
* @see menu_ui_form_node_form_alter()
|
||||
* @see menu_form_node_form_alter()
|
||||
*/
|
||||
function menu_ui_node_submit(EntityInterface $node, $form, $form_state) {
|
||||
function menu_node_submit(EntityInterface $node, $form, $form_state) {
|
||||
if (!empty($form_state['values']['menu'])) {
|
||||
$node->menu = entity_create('menu_link', $form_state['values']['menu']);
|
||||
// Decompose the selected menu parent option into 'menu_name' and 'plid', if
|
||||
|
@ -579,10 +579,10 @@ function menu_ui_node_submit(EntityInterface $node, $form, $form_state) {
|
|||
* Adds menu options to the node type form.
|
||||
*
|
||||
* @see NodeTypeFormController::form().
|
||||
* @see menu_ui_form_node_type_form_submit().
|
||||
* @see menu_form_node_type_form_submit().
|
||||
*/
|
||||
function menu_ui_form_node_type_form_alter(&$form, $form_state) {
|
||||
$menu_options = menu_ui_get_menus();
|
||||
function menu_form_node_type_form_alter(&$form, $form_state) {
|
||||
$menu_options = menu_get_menus();
|
||||
$type = $form_state['controller']->getEntity();
|
||||
if ($type->id()) {
|
||||
$config_values = \Drupal::config('menu.entity.node.' . $type->id())->get();
|
||||
|
@ -611,9 +611,9 @@ function menu_ui_form_node_type_form_alter(&$form, $form_state) {
|
|||
// To avoid an 'illegal option' error after saving the form we have to load
|
||||
// all available menu items.
|
||||
// Otherwise it is not possible to dynamically add options to the list.
|
||||
// @todo Convert menu_ui_parent_options() into a #process callback.
|
||||
// @todo Convert menu_parent_options() into a #process callback.
|
||||
$menu_link = entity_create('menu_link', array('mlid' => 0));
|
||||
$options = menu_ui_parent_options(menu_ui_get_menus(), $menu_link);
|
||||
$options = menu_parent_options(menu_get_menus(), $menu_link);
|
||||
$form['menu']['menu_parent'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Default parent item'),
|
||||
|
@ -623,15 +623,15 @@ function menu_ui_form_node_type_form_alter(&$form, $form_state) {
|
|||
'#attributes' => array('class' => array('menu-title-select')),
|
||||
);
|
||||
|
||||
$form['actions']['submit']['#submit'][] = 'menu_ui_form_node_type_form_submit';
|
||||
$form['actions']['submit']['#submit'][] = 'menu_form_node_type_form_submit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for forms with menu options.
|
||||
*
|
||||
* @see menu_ui_form_node_type_form_alter().
|
||||
* @see menu_form_node_type_form_alter().
|
||||
*/
|
||||
function menu_ui_form_node_type_form_submit(&$form, $form_state) {
|
||||
function menu_form_node_type_form_submit(&$form, $form_state) {
|
||||
$type = $form_state['controller']->getEntity();
|
||||
\Drupal::config('menu.entity.node.' . $type->id())
|
||||
->set('available_menus', array_values(array_filter($form_state['values']['menu_options'])))
|
||||
|
@ -649,7 +649,7 @@ function menu_ui_form_node_type_form_submit(&$form, $form_state) {
|
|||
* An array with the machine-readable names as the keys, and human-readable
|
||||
* titles as the values.
|
||||
*/
|
||||
function menu_ui_get_menus($all = TRUE) {
|
||||
function menu_get_menus($all = TRUE) {
|
||||
if ($custom_menus = entity_load_multiple('menu')) {
|
||||
if (!$all) {
|
||||
$custom_menus = array_diff_key($custom_menus, menu_list_system_menus());
|
||||
|
@ -665,8 +665,8 @@ function menu_ui_get_menus($all = TRUE) {
|
|||
/**
|
||||
* Implements hook_preprocess_HOOK() for block templates.
|
||||
*/
|
||||
function menu_ui_preprocess_block(&$variables) {
|
||||
if ($variables['configuration']['provider'] == 'menu_ui') {
|
||||
function menu_preprocess_block(&$variables) {
|
||||
if ($variables['configuration']['provider'] == 'menu') {
|
||||
$variables['attributes']['role'] = 'navigation';
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
menu_ui.settings:
|
||||
menu.settings:
|
||||
path: '/admin/structure/menu/settings'
|
||||
defaults:
|
||||
_form: 'Drupal\menu_ui\MenuSettingsForm'
|
||||
_form: 'Drupal\menu\MenuSettingsForm'
|
||||
_title: 'Menus'
|
||||
requirements:
|
||||
_permission: 'administer menu'
|
||||
|
||||
menu_ui.overview_page:
|
||||
menu.overview_page:
|
||||
path: '/admin/structure/menu'
|
||||
defaults:
|
||||
_entity_list: 'menu'
|
||||
|
@ -14,22 +14,22 @@ menu_ui.overview_page:
|
|||
requirements:
|
||||
_permission: 'administer menu'
|
||||
|
||||
menu_ui.parent_options_js:
|
||||
menu.parent_options_js:
|
||||
path: '/admin/structure/menu/parents'
|
||||
defaults:
|
||||
_controller: '\Drupal\menu_ui\Controller\MenuController::getParentOptions'
|
||||
_controller: '\Drupal\menu\Controller\MenuController::getParentOptions'
|
||||
requirements:
|
||||
_permission: 'administer menu'
|
||||
|
||||
menu_ui.link_add:
|
||||
menu.link_add:
|
||||
path: '/admin/structure/menu/manage/{menu}/add'
|
||||
defaults:
|
||||
_content: '\Drupal\menu_ui\Controller\MenuController::addLink'
|
||||
_content: '\Drupal\menu\Controller\MenuController::addLink'
|
||||
_title: 'Add menu link'
|
||||
requirements:
|
||||
_entity_create_access: 'menu_link'
|
||||
|
||||
menu_ui.link_edit:
|
||||
menu.link_edit:
|
||||
path: '/admin/structure/menu/item/{menu_link}/edit'
|
||||
defaults:
|
||||
_entity_form: 'menu_link'
|
||||
|
@ -37,7 +37,7 @@ menu_ui.link_edit:
|
|||
requirements:
|
||||
_entity_access: 'menu_link.update'
|
||||
|
||||
menu_ui.link_reset:
|
||||
menu.link_reset:
|
||||
path: '/admin/structure/menu/item/{menu_link}/reset'
|
||||
defaults:
|
||||
_entity_form: 'menu_link.reset'
|
||||
|
@ -45,7 +45,7 @@ menu_ui.link_reset:
|
|||
requirements:
|
||||
_entity_access: 'menu_link.reset'
|
||||
|
||||
menu_ui.link_delete:
|
||||
menu.link_delete:
|
||||
path: '/admin/structure/menu/item/{menu_link}/delete'
|
||||
defaults:
|
||||
_entity_form: 'menu_link.delete'
|
||||
|
@ -53,7 +53,7 @@ menu_ui.link_delete:
|
|||
requirements:
|
||||
_entity_access: 'menu_link.delete'
|
||||
|
||||
menu_ui.menu_add:
|
||||
menu.menu_add:
|
||||
path: '/admin/structure/menu/add'
|
||||
defaults:
|
||||
_entity_form: 'menu.add'
|
||||
|
@ -61,15 +61,15 @@ menu_ui.menu_add:
|
|||
requirements:
|
||||
_entity_create_access: 'menu'
|
||||
|
||||
menu_ui.menu_edit:
|
||||
menu.menu_edit:
|
||||
path: '/admin/structure/menu/manage/{menu}'
|
||||
defaults:
|
||||
_entity_form: 'menu.edit'
|
||||
_title_callback: '\Drupal\menu_ui\Controller\MenuController::menuTitle'
|
||||
_title_callback: '\Drupal\menu\Controller\MenuController::menuTitle'
|
||||
requirements:
|
||||
_entity_access: 'menu.update'
|
||||
|
||||
menu_ui.delete_menu:
|
||||
menu.delete_menu:
|
||||
path: '/admin/structure/menu/manage/{menu}/delete'
|
||||
defaults:
|
||||
_entity_form: 'menu.delete'
|
|
@ -111,7 +111,7 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
public $module = 'menu_ui';
|
||||
public $module = 'menu';
|
||||
|
||||
/**
|
||||
* A flag for whether the link should be rendered in menus.
|
||||
|
|
|
@ -31,7 +31,7 @@ class MenuLinkAccessController extends EntityAccessController {
|
|||
|
||||
case 'delete':
|
||||
// Only items created by the menu module can be deleted.
|
||||
return $entity->module == 'menu_ui' || $entity->updated == 1;
|
||||
return $entity->module == 'menu' || $entity->updated == 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class MenuLinkFormController extends EntityFormController {
|
|||
if (isset($menu_link->options['fragment'])) {
|
||||
$path .= '#' . $menu_link->options['fragment'];
|
||||
}
|
||||
if ($menu_link->module == 'menu_ui') {
|
||||
if ($menu_link->module == 'menu') {
|
||||
$form['link_path'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Path'),
|
||||
|
@ -137,7 +137,7 @@ class MenuLinkFormController extends EntityFormController {
|
|||
);
|
||||
|
||||
// Generate a list of possible parents (not including this link or descendants).
|
||||
$options = menu_ui_parent_options(menu_ui_get_menus(), $menu_link);
|
||||
$options = menu_parent_options(menu_get_menus(), $menu_link);
|
||||
$default = $menu_link->menu_name . ':' . $menu_link->plid;
|
||||
if (!isset($options[$default])) {
|
||||
$default = 'tools:0';
|
||||
|
@ -298,7 +298,7 @@ class MenuLinkFormController extends EntityFormController {
|
|||
if ($saved) {
|
||||
drupal_set_message(t('The menu link has been saved.'));
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => 'menu_ui.menu_edit',
|
||||
'route_name' => 'menu.menu_edit',
|
||||
'route_parameters' => array(
|
||||
'menu' => $menu_link->menu_name,
|
||||
),
|
||||
|
|
|
@ -15,7 +15,7 @@ function menu_link_help($path, $arg) {
|
|||
case 'admin/help#menu_link':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Menu Link module allows users to create menu links. It is required by the Menu module, which provides an interface for managing menus. See the <a href="!menu-help">Menu module help page</a> for more information.', array('!menu-help' => \Drupal::url('help.page', array('name' => 'menu_ui')))) . '</p>';
|
||||
$output .= '<p>' . t('The Menu Link module allows users to create menu links. It is required by the Menu module, which provides an interface for managing menus. See the <a href="!menu-help">Menu module help page</a> for more information.', array('!menu-help' => \Drupal::url('help.page', array('name' => 'menu')))) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
@ -203,12 +203,12 @@ function menu_link_maintain($module, $op, $link_path, $link_title = NULL) {
|
|||
function menu_link_system_breadcrumb_alter(array &$breadcrumb, array $attributes, array $context) {
|
||||
// Custom breadcrumb behavior for editing menu links, we append a link to
|
||||
// the menu in which the link is found.
|
||||
if (!empty($attributes[RouteObjectInterface::ROUTE_NAME]) && $attributes[RouteObjectInterface::ROUTE_NAME] == 'menu_ui.link_edit' && !empty($attributes['menu_link'])) {
|
||||
if (!empty($attributes[RouteObjectInterface::ROUTE_NAME]) && $attributes[RouteObjectInterface::ROUTE_NAME] == 'menu.link_edit' && !empty($attributes['menu_link'])) {
|
||||
$menu_link = $attributes['menu_link'];
|
||||
if (($menu_link instanceof MenuLinkInterface) && !$menu_link->isNew()) {
|
||||
// Add a link to the menu admin screen.
|
||||
$menu = entity_load('menu', $menu_link->menu_name);
|
||||
$breadcrumb[] = Drupal::l($menu->label(), 'menu_ui.menu_edit', array('menu' => $menu->id));
|
||||
$breadcrumb[] = Drupal::l($menu->label(), 'menu.menu_edit', array('menu' => $menu->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
menu_ui_edit:
|
||||
title: 'Edit menu'
|
||||
route_name: 'menu_ui.menu_edit'
|
||||
group: menu
|
|
@ -1,11 +0,0 @@
|
|||
menu_ui_link_add:
|
||||
route_name: menu_ui.link_add
|
||||
title: 'Add link'
|
||||
appears_on:
|
||||
- menu_ui.menu_edit
|
||||
|
||||
menu_ui.menu_add:
|
||||
route_name: menu_ui.menu_add
|
||||
title: 'Add menu'
|
||||
appears_on:
|
||||
- menu_ui.overview_page
|
|
@ -1,15 +0,0 @@
|
|||
menu_ui.menu_edit:
|
||||
title: 'Edit menu'
|
||||
route_name: menu_ui.menu_edit
|
||||
base_route: menu_ui.menu_edit
|
||||
|
||||
menu_ui.overview_page:
|
||||
title: 'List'
|
||||
route_name: menu_ui.overview_page
|
||||
base_route: menu_ui.overview_page
|
||||
|
||||
menu_ui.settings:
|
||||
title: 'Settings'
|
||||
route_name: menu_ui.settings
|
||||
base_route: menu_ui.overview_page
|
||||
weight: 100
|
|
@ -11,4 +11,4 @@ process:
|
|||
override_parent_selector: menu_override_parent_selector
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: menu_ui.settings
|
||||
config_name: menu.settings
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\migrate_drupal\Tests\Dump;
|
||||
|
||||
/**
|
||||
* Database dump for testing menu_ui.settings.yml migration.
|
||||
* Database dump for testing menu.settings.yml migration.
|
||||
*/
|
||||
class Drupal6MenuSettings extends Drupal6DumpBase {
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ class MigrateMenuConfigsTest extends MigrateDrupalTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('menu_ui');
|
||||
public static $modules = array('menu');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Migrate variables to menu_ui.settings.yml',
|
||||
'description' => 'Upgrade variables to menu_ui.settings.yml',
|
||||
'name' => 'Migrate variables to menu.settings.yml',
|
||||
'description' => 'Upgrade variables to menu.settings.yml',
|
||||
'group' => 'Migrate Drupal',
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class MigrateMenuConfigsTest extends MigrateDrupalTestBase {
|
|||
* Tests migration of variables for the menu module.
|
||||
*/
|
||||
public function testMenuSettings() {
|
||||
$config = \Drupal::config('menu_ui.settings');
|
||||
$config = \Drupal::config('menu.settings');
|
||||
$this->assertIdentical($config->get('main_links'), 'primary-links');
|
||||
$this->assertIdentical($config->get('secondary_links'), 'secondary-links');
|
||||
$this->assertIdentical($config->get('override_parent_selector'), FALSE);
|
||||
|
|
|
@ -20,9 +20,7 @@ use Drupal\Core\Database\Query\Condition;
|
|||
use Drupal\node\NodeInterface;
|
||||
use Drupal\search\Plugin\ConfigurableSearchPluginBase;
|
||||
use Drupal\search\Plugin\SearchIndexingInterface;
|
||||
use Drupal\Search\SearchQuery;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Handles searching for node entities using the Search module index.
|
||||
|
@ -159,17 +157,6 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
return !empty($account) && $account->hasPermission('access content');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isSearchExecutable() {
|
||||
// Node search is executable if we have keywords or an advanced parameter.
|
||||
// At least, we should parse out the parameters and see if there are any
|
||||
// keyword matches in that case, rather than just printing out the
|
||||
// "Please enter keywords" message.
|
||||
return !empty($this->keywords) || (isset($this->searchParameters['f']) && count($this->searchParameters['f']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -195,8 +182,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
// the URL: ?f[]=type:page&f[]=term:27&f[]=term:13&f[]=langcode:en
|
||||
// So $parameters['f'] looks like:
|
||||
// array('type:page', 'term:27', 'term:13', 'langcode:en');
|
||||
// We need to parse this out into query conditions, some of which go into
|
||||
// the keywords string, and some of which are separate conditions.
|
||||
// We need to parse this out into query conditions.
|
||||
$parameters = $this->getParameters();
|
||||
if (!empty($parameters['f']) && is_array($parameters['f'])) {
|
||||
$filters = array();
|
||||
|
@ -209,7 +195,6 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
$filters[$m[1]][$m[2]] = $m[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Now turn these into query conditions. This assumes that everything in
|
||||
// $filters is a known type of advanced search.
|
||||
foreach ($filters as $option => $matched) {
|
||||
|
@ -226,11 +211,15 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
}
|
||||
}
|
||||
}
|
||||
// Only continue if the first pass query matches.
|
||||
if (!$query->executeFirstPass()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Add the ranking expressions.
|
||||
$this->addNodeRankings($query);
|
||||
|
||||
// Run the query and load results.
|
||||
// Load results.
|
||||
$find = $query
|
||||
// Add the language code of the indexed item to the result of the query,
|
||||
// since the node will be rendered using the respective language.
|
||||
|
@ -242,21 +231,6 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
->limit(10)
|
||||
->execute();
|
||||
|
||||
// Check query status and set messages if needed.
|
||||
$status = $query->getStatus();
|
||||
|
||||
if ($status & SearchQuery::EXPRESSIONS_IGNORED) {
|
||||
drupal_set_message($this->t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => $this->searchSettings->get('and_or_limit'))), 'warning');
|
||||
}
|
||||
|
||||
if ($status & SearchQuery::LOWER_CASE_OR) {
|
||||
drupal_set_message($this->t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'), 'warning');
|
||||
}
|
||||
|
||||
if ($status & SearchQuery::NO_POSITIVE_KEYWORDS) {
|
||||
drupal_set_message(\Drupal::translation()->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.'), 'warning');
|
||||
}
|
||||
|
||||
$node_storage = $this->entityManager->getStorage('node');
|
||||
$node_render = $this->entityManager->getViewBuilder('node');
|
||||
|
||||
|
@ -396,7 +370,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function searchFormAlter(array &$form, array &$form_state) {
|
||||
// Add advanced search keyword-related boxes.
|
||||
// Add keyword boxes.
|
||||
$form['advanced'] = array(
|
||||
'#type' => 'details',
|
||||
'#title' => t('Advanced search'),
|
||||
|
@ -471,18 +445,25 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
'#options' => $language_options,
|
||||
);
|
||||
}
|
||||
|
||||
// Add a submit handler.
|
||||
$form['#submit'][] = array($this, 'searchFormSubmit');
|
||||
}
|
||||
|
||||
/*
|
||||
* {@inheritdoc}
|
||||
/**
|
||||
* Handles submission of elements added in searchFormAlter().
|
||||
*
|
||||
* @param array $form
|
||||
* Nested array of form elements that comprise the form.
|
||||
* @param array $form_state
|
||||
* A keyed array containing the current state of the form.
|
||||
*/
|
||||
public function buildSearchUrlQuery($form_state) {
|
||||
// Read keyword and advanced search information from the form values,
|
||||
// and put these into the GET parameters.
|
||||
$keys = trim($form_state['values']['keys']);
|
||||
|
||||
// Collect extra filters.
|
||||
public function searchFormSubmit(array &$form, array &$form_state) {
|
||||
// Initialize using any existing basic search keywords.
|
||||
$keys = $form_state['values']['processed_keys'];
|
||||
$filters = array();
|
||||
|
||||
// Collect extra restrictions.
|
||||
if (isset($form_state['values']['type']) && is_array($form_state['values']['type'])) {
|
||||
// Retrieve selected types - Form API sets the value of unselected
|
||||
// checkboxes to 0.
|
||||
|
@ -518,17 +499,21 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
if ($form_state['values']['phrase'] != '') {
|
||||
$keys .= ' "' . str_replace('"', ' ', $form_state['values']['phrase']) . '"';
|
||||
}
|
||||
$keys = trim($keys);
|
||||
|
||||
// Put the keywords and advanced parameters into GET parameters. Make sure
|
||||
// to put keywords into the query even if it is empty, because the page
|
||||
// controller uses that to decide it's time to check for search results.
|
||||
$query = array('keys' => $keys);
|
||||
if (!empty($keys)) {
|
||||
form_set_value($form['basic']['processed_keys'], trim($keys), $form_state);
|
||||
}
|
||||
$options = array();
|
||||
if ($filters) {
|
||||
$query['f'] = $filters;
|
||||
$options['query'] = array('f' => $filters);
|
||||
}
|
||||
|
||||
return $query;
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => 'search.view_' . $form_state['search_page_id'],
|
||||
'route_parameters' => array(
|
||||
'keys' => $keys,
|
||||
),
|
||||
'options' => $options,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,42 +51,42 @@ class SearchController extends ControllerBase {
|
|||
* The request object.
|
||||
* @param \Drupal\search\SearchPageInterface $entity
|
||||
* The search page entity.
|
||||
* @param string $keys
|
||||
* (optional) Search keywords, defaults to an empty string.
|
||||
*
|
||||
* @return array
|
||||
* The search form and search results build array.
|
||||
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* The search form and search results or redirect response.
|
||||
*/
|
||||
public function view(Request $request, SearchPageInterface $entity) {
|
||||
$build = array();
|
||||
$plugin = $entity->getPlugin();
|
||||
|
||||
// Build the form first, because it may redirect during the submit,
|
||||
// and we don't want to build the results based on last time's request.
|
||||
if ($request->query->has('keys')) {
|
||||
$keys = trim($request->get('keys'));
|
||||
$plugin->setSearch($keys, $request->query->all(), $request->attributes->all());
|
||||
public function view(Request $request, SearchPageInterface $entity, $keys = '') {
|
||||
// Also try to pull search keywords from the request to support old GET
|
||||
// format of searches for existing links.
|
||||
if (!$keys && $request->query->has('keys')) {
|
||||
$keys = $request->query->get('keys');
|
||||
}
|
||||
$keys = trim($keys);
|
||||
$build['#title'] = $this->t('Search');
|
||||
|
||||
$build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search');
|
||||
|
||||
// Build search results, if keywords or other search parameters are in the
|
||||
// GET parameters. Note that we need to try the search if 'keys' is in
|
||||
// there at all, vs. being empty, due to advanced search.
|
||||
$plugin = $entity->getPlugin();
|
||||
$plugin->setSearch($keys, $request->query->all(), $request->attributes->all());
|
||||
$results = array();
|
||||
if ($request->query->has('keys')) {
|
||||
|
||||
// Process the search form. Note that if there is
|
||||
// \Drupal::request()->request data, search_form_submit() will cause a
|
||||
// redirect to search/[path]/[keys], which will get us back to this page
|
||||
// callback. In other words, the search form submits with POST but redirects
|
||||
// to GET. This way we can keep the search query URL clean as a whistle.
|
||||
if ($request->request->has('form_id') || $request->request->get('form_id') != 'search_form') {
|
||||
// Only search if there are keywords or non-empty conditions.
|
||||
if ($plugin->isSearchExecutable()) {
|
||||
// Log the search.
|
||||
watchdog('search', 'Searched %type for %keys.', array('%keys' => $keys, '%type' => $entity->label()), WATCHDOG_NOTICE);
|
||||
// Log the search keys.
|
||||
watchdog('search', 'Searched %type for %keys.', array('%keys' => $keys, '%type' => $entity->label()), WATCHDOG_NOTICE, $this->l(t('results'), 'search.view_' . $entity->id(), array('keys' => $keys)));
|
||||
|
||||
// Collect the search results.
|
||||
$results = $plugin->buildResults();
|
||||
}
|
||||
else {
|
||||
// The search not being executable means that no keywords or other
|
||||
// conditions were entered.
|
||||
drupal_set_message($this->t('Please enter some keywords.'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// The form may be altered based on whether the search was run.
|
||||
$build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search');
|
||||
if (count($results)) {
|
||||
$build['search_results_title'] = array(
|
||||
'#markup' => '<h2>' . $this->t('Search results') . '</h2>',
|
||||
|
|
|
@ -10,8 +10,6 @@ namespace Drupal\search\Form;
|
|||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\search\SearchPageRepositoryInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Builds the search form for the search block.
|
||||
|
@ -55,21 +53,7 @@ class SearchBlockForm extends FormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, array &$form_state) {
|
||||
// Set up the form to submit using GET to the correct search page.
|
||||
$entity_id = $this->searchPageRepository->getDefaultSearchPage();
|
||||
if (!$entity_id) {
|
||||
$form['message'] = array(
|
||||
'#markup' => $this->t('Search is currently disabled'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
$route = 'search.view_' . $entity_id;
|
||||
$form['#action'] = $this->url($route);
|
||||
$form['#token'] = FALSE;
|
||||
$form['#method'] = 'get';
|
||||
|
||||
$form['keys'] = array(
|
||||
$form['search_block_form'] = array(
|
||||
'#type' => 'search',
|
||||
'#title' => $this->t('Search'),
|
||||
'#title_display' => 'invisible',
|
||||
|
@ -77,14 +61,8 @@ class SearchBlockForm extends FormBase {
|
|||
'#default_value' => '',
|
||||
'#attributes' => array('title' => $this->t('Enter the terms you wish to search for.')),
|
||||
);
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Search'),
|
||||
// Prevent op from showing up in the query string.
|
||||
'#name' => '',
|
||||
);
|
||||
$form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Search'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
@ -93,7 +71,36 @@ class SearchBlockForm extends FormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, array &$form_state) {
|
||||
// This form submits to the search page, so processing happens there.
|
||||
// The search form relies on control of the redirect destination for its
|
||||
// functionality, so we override any static destination set in the request.
|
||||
// See http://drupal.org/node/292565.
|
||||
$request = $this->getRequest();
|
||||
if ($request->query->has('destination')) {
|
||||
$request->query->remove('destination');
|
||||
}
|
||||
|
||||
// Check to see if the form was submitted empty.
|
||||
// If it is empty, display an error message.
|
||||
// (This method is used instead of setting #required to TRUE for this field
|
||||
// because that results in a confusing error message. It would say a plain
|
||||
// "field is required" because the search keywords field has no title.
|
||||
// The error message would also complain about a missing #title field.)
|
||||
if ($form_state['values']['search_block_form'] == '') {
|
||||
$this->setFormError('keys', $form_state, $this->t('Please enter some keywords.'));
|
||||
}
|
||||
|
||||
$form_id = $form['form_id']['#value'];
|
||||
if ($entity_id = $this->searchPageRepository->getDefaultSearchPage()) {
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => 'search.view_' . $entity_id,
|
||||
'route_parameters' => array(
|
||||
'keys' => trim($form_state['values'][$form_id]),
|
||||
),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$this->setFormError('', $form_state, $this->t('Search is currently disabled.'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,17 +8,9 @@
|
|||
namespace Drupal\search\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityFormController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Provides a search form for site wide search.
|
||||
*
|
||||
* Search plugins can define method searchFormAlter() to alter the form. If they
|
||||
* have additional or substitute fields, they will need to override the form
|
||||
* submit, making sure to redirect with a GET parameter of 'keys' included, to
|
||||
* trigger the search being processed by the controller, and adding in any
|
||||
* additional query parameters they need to execute search.
|
||||
*/
|
||||
class SearchPageForm extends EntityFormController {
|
||||
|
||||
|
@ -41,8 +33,8 @@ class SearchPageForm extends EntityFormController {
|
|||
*/
|
||||
public function form(array $form, array &$form_state) {
|
||||
$plugin = $this->entity->getPlugin();
|
||||
$form_state['search_page_id'] = $this->entity->id();
|
||||
|
||||
$form_state['search_page_id'] = $this->entity->id();
|
||||
$form['basic'] = array(
|
||||
'#type' => 'container',
|
||||
'#attributes' => array(
|
||||
|
@ -66,7 +58,6 @@ class SearchPageForm extends EntityFormController {
|
|||
'#type' => 'submit',
|
||||
'#value' => $this->t('Search'),
|
||||
);
|
||||
|
||||
// Allow the plugin to add to or alter the search form.
|
||||
$plugin->searchFormAlter($form, $form_state);
|
||||
|
||||
|
@ -81,20 +72,29 @@ class SearchPageForm extends EntityFormController {
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, array &$form_state) {
|
||||
form_set_value($form['basic']['processed_keys'], trim($form_state['values']['keys']), $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, array &$form_state) {
|
||||
// Redirect to the search page with keywords in the GET parameters.
|
||||
// Plugins with additional search parameters will need to provide their
|
||||
// own form submit handler to replace this, so they can put their values
|
||||
// into the GET as well. If so, make sure to put 'keys' into the GET
|
||||
// parameters so that the search results generation is triggered.
|
||||
$query = $this->entity->getPlugin()->buildSearchUrlQuery($form_state);
|
||||
$route = 'search.view_' . $form_state['search_page_id'];
|
||||
$keys = $form_state['values']['processed_keys'];
|
||||
if ($keys == '') {
|
||||
$this->setFormError('keys', $form_state, $this->t('Please enter some keywords.'));
|
||||
// Fall through to the form redirect.
|
||||
}
|
||||
|
||||
$form_state['redirect_route'] = array(
|
||||
'route_name' => $route,
|
||||
'options' => array('query' => $query),
|
||||
'route_name' => 'search.view_' . $this->entity->id(),
|
||||
'route_parameters' => array(
|
||||
'keys' => $keys,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ interface SearchInterface extends PluginInspectionInterface {
|
|||
* @param string $keywords
|
||||
* The keywords to use in a search.
|
||||
* @param array $parameters
|
||||
* Array of parameters as an associative array. This is expected to
|
||||
* Array of parameters as am associative array. This is expected to
|
||||
* be the query string from the current request.
|
||||
* @param array $attributes
|
||||
* Array of attributes, usually from the current request object.
|
||||
|
@ -85,9 +85,9 @@ interface SearchInterface extends PluginInspectionInterface {
|
|||
* Alters the search form when being built for a given plugin.
|
||||
*
|
||||
* The core search module only invokes this method on active module plugins
|
||||
* when building a form for them in
|
||||
* \Drupal\search\Form\SearchPageForm::form(). A plugin implementing this
|
||||
* will also need to implement the buildSearchUrlQuery() method.
|
||||
* when building a form for them in search_form(). A plugin implementing
|
||||
* this needs to add validate and submit callbacks to the form if it needs
|
||||
* to act after form submission.
|
||||
*
|
||||
* @param array $form
|
||||
* Nested array of form elements that comprise the form.
|
||||
|
@ -95,30 +95,7 @@ interface SearchInterface extends PluginInspectionInterface {
|
|||
* A keyed array containing the current state of the form. The arguments
|
||||
* that \Drupal::formBuilder()->getForm() was originally called with are
|
||||
* available in the array $form_state['build_info']['args'].
|
||||
*
|
||||
* @see SearchInterface::buildSearchUrlQuery()
|
||||
*/
|
||||
public function searchFormAlter(array &$form, array &$form_state);
|
||||
|
||||
/**
|
||||
* Builds the URL GET query parameters array for search.
|
||||
*
|
||||
* When the search form is submitted, a redirect is generated with the
|
||||
* search input as GET query parameters. Plugins using the searchFormAlter()
|
||||
* method to add form elements to the search form will need to override this
|
||||
* method to gather the form input and add it to the GET query parameters.
|
||||
*
|
||||
* @param array $form_state
|
||||
* The form state, with submitted form information.
|
||||
*
|
||||
* @return array
|
||||
* An array of GET query parameters containing all relevant form values
|
||||
* to process the search. The 'keys' element must be present in order to
|
||||
* trigger generation of search results, even if it is empty or unused by
|
||||
* the search plugin.
|
||||
*
|
||||
* @see SearchInterface::searchFormAlter()
|
||||
*/
|
||||
public function buildSearchUrlQuery($form_state);
|
||||
|
||||
}
|
||||
|
|
|
@ -101,21 +101,11 @@ abstract class SearchPluginBase extends PluginBase implements ContainerFactoryPl
|
|||
return $built;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function searchFormAlter(array &$form, array &$form_state) {
|
||||
// Empty default implementation.
|
||||
}
|
||||
|
||||
/*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildSearchUrlQuery($form_state) {
|
||||
// Grab the keywords entered in the form and put them as 'keys' in the GET.
|
||||
$keys = trim($form_state['values']['keys']);
|
||||
$query = array('keys' => $keys);
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,13 +77,15 @@ class SearchPageRoutes implements ContainerInjectionInterface {
|
|||
$active_pages = $this->searchPageRepository->getActiveSearchPages();
|
||||
foreach ($active_pages as $entity_id => $entity) {
|
||||
$routes["search.view_$entity_id"] = new Route(
|
||||
'/search/' . $entity->getPath(),
|
||||
'/search/' . $entity->getPath() . '/{keys}',
|
||||
array(
|
||||
'_content' => 'Drupal\search\Controller\SearchController::view',
|
||||
'_title' => 'Search',
|
||||
'_title' => $entity->label(),
|
||||
'entity' => $entity_id,
|
||||
'keys' => '',
|
||||
),
|
||||
array(
|
||||
'keys' => '.+',
|
||||
'_entity_access' => 'entity.view',
|
||||
'_permission' => 'search content',
|
||||
),
|
||||
|
|
|
@ -15,71 +15,25 @@ use Drupal\Core\Database\StatementEmpty;
|
|||
/**
|
||||
* Performs a query on the full-text search index for a word or words.
|
||||
*
|
||||
* This query is used by search plugins that use the search index (not all
|
||||
* search plugins do, as some use a different searching mechanism). It
|
||||
* assumes you have set up a query on the {search_index} table with alias 'i',
|
||||
* and will only work if the user is searching for at least one "positive"
|
||||
* keyword or phrase.
|
||||
* This function is normally only called by each plugin that supports the
|
||||
* indexed search.
|
||||
*
|
||||
* For efficiency, users of this query can run the prepareAndNormalize()
|
||||
* method to figure out if there are any search results, before fully setting
|
||||
* up and calling execute() to execute the query. The scoring expressions are
|
||||
* not needed until the execute() step. However, it's not really necessary
|
||||
* to do this, because this class's execute() method does that anyway.
|
||||
* Results are retrieved in two logical passes. However, the two passes are
|
||||
* joined together into a single query, and in the case of most simple queries
|
||||
* the second pass is not even used.
|
||||
*
|
||||
* During both the prepareAndNormalize() and execute() steps, there can be
|
||||
* problems. Call getStatus() to figure out if the query is OK or not.
|
||||
* The first pass selects a set of all possible matches, which has the benefit
|
||||
* of also providing the exact result set for simple "AND" or "OR" searches.
|
||||
*
|
||||
* The query object is given the tag 'search_$type' and can be further
|
||||
* The second portion of the query further refines this set by verifying
|
||||
* advanced text conditions (such as negative or phrase matches).
|
||||
*
|
||||
* The used query object has the tag 'search_$type' and can be further
|
||||
* extended with hook_query_alter().
|
||||
*/
|
||||
class SearchQuery extends SelectExtender {
|
||||
|
||||
/**
|
||||
* Indicates no positive keywords were in the search expression.
|
||||
*
|
||||
* Positive keywords are words that are searched for, as opposed to negative
|
||||
* keywords, which are words that are excluded. To count as a keyword, a
|
||||
* word must be at least
|
||||
* \Drupal::config('search.settings')->get('index.minimum_word_size')
|
||||
* characters.
|
||||
*
|
||||
* @see SearchQuery::getStatus()
|
||||
*/
|
||||
const NO_POSITIVE_KEYWORDS = 1;
|
||||
|
||||
/**
|
||||
* Indicates that part of the search expression was ignored.
|
||||
*
|
||||
* To prevent Denial of Service attacks, only
|
||||
* \Drupal::config('search.settings')->get('and_or_limit') expressions
|
||||
* (positive keywords, phrases, negative keywords) are allowed; this flag
|
||||
* indicates that expressions existed past that limit and they were removed.
|
||||
*
|
||||
* @see SearchQuery::getStatus()
|
||||
*/
|
||||
const EXPRESSIONS_IGNORED = 2;
|
||||
|
||||
/**
|
||||
* Indicates that lower-case "or" was in the search expression.
|
||||
*
|
||||
* The word "or" in lower case was found in the search expression. This
|
||||
* probably means someone was trying to do an OR search but used lower-case
|
||||
* instead of upper-case.
|
||||
*
|
||||
* @see SearchQuery::getStatus()
|
||||
*/
|
||||
const LOWER_CASE_OR = 4;
|
||||
|
||||
/**
|
||||
* Indicates that no positive keyword matches were found.
|
||||
*
|
||||
* @see SearchQuery::getStatus()
|
||||
*/
|
||||
const NO_KEYWORD_MATCHES = 8;
|
||||
|
||||
/**
|
||||
* The keywords and advanced search options that are entered by the user.
|
||||
* The search query that is used for searching.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -88,22 +42,23 @@ class SearchQuery extends SelectExtender {
|
|||
/**
|
||||
* The type of search (search type).
|
||||
*
|
||||
* This maps to the value of the type column in search_index, and is usually
|
||||
* equal to the machine-readable name of the plugin or the search page.
|
||||
* This maps to the value of the type column in search_index, and is equal
|
||||
* to the machine-readable name of the entity type being indexed, or other
|
||||
* identifier provided by a search plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Parsed-out positive and negative search keys.
|
||||
* Positive and negative search keys.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $keys = array('positive' => array(), 'negative' => array());
|
||||
|
||||
/**
|
||||
* Indicates whether the query conditions are simple or complex (LIKE).
|
||||
* Indicates whether the first pass query requires complex conditions (LIKE).
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
|
@ -112,8 +67,8 @@ class SearchQuery extends SelectExtender {
|
|||
/**
|
||||
* Conditions that are used for exact searches.
|
||||
*
|
||||
* This is always used for the second step in the query, but is not part of
|
||||
* the preparation step unless $this->simple is FALSE.
|
||||
* This is always used for the second pass query but not for the first pass,
|
||||
* unless $this->simple is FALSE.
|
||||
*
|
||||
* @var DatabaseCondition
|
||||
*/
|
||||
|
@ -127,7 +82,7 @@ class SearchQuery extends SelectExtender {
|
|||
protected $matches = 0;
|
||||
|
||||
/**
|
||||
* Array of positive search words.
|
||||
* Array of search words.
|
||||
*
|
||||
* These words have to match against {search_index}.word.
|
||||
*
|
||||
|
@ -136,47 +91,46 @@ class SearchQuery extends SelectExtender {
|
|||
protected $words = array();
|
||||
|
||||
/**
|
||||
* Multiplier to normalize the keyword score.
|
||||
* Multiplier for the normalized search score.
|
||||
*
|
||||
* This value is calculated by the preparation step, and is used as a
|
||||
* multiplier of the word scores to make sure they are between 0 and 1.
|
||||
* This value is calculated by the first pass query and multiplied with the
|
||||
* actual score of a specific word to make sure that the resulting calculated
|
||||
* score is between 0 and 1.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
protected $normalize = 0;
|
||||
protected $normalize;
|
||||
|
||||
/**
|
||||
* Indicates whether the preparation step has been executed.
|
||||
* Indicates whether the first pass query has been executed.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $executedPrepare = FALSE;
|
||||
protected $executedFirstPass = FALSE;
|
||||
|
||||
/**
|
||||
* A bitmap of status conditions, described in getStatus().
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @see SearchQuery::getStatus()
|
||||
*/
|
||||
protected $status = 0;
|
||||
|
||||
/**
|
||||
* The word score expressions.
|
||||
* Stores score expressions.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see SearchQuery::addScore()
|
||||
* @see addScore()
|
||||
*/
|
||||
protected $scores = array();
|
||||
|
||||
/**
|
||||
* Arguments for the score expressions.
|
||||
* Stores arguments for score expressions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $scoresArguments = array();
|
||||
|
||||
/**
|
||||
* Stores multipliers for score expressions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $multiply = array();
|
||||
|
||||
/**
|
||||
* The number of 'i.relevance' occurrences in score expressions.
|
||||
*
|
||||
|
@ -185,48 +139,40 @@ class SearchQuery extends SelectExtender {
|
|||
protected $relevance_count = 0;
|
||||
|
||||
/**
|
||||
* Multipliers for score expressions.
|
||||
* Whether or not search expressions were ignored.
|
||||
*
|
||||
* @var array
|
||||
* The maximum number of AND/OR combinations exceeded can be configured to
|
||||
* avoid Denial-of-Service attacks. Expressions beyond the limit are ignored.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $multiply = array();
|
||||
protected $expressionsIgnored = FALSE;
|
||||
|
||||
/**
|
||||
* Sets the search query expression.
|
||||
* Sets up the search query expression.
|
||||
*
|
||||
* @param $expression
|
||||
* A search string, which can contain keywords and options.
|
||||
* @param $query
|
||||
* A search query string, which can contain options.
|
||||
* @param $type
|
||||
* The search type. This maps to {search_index}.type in the database.
|
||||
*
|
||||
* @return $this
|
||||
* @return
|
||||
* The SearchQuery object.
|
||||
*/
|
||||
public function searchExpression($expression, $type) {
|
||||
$this->searchExpression = $expression;
|
||||
$this->type = $type;
|
||||
|
||||
// Add query tag.
|
||||
$this->addTag('search_' . $type);
|
||||
|
||||
// Initialize conditions and status.
|
||||
$this->conditions = db_and();
|
||||
$this->status = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the search query into SQL conditions.
|
||||
*
|
||||
* Sets up the following variables:
|
||||
* - $this->keys
|
||||
* - $this->words
|
||||
* - $this->conditions
|
||||
* - $this->simple
|
||||
* - $this->matches
|
||||
* We build two queries that match the dataset bodies.
|
||||
*/
|
||||
protected function parseSearchExpression() {
|
||||
// Matches words optionally prefixed by a - sign. A word in this case is
|
||||
// Matchs words optionally prefixed by a dash. A word in this case is
|
||||
// something between two spaces, optionally quoted.
|
||||
preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->searchExpression , $keywords, PREG_SET_ORDER);
|
||||
|
||||
|
@ -236,6 +182,7 @@ class SearchQuery extends SelectExtender {
|
|||
|
||||
// Classify tokens.
|
||||
$or = FALSE;
|
||||
$warning = '';
|
||||
$limit_combinations = \Drupal::config('search.settings')->get('and_or_limit');
|
||||
// The first search expression does not count as AND.
|
||||
$and_count = -1;
|
||||
|
@ -244,10 +191,9 @@ class SearchQuery extends SelectExtender {
|
|||
if ($or_count && $and_count + $or_count >= $limit_combinations) {
|
||||
// Ignore all further search expressions to prevent Denial-of-Service
|
||||
// attacks using a high number of AND/OR combinations.
|
||||
$this->status |= SearchQuery::EXPRESSIONS_IGNORED;
|
||||
$this->expressionsIgnored = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
$phrase = FALSE;
|
||||
// Strip off phrase quotes.
|
||||
if ($match[2]{0} == '"') {
|
||||
|
@ -281,14 +227,14 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
// AND operator: implied, so just ignore it.
|
||||
elseif ($match[2] == 'AND' || $match[2] == 'and') {
|
||||
$warning = $match[2];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Plain keyword.
|
||||
else {
|
||||
if ($match[2] == 'or') {
|
||||
// Lower-case "or" instead of "OR" is a warning condition.
|
||||
$this->status |= SearchQuery::LOWER_CASE_OR;
|
||||
$warning = $match[2];
|
||||
}
|
||||
if ($or) {
|
||||
// Add to last element (which is an array).
|
||||
|
@ -303,6 +249,7 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
|
||||
// Convert keywords into SQL statements.
|
||||
$this->conditions = db_and();
|
||||
$simple_and = FALSE;
|
||||
$simple_or = FALSE;
|
||||
// Positive matches.
|
||||
|
@ -343,19 +290,18 @@ class SearchQuery extends SelectExtender {
|
|||
$this->conditions->condition('d.data', "% $key %", 'NOT LIKE');
|
||||
$this->simple = FALSE;
|
||||
}
|
||||
|
||||
if ($warning == 'or') {
|
||||
drupal_set_message(t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a word or phrase for parseQuery().
|
||||
*
|
||||
* Splits a phrase into words. Adds its words to $this->words, if it is not
|
||||
* already there. Returns a list containing the number of new words found,
|
||||
* and the total number of words in the phrase.
|
||||
* Helper function for parseQuery().
|
||||
*/
|
||||
protected function parseWord($word) {
|
||||
$num_new_scores = 0;
|
||||
$num_valid_words = 0;
|
||||
|
||||
// Determine the scorewords of this word/phrase.
|
||||
$split = explode(' ', $word);
|
||||
foreach ($split as $s) {
|
||||
|
@ -368,43 +314,40 @@ class SearchQuery extends SelectExtender {
|
|||
$num_valid_words++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return matching snippet and number of added words.
|
||||
return array($num_new_scores, $num_valid_words);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the query and calculates the normalization factor.
|
||||
* Executes the first pass query.
|
||||
*
|
||||
* After the query is normalized the keywords are weighted to give the results
|
||||
* a relevancy score. The query is ready for execution after this.
|
||||
* This can either be done explicitly, so that additional scores and
|
||||
* conditions can be applied to the second pass query, or implicitly by
|
||||
* addScore() or execute().
|
||||
*
|
||||
* Error and warning conditions can apply. Call getStatus() after calling
|
||||
* this method to retrieve them.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if at least one keyword matched the search index; FALSE if not.
|
||||
* @return
|
||||
* TRUE if search items exist, FALSE if not.
|
||||
*/
|
||||
public function prepareAndNormalize() {
|
||||
public function executeFirstPass() {
|
||||
$this->parseSearchExpression();
|
||||
$this->executedPrepare = TRUE;
|
||||
|
||||
if (count($this->words) == 0) {
|
||||
// Although the query could proceed, there is no point in joining
|
||||
// with other tables and attempting to normalize if there are no
|
||||
// keywords present.
|
||||
$this->status |= SearchQuery::NO_POSITIVE_KEYWORDS;
|
||||
form_set_error('keys', $form_state, format_plural(\Drupal::config('search.settings')->get('index.minimum_word_size'), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.'));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Build the basic search query: match the entered keywords.
|
||||
$or = db_or();
|
||||
foreach ($this->words as $word) {
|
||||
$or->condition('i.word', $word);
|
||||
if ($this->expressionsIgnored) {
|
||||
drupal_set_message(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => \Drupal::config('search.settings')->get('and_or_limit'))), 'warning');
|
||||
}
|
||||
$this->condition($or);
|
||||
$this->executedFirstPass = TRUE;
|
||||
|
||||
// Add keyword normalization information to the query.
|
||||
if (!empty($this->words)) {
|
||||
$or = db_or();
|
||||
foreach ($this->words as $word) {
|
||||
$or->condition('i.word', $word);
|
||||
}
|
||||
$this->condition($or);
|
||||
}
|
||||
// Build query for keyword normalization.
|
||||
$this->join('search_total', 't', 'i.word = t.word');
|
||||
$this
|
||||
->condition('i.type', $this->type)
|
||||
|
@ -412,38 +355,26 @@ class SearchQuery extends SelectExtender {
|
|||
->groupBy('i.sid')
|
||||
->having('COUNT(*) >= :matches', array(':matches' => $this->matches));
|
||||
|
||||
// Clone the query object to calculate normalization.
|
||||
$normalize_query = clone $this->query;
|
||||
// Clone the query object to do the firstPass query;
|
||||
$first = clone $this->query;
|
||||
|
||||
// For complex search queries, add the LIKE conditions; if the query is
|
||||
// simple, we do not need them for normalization.
|
||||
// For complex search queries, add the LIKE conditions to the first pass query.
|
||||
if (!$this->simple) {
|
||||
$normalize_query->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type AND i.langcode = d.langcode');
|
||||
if (count($this->conditions)) {
|
||||
$normalize_query->condition($this->conditions);
|
||||
}
|
||||
$first->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type');
|
||||
$first->condition($this->conditions);
|
||||
}
|
||||
|
||||
// Calculate normalization, which is the max of all the search scores for
|
||||
// positive keywords in the query. And note that the query could have other
|
||||
// fields added to it by the user of this extension.
|
||||
$normalize_query->addExpression('SUM(i.score * t.count)', 'calculated_score');
|
||||
$result = $normalize_query
|
||||
// Calculate maximum keyword relevance, to normalize it.
|
||||
$first->addExpression('SUM(i.score * t.count)', 'calculated_score');
|
||||
$this->normalize = $first
|
||||
->range(0, 1)
|
||||
->orderBy('calculated_score', 'DESC')
|
||||
->execute()
|
||||
->fetchObject();
|
||||
if (isset($result->calculated_score)) {
|
||||
$this->normalize = (float) $result->calculated_score;
|
||||
}
|
||||
->fetchField();
|
||||
|
||||
if ($this->normalize) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// If the normalization value was zero, that indicates there were no
|
||||
// matches to the supplied positive keywords.
|
||||
$this->status |= SearchQuery::NO_KEYWORD_MATCHES;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -506,35 +437,29 @@ class SearchQuery extends SelectExtender {
|
|||
/**
|
||||
* Executes the search.
|
||||
*
|
||||
* If not already done, this calls prepareAndNormalize() first. Then the
|
||||
* complex conditions are applied to the query including score expressions
|
||||
* and ordering.
|
||||
*
|
||||
* Error and warning conditions can apply. Call getStatus() after calling
|
||||
* this method to retrieve them.
|
||||
* If not already done, this executes the first pass query. Then the complex
|
||||
* conditions are applied to the query including score expressions and
|
||||
* ordering.
|
||||
*
|
||||
* @return
|
||||
* A query result set containing the results of the query.
|
||||
* FALSE if the first pass query returned no results, and a database result
|
||||
* set if there were results.
|
||||
*/
|
||||
public function execute() {
|
||||
|
||||
if (!$this->executedPrepare) {
|
||||
$this->prepareAndNormalize();
|
||||
public function execute()
|
||||
{
|
||||
if (!$this->executedFirstPass) {
|
||||
$this->executeFirstPass();
|
||||
}
|
||||
|
||||
if (!$this->normalize) {
|
||||
// There were no keyword matches, so return an empty result set.
|
||||
return new StatementEmpty();
|
||||
}
|
||||
|
||||
// Add conditions to the query.
|
||||
$this->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type AND i.langcode = d.langcode');
|
||||
if (count($this->conditions)) {
|
||||
$this->condition($this->conditions);
|
||||
}
|
||||
// Add conditions to query.
|
||||
$this->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type');
|
||||
$this->condition($this->conditions);
|
||||
|
||||
// Add default score (keyword relevance) if there are not any defined.
|
||||
if (empty($this->scores)) {
|
||||
// Add default score.
|
||||
$this->addScore('i.relevance');
|
||||
}
|
||||
|
||||
|
@ -548,7 +473,6 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Add arguments for the keyword relevance normalization number.
|
||||
$normalization = 1.0 / $this->normalize;
|
||||
for ($i = 0; $i < $this->relevance_count; $i++ ) {
|
||||
|
@ -564,8 +488,9 @@ class SearchQuery extends SelectExtender {
|
|||
$this->orderBy('calculated_score', 'DESC');
|
||||
}
|
||||
|
||||
// Add query metadata.
|
||||
// Add tag and useful metadata.
|
||||
$this
|
||||
->addTag('search_' . $this->type)
|
||||
->addMetaData('normalize', $this->normalize)
|
||||
->fields('i', array('type', 'sid'));
|
||||
return $this->query->execute();
|
||||
|
@ -579,18 +504,12 @@ class SearchQuery extends SelectExtender {
|
|||
* first.
|
||||
*/
|
||||
public function countQuery() {
|
||||
if (!$this->executedPrepare) {
|
||||
$this->prepareAndNormalize();
|
||||
}
|
||||
|
||||
// Clone the inner query.
|
||||
$inner = clone $this->query;
|
||||
|
||||
// Add conditions to query.
|
||||
$inner->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type');
|
||||
if (count($this->conditions)) {
|
||||
$inner->condition($this->conditions);
|
||||
}
|
||||
$inner->condition($this->conditions);
|
||||
|
||||
// Remove existing fields and expressions, they are not needed for a count
|
||||
// query.
|
||||
|
@ -599,7 +518,7 @@ class SearchQuery extends SelectExtender {
|
|||
$expressions =& $inner->getExpressions();
|
||||
$expressions = array();
|
||||
|
||||
// Add sid as the only field and count them as a subquery.
|
||||
// Add the sid as the only field and count them as a subquery.
|
||||
$count = db_select($inner->fields('i', array('sid')), NULL, array('target' => 'slave'));
|
||||
|
||||
// Add the COUNT() expression.
|
||||
|
@ -607,20 +526,4 @@ class SearchQuery extends SelectExtender {
|
|||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query status bitmap.
|
||||
*
|
||||
* @return int
|
||||
* A bitmap indicating query status. Zero indicates there were no problems.
|
||||
* A non-zero value is a combination of one or more of the following flags:
|
||||
* - SearchQuery::NO_POSITIVE_KEYWORDS
|
||||
* - SearchQuery::EXPRESSIONS_IGNORED
|
||||
* - SearchQuery::LOWER_CASE_OR
|
||||
* - SearchQuery::NO_KEYWORD_MATCHES
|
||||
*/
|
||||
public function getStatus() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,11 +51,11 @@ class SearchAdvancedSearchFormTest extends SearchTestBase {
|
|||
$this->assertNotEqual($dummy_title, $this->node->label(), "Dummy title doesn't equal node title.");
|
||||
|
||||
// Search for the dummy title with a GET query.
|
||||
$this->drupalGet('search/node', array('query' => array('keys' => $dummy_title)));
|
||||
$this->drupalGet('search/node/' . $dummy_title);
|
||||
$this->assertNoText($this->node->label(), 'Basic page node is not found with dummy title.');
|
||||
|
||||
// Search for the title of the node with a GET query.
|
||||
$this->drupalGet('search/node', array('query' => array('keys' => $this->node->label())));
|
||||
$this->drupalGet('search/node/' . $this->node->label());
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with GET query.');
|
||||
|
||||
// Search for the title of the node with a POST query.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\search\Tests\SearchBlockTest.
|
||||
* Definition of Drupal\search\Tests\SearchBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
@ -51,15 +51,15 @@ class SearchBlockTest extends SearchTestBase {
|
|||
$this->assertText($block->label(), 'Block title was found.');
|
||||
|
||||
// Test a normal search via the block form, from the front page.
|
||||
$terms = array('keys' => 'test');
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$terms = array('search_block_form' => 'test');
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Test a search from the block on a 404 page.
|
||||
$this->drupalGet('foo');
|
||||
$this->assertResponse(404);
|
||||
$this->submitGetForm(NULL, $terms, t('Search'));
|
||||
$this->drupalPostForm(NULL, $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
|
@ -67,23 +67,20 @@ class SearchBlockTest extends SearchTestBase {
|
|||
$visibility['path']['pages'] = 'search';
|
||||
$block->set('visibility', $visibility);
|
||||
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Confirm that the form submits to the default search page.
|
||||
/** @var $search_page_repository \Drupal\search\SearchPageRepositoryInterface */
|
||||
$search_page_repository = \Drupal::service('search.search_page_repository');
|
||||
$entity_id = $search_page_repository->getDefaultSearchPage();
|
||||
// Confirm that the user is redirected to the search page.
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, array(), array('query' => array('keys' => $terms['keys']), 'absolute' => TRUE)),
|
||||
'Submitted to correct url.'
|
||||
url('search/node/' . $terms['search_block_form'], array('absolute' => TRUE)),
|
||||
'Redirected to correct url.'
|
||||
);
|
||||
|
||||
// Test an empty search via the block form, from the front page.
|
||||
$terms = array('keys' => '');
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$terms = array('search_block_form' => '');
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Please enter some keywords');
|
||||
|
||||
|
@ -91,24 +88,9 @@ class SearchBlockTest extends SearchTestBase {
|
|||
// submitted empty.
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, array(), array('query' => array('keys' => ''), 'absolute' => TRUE)),
|
||||
url('search/node/', array('absolute' => TRUE)),
|
||||
'Redirected to correct url.'
|
||||
);
|
||||
|
||||
// Test that after entering a too-short keyword in the form, you can then
|
||||
// search again with a longer keyword. First test using the block form.
|
||||
$this->submitGetForm('node', array('keys' => $this->randomName(1)), t('Search'));
|
||||
$this->assertText('You must include at least one positive keyword', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->submitGetForm(NULL, array('keys' => $this->randomName()), t('Search'), 'search-block-form');
|
||||
$this->assertNoText('You must include at least one positive keyword', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Same test again, using the search page form for the second search this
|
||||
// time.
|
||||
$this->submitGetForm('node', array('keys' => $this->randomName(1)), t('Search'));
|
||||
$this->drupalPostForm(NULL, array('keys' => $this->randomName()), t('Search'), array(), array(), 'search-form');
|
||||
$this->assertNoText('You must include at least one positive keyword', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,11 +82,11 @@ class SearchCommentCountToggleTest extends SearchTestBase {
|
|||
function testSearchCommentCountToggle() {
|
||||
// Search for the nodes by string in the node body.
|
||||
$edit = array(
|
||||
'keys' => "'SearchCommentToggleTestCase'",
|
||||
'search_block_form' => "'SearchCommentToggleTestCase'",
|
||||
);
|
||||
|
||||
// Test comment count display for nodes with comment status set to Open
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$this->assertText(t('0 comments'), 'Empty comment count displays for nodes with comment status set to Open');
|
||||
$this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Open');
|
||||
|
||||
|
@ -96,7 +96,7 @@ class SearchCommentCountToggleTest extends SearchTestBase {
|
|||
$this->searchable_nodes['1 comment']->set('comment', CommentItemInterface::CLOSED);
|
||||
$this->searchable_nodes['1 comment']->save();
|
||||
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Closed');
|
||||
$this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Closed');
|
||||
|
||||
|
@ -106,7 +106,7 @@ class SearchCommentCountToggleTest extends SearchTestBase {
|
|||
$this->searchable_nodes['1 comment']->set('comment', CommentItemInterface::HIDDEN);
|
||||
$this->searchable_nodes['1 comment']->save();
|
||||
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Hidden');
|
||||
$this->assertNoText(t('1 comment'), 'Non-empty comment count does not display for nodes with comment status set to Hidden');
|
||||
}
|
||||
|
|
|
@ -94,18 +94,18 @@ class SearchCommentTest extends SearchTestBase {
|
|||
|
||||
// Search for the comment subject.
|
||||
$edit = array(
|
||||
'keys' => "'" . $edit_comment['subject'] . "'",
|
||||
'search_block_form' => "'" . $edit_comment['subject'] . "'",
|
||||
);
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$node2 = node_load($node->id(), TRUE);
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
$this->assertText($edit_comment['subject'], 'Comment subject found in search results.');
|
||||
|
||||
// Search for the comment body.
|
||||
$edit = array(
|
||||
'keys' => "'" . $comment_body . "'",
|
||||
'search_block_form' => "'" . $comment_body . "'",
|
||||
);
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
|
||||
// Verify that comment is rendered using proper format.
|
||||
|
@ -123,7 +123,7 @@ class SearchCommentTest extends SearchTestBase {
|
|||
$this->cronRun();
|
||||
|
||||
// Search for $title.
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
$this->assertNoText($comment_body, 'Comment body text not found in search results.');
|
||||
}
|
||||
|
||||
|
@ -209,9 +209,9 @@ class SearchCommentTest extends SearchTestBase {
|
|||
|
||||
// Search for the comment subject.
|
||||
$edit = array(
|
||||
'keys' => "'" . $this->comment_subject . "'",
|
||||
'search_block_form' => "'" . $this->comment_subject . "'",
|
||||
);
|
||||
$this->submitGetForm('', $edit, t('Search'));
|
||||
$this->drupalPostForm('', $edit, t('Search'));
|
||||
|
||||
if ($assume_access) {
|
||||
$expected_node_result = $this->assertText($this->node->label());
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\search\Tests\SearchConfigSettingsFormTest.
|
||||
* Definition of Drupal\search\Tests\SearchConfigSettingsFormTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
@ -150,7 +150,7 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
|
|||
|
||||
// Run a search from the correct search URL.
|
||||
$info = $plugin_info[$entity_id];
|
||||
$this->drupalGet('search/' . $entity->getPath(), array('query' => array('keys' => $info['keys'])));
|
||||
$this->drupalGet('search/' . $entity->getPath() . '/' . $info['keys']);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('no results', $entity->label() . ' search found results');
|
||||
$this->assertText($info['text'], 'Correct search text found');
|
||||
|
@ -165,11 +165,12 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
|
|||
|
||||
// Run a search from the search block on the node page. Verify you get
|
||||
// to this plugin's search results page.
|
||||
$terms = array('keys' => $info['keys']);
|
||||
$this->submitGetForm('node', $terms, t('Search'));
|
||||
$current = $this->getURL();
|
||||
$expected = \Drupal::url('search.view_' . $entity->id(), array(), array('query' => array('keys' => $info['keys']), 'absolute' => TRUE));
|
||||
$this->assertEqual( $current, $expected, 'Block redirected to right search page');
|
||||
$terms = array('search_block_form' => $info['keys']);
|
||||
$this->drupalPostForm('node', $terms, t('Search'));
|
||||
$this->assertEqual(
|
||||
$this->getURL(),
|
||||
\Drupal::url('search.view_' . $entity->id(), array('keys' => $info['keys']), array('absolute' => TRUE)),
|
||||
'Block redirected to right search page');
|
||||
|
||||
// Try an invalid search path, which should 404.
|
||||
$this->drupalGet('search/not_a_plugin_path');
|
||||
|
@ -186,13 +187,8 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
|
|||
// Set the node search as default.
|
||||
$this->drupalGet('admin/config/search/settings/manage/node_search/set-default');
|
||||
|
||||
$paths = array(
|
||||
'search/node' => array('query' => array('keys' => 'pizza')),
|
||||
'search/node' => array(),
|
||||
);
|
||||
|
||||
foreach ($paths as $path => $options) {
|
||||
$this->drupalGet($path, $options);
|
||||
foreach (array('search/node/pizza', 'search/node') as $path) {
|
||||
$this->drupalGet($path);
|
||||
foreach ($plugins as $entity_id) {
|
||||
$label = $entities[$entity_id]->label();
|
||||
$this->assertText($label, format_string('%label search tab is shown', array('%label' => $label)));
|
||||
|
|
|
@ -68,9 +68,9 @@ class SearchEmbedFormTest extends SearchTestBase {
|
|||
$this->submit_count = $count;
|
||||
|
||||
// Now verify that we can see and submit the form from the search results.
|
||||
$this->drupalGet('search/node', array('query' => array('keys' => $this->node->label())));
|
||||
$this->drupalGet('search/node/' . $this->node->label());
|
||||
$this->assertText(t('Your name'), 'Form is visible');
|
||||
$this->drupalPostForm(NULL,
|
||||
$this->drupalPostForm('search/node/' . $this->node->label(),
|
||||
array('name' => 'John'),
|
||||
t('Send away'));
|
||||
$this->assertText(t('Test form was submitted'), 'Form message appears');
|
||||
|
|
|
@ -49,15 +49,20 @@ class SearchKeywordsConditionsTest extends SearchTestBase {
|
|||
$this->assertNoText('Dummy search snippet to display');
|
||||
// With keys - get results.
|
||||
$keys = 'bike shed ' . $this->randomName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('keys' => $keys)));
|
||||
$this->drupalGet("search/dummy_path/{$keys}");
|
||||
$this->assertText("Dummy search snippet to display. Keywords: {$keys}");
|
||||
$keys = 'blue drop ' . $this->randomName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('keys' => $keys)));
|
||||
$this->assertText("Dummy search snippet to display. Keywords: {$keys}");
|
||||
// Add some conditions and keys.
|
||||
$keys = 'moving drop ' . $this->randomName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('keys' => 'bike', 'search_conditions' => $keys)));
|
||||
$this->drupalGet("search/dummy_path/bike", array('query' => array('search_conditions' => $keys)));
|
||||
$this->assertText("Dummy search snippet to display.");
|
||||
$this->assertRaw(print_r(array('keys' => 'bike', 'search_conditions' => $keys), TRUE));
|
||||
$this->assertRaw(print_r(array('search_conditions' => $keys), TRUE));
|
||||
// Add some conditions and no keys.
|
||||
$keys = 'drop kick ' . $this->randomName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('search_conditions' => $keys)));
|
||||
$this->assertText("Dummy search snippet to display.");
|
||||
$this->assertRaw(print_r(array('search_conditions' => $keys), TRUE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class SearchLanguageTest extends SearchTestBase {
|
|||
|
||||
// Ensure selecting no language does not make the query different.
|
||||
$this->drupalPostForm('search/node', array(), t('Advanced search'));
|
||||
$this->assertEqual($this->getUrl(), url('search/node/', array('query' => array('keys' => ''), 'absolute' => TRUE)), 'Correct page redirection, no language filtering.');
|
||||
$this->assertEqual($this->getUrl(), url('search/node/', array('absolute' => TRUE)), 'Correct page redirection, no language filtering.');
|
||||
|
||||
// Pick French and ensure it is selected.
|
||||
$edit = array('language[fr]' => TRUE);
|
||||
|
|
|
@ -42,7 +42,7 @@ class SearchPageOverrideTest extends SearchTestBase {
|
|||
|
||||
function testSearchPageHook() {
|
||||
$keys = 'bike shed ' . $this->randomName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('keys' => $keys)));
|
||||
$this->drupalGet("search/dummy_path/{$keys}");
|
||||
$this->assertText('Dummy search snippet', 'Dummy search snippet is shown');
|
||||
$this->assertText('Test page text is here', 'Page override is working');
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class SearchPageTextTest extends SearchTestBase {
|
|||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$this->searching_user = $this->drupalCreateUser(array('search content', 'access user profiles', 'use advanced search'));
|
||||
$this->searching_user = $this->drupalCreateUser(array('search content', 'access user profiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,9 +55,9 @@ class SearchPageTextTest extends SearchTestBase {
|
|||
$this->assertTitle($title, 'Search page title is correct');
|
||||
|
||||
// Test that search keywords containing slashes are correctly loaded
|
||||
// from the GET params and displayed in the search form.
|
||||
// from the path and displayed in the search form.
|
||||
$arg = $this->randomName() . '/' . $this->randomName();
|
||||
$this->drupalGet('search/node', array('query' => array('keys' => $arg)));
|
||||
$this->drupalGet('search/node/' . $arg);
|
||||
$input = $this->xpath("//input[@id='edit-keys' and @value='{$arg}']");
|
||||
$this->assertFalse(empty($input), 'Search keys with a / are correctly set as the default value in the search box.');
|
||||
|
||||
|
@ -74,41 +74,5 @@ class SearchPageTextTest extends SearchTestBase {
|
|||
$edit['keys'] = implode(' ', $keys);
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertRaw(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => $limit)));
|
||||
|
||||
// Test that a search on Node or User with no keywords entered generates
|
||||
// the "Please enter some keywords" message.
|
||||
$this->drupalPostForm('search/node', array(), t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on node page');
|
||||
$this->drupalPostForm('search/user', array(), t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on user page');
|
||||
|
||||
// Make sure the "Please enter some keywords" message is NOT displayed if
|
||||
// you use "or" words or phrases in Advanced Search.
|
||||
$this->drupalPostForm('search/node', array('or' => $this->randomName() . ' ' . $this->randomName()), t('Advanced search'));
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced OR keywords entered, no keywords message is not displayed on node page');
|
||||
$this->drupalPostForm('search/node', array('phrase' => '"' . $this->randomName() . '" "' . $this->randomName() . '"'), t('Advanced search'));
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced phrase entered, no keywords message is not displayed on node page');
|
||||
|
||||
// Verify that if you search for a too-short keyword, you get the right
|
||||
// message, and that if after that you search for a longer keyword, you
|
||||
// do not still see the message.
|
||||
$this->drupalPostForm('search/node', array('keys' => $this->randomName(1)), t('Search'));
|
||||
$this->assertText('You must include at least one positive keyword', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->drupalPostForm(NULL, array('keys' => $this->randomName()), t('Search'));
|
||||
$this->assertNoText('You must include at least one positive keyword', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Test that if you search for a URL with .. in it, you still end up at
|
||||
// the search page. See issue https://drupal.org/node/890058.
|
||||
$this->drupalPostForm('search/node', array('keys' => '../../admin'), t('Search'));
|
||||
$this->assertResponse(200, 'Searching for ../../admin with non-admin user does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for ../../admin with non-admin user gives you a no search results page');
|
||||
|
||||
// Test that if you search for a URL starting with "./", you still end up
|
||||
// at the search page. See issue https://drupal.org/node/1421560.
|
||||
$this->drupalPostForm('search/node', array('keys' => '.something'), t('Search'));
|
||||
$this->assertResponse(200, 'Searching for .something does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for .something gives you a no search results page');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\search\Tests\SearchQueryAlterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Tests that the node search query can be altered via the query alter hook.
|
||||
*/
|
||||
class SearchQueryAlterTest extends SearchTestBase {
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('search_query_alter');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Search query alter',
|
||||
'description' => 'Tests that the node search query can be altered via the query alter hook.',
|
||||
'group' => 'Search'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the query alter works.
|
||||
*/
|
||||
function testQueryAlter() {
|
||||
// Login with sufficient privileges.
|
||||
$this->drupalLogin($this->drupalCreateUser(array('create page content', 'search content')));
|
||||
|
||||
// Create a node and an article with the same keyword. The query alter
|
||||
// test module will alter the query so only articles should be returned.
|
||||
$data = array(
|
||||
'type' => 'page',
|
||||
'title' => 'test page',
|
||||
'body' => array(array('value' => 'pizza')),
|
||||
);
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
$data['type'] = 'article';
|
||||
$data['title'] = 'test article';
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
// Update the search index.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search for the body keyword 'pizza'.
|
||||
$this->drupalPostForm('search/node', array('keys' => 'pizza'), t('Search'));
|
||||
// The article should be there but not the page.
|
||||
$this->assertText('article', 'Article is in search results');
|
||||
$this->assertNoText('page', 'Page is not in search results');
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Component\Utility\String;
|
||||
|
||||
/**
|
||||
* Defines the common search test code.
|
||||
|
@ -31,66 +30,4 @@ abstract class SearchTestBase extends WebTestBase {
|
|||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates submission of a form using GET instead of POST.
|
||||
*
|
||||
* Forms that use the GET method cannot be submitted with
|
||||
* WebTestBase::drupalPostForm(), which explicitly uses POST to submit the
|
||||
* form. So this method finds the form, verifies that it has input fields and
|
||||
* a submit button matching the inputs to this method, and then calls
|
||||
* WebTestBase::drupalGet() to simulate the form submission to the 'action'
|
||||
* URL of the form (if set, or the current URL if not).
|
||||
*
|
||||
* See WebTestBase::drupalPostForm() for more detailed documentation of the
|
||||
* function parameters.
|
||||
*
|
||||
* @param string $path
|
||||
* Location of the form to be submitted: either a Drupal path, absolute
|
||||
* path, or NULL to use the current page.
|
||||
* @param array $edit
|
||||
* Form field data to submit. Unlike drupalPostForm(), this does not support
|
||||
* file uploads.
|
||||
* @param string $submit
|
||||
* Value of the submit button to submit clicking. Unlike drupalPostForm(),
|
||||
* this does not support AJAX.
|
||||
* @param string $form_html_id
|
||||
* (optional) HTML ID of the form, to disambiguate.
|
||||
*/
|
||||
protected function submitGetForm($path, $edit, $submit, $form_html_id = NULL) {
|
||||
if (isset($path)) {
|
||||
$this->drupalGet($path);
|
||||
}
|
||||
|
||||
if ($this->parse()) {
|
||||
// Iterate over forms to find one that matches $edit and $submit.
|
||||
$edit_save = $edit;
|
||||
$xpath = '//form';
|
||||
if (!empty($form_html_id)) {
|
||||
$xpath .= "[@id='" . $form_html_id . "']";
|
||||
}
|
||||
$forms = $this->xpath($xpath);
|
||||
foreach ($forms as $form) {
|
||||
// Try to set the fields of this form as specified in $edit.
|
||||
$edit = $edit_save;
|
||||
$post = array();
|
||||
$upload = array();
|
||||
$submit_matches = $this->handleForm($post, $edit, $upload, $submit, $form);
|
||||
if (!$edit && $submit_matches) {
|
||||
// Everything matched, so "submit" the form.
|
||||
$action = isset($form['action']) ? $this->getAbsoluteUrl((string) $form['action']) : NULL;
|
||||
$this->drupalGet($action, array('query' => $post));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We have not found a form which contained all fields of $edit and
|
||||
// the submit button.
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->fail(String::format('Failed to set field @name to @value', array('@name' => $name, '@value' => $value)));
|
||||
}
|
||||
$this->assertTrue($submit_matches, format_string('Found the @submit button', array('@submit' => $submit)));
|
||||
$this->fail(format_string('Found the requested form fields at @path', array('@path' => $path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
* Returns the conditions property.
|
||||
*
|
||||
* @return array
|
||||
* The query conditions.
|
||||
*/
|
||||
public function &conditions() {
|
||||
return $this->conditions;
|
||||
|
@ -28,7 +27,6 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
* Returns the words property.
|
||||
*
|
||||
* @return array
|
||||
* The positive search keywords.
|
||||
*/
|
||||
public function words() {
|
||||
return $this->words;
|
||||
|
@ -38,8 +36,6 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
* Returns the simple property.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if it is a simple query, and FALSE if it is complicated (phrases
|
||||
* or LIKE).
|
||||
*/
|
||||
public function simple() {
|
||||
return $this->simple;
|
||||
|
@ -49,7 +45,6 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
* Returns the matches property.
|
||||
*
|
||||
* @return int
|
||||
* The number of matches needed.
|
||||
*/
|
||||
public function matches() {
|
||||
return $this->matches;
|
||||
|
|
|
@ -815,19 +815,3 @@ function search_module_preinstall() {
|
|||
// @todo Remove in https://drupal.org/node/2155635.
|
||||
\Drupal::service('plugin.manager.search')->clearCachedDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter() for the search_block_form form.
|
||||
*
|
||||
* Since the exposed form is a GET form, we don't want it to send the form
|
||||
* tokens. However, you cannot make this happen in the form builder function
|
||||
* itself, because the tokens are added to the form after the builder function
|
||||
* is called. So, we have to do it in a form_alter.
|
||||
*
|
||||
* @see \Drupal\search\Form\SearchBlockForm
|
||||
*/
|
||||
function search_form_search_block_form_alter(&$form, &$form_state) {
|
||||
$form['form_build_id']['#access'] = FALSE;
|
||||
$form['form_token']['#access'] = FALSE;
|
||||
$form['form_id']['#access'] = FALSE;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Drupal\search_extra_type\Plugin\Search;
|
|||
use Drupal\search\Plugin\ConfigurableSearchPluginBase;
|
||||
|
||||
/**
|
||||
* Executes a dummy keyword search.
|
||||
* Executes a keyword search against the search index.
|
||||
*
|
||||
* @SearchPlugin(
|
||||
* id = "search_extra_type_search",
|
||||
|
@ -33,7 +33,7 @@ class SearchExtraTypeSearch extends ConfigurableSearchPluginBase {
|
|||
* Verifies if the given parameters are valid enough to execute a search for.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if there are keywords or search conditions in the query.
|
||||
* A true or false depending on the implementation.
|
||||
*/
|
||||
public function isSearchExecutable() {
|
||||
return (bool) ($this->keywords || !empty($this->searchParameters['search_conditions']));
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
name: 'Test Search Query Alter'
|
||||
type: module
|
||||
description: 'Support module for Search module testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
hidden: true
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Drupal\Core\Database\Query\AlterableInterface;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test module that alters search queries.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_query_TAG_alter(): tag search_$type with $type node_search.
|
||||
*/
|
||||
function search_query_alter_query_search_node_search_alter(AlterableInterface $query) {
|
||||
// For testing purposes, restrict the query to node type 'article' only.
|
||||
$query->condition('n.type', 'article');
|
||||
}
|
|
@ -2162,8 +2162,6 @@ abstract class WebTestBase extends TestBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
// An empty name means the value is not sent.
|
||||
unset($post['']);
|
||||
return $submit_matches;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use Drupal\Core\Cache\Cache;
|
|||
*
|
||||
* @see \Drupal\system\Tests\Bootstrap\PageCacheTest
|
||||
* @see \Drupal\node\Tests\NodePageCacheTest
|
||||
* @see \Drupal\menu_ui\Tests\MenuTest::testMenuBlockPageCacheTags()
|
||||
* @see \Drupal\menu\Tests\MenuTest::testMenuBlockPageCacheTags()
|
||||
*/
|
||||
class PageCacheTagsIntegrationTest extends WebTestBase {
|
||||
|
||||
|
|
|
@ -7,4 +7,4 @@ core: 8.x
|
|||
hidden: true
|
||||
dependencies:
|
||||
- test_page_test
|
||||
- menu_ui
|
||||
- menu
|
||||
|
|
|
@ -53,7 +53,7 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'block', 'menu_ui', 'user', 'taxonomy', 'toolbar', 'language', 'test_page_test', 'locale');
|
||||
public static $modules = array('node', 'block', 'menu', 'user', 'taxonomy', 'toolbar', 'language', 'test_page_test', 'locale');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
|
|
@ -19,7 +19,7 @@ class UserAccountLinksTests extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('menu_ui', 'block', 'test_page_test');
|
||||
public static $modules = array('menu', 'block', 'test_page_test');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
|
|
@ -34,7 +34,7 @@ class UserSearchTest extends WebTestBase {
|
|||
$this->drupalLogin($user1);
|
||||
$keys = $user1->getEmail();
|
||||
$edit = array('keys' => $keys);
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->drupalPostForm('search/user/', $edit, t('Search'));
|
||||
$this->assertNoText($keys);
|
||||
$this->drupalLogout();
|
||||
|
||||
|
@ -42,7 +42,7 @@ class UserSearchTest extends WebTestBase {
|
|||
$this->drupalLogin($user2);
|
||||
$keys = $user2->getEmail();
|
||||
$edit = array('keys' => $keys);
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->drupalPostForm('search/user/', $edit, t('Search'));
|
||||
$this->assertText($keys);
|
||||
|
||||
// Create a blocked user.
|
||||
|
@ -53,14 +53,14 @@ class UserSearchTest extends WebTestBase {
|
|||
// Verify that users with "administer users" permissions can see blocked
|
||||
// accounts in search results.
|
||||
$edit = array('keys' => $blocked_user->getUsername());
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->drupalPostForm('search/user/', $edit, t('Search'));
|
||||
$this->assertText($blocked_user->getUsername(), 'Blocked users are listed on the user search results for users with the "administer users" permission.');
|
||||
|
||||
// Verify that users without "administer users" permissions do not see
|
||||
// blocked accounts in search results.
|
||||
$this->drupalLogin($user1);
|
||||
$edit = array('keys' => $blocked_user->getUsername());
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->drupalPostForm('search/user/', $edit, t('Search'));
|
||||
$this->assertNoText($blocked_user->getUsername(), 'Blocked users are hidden from the user search results.');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
|
|
@ -217,11 +217,11 @@ class Page extends PathPluginBase {
|
|||
);
|
||||
|
||||
// Only display the menu selector if menu module is enabled.
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu_ui')) {
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu')) {
|
||||
$form['menu']['name'] = array(
|
||||
'#title' => t('Menu'),
|
||||
'#type' => 'select',
|
||||
'#options' => menu_ui_get_menus(),
|
||||
'#options' => menu_get_menus(),
|
||||
'#default_value' => $menu['name'],
|
||||
'#states' => array(
|
||||
'visible' => array(
|
||||
|
@ -334,11 +334,11 @@ class Page extends PathPluginBase {
|
|||
),
|
||||
);
|
||||
// Only display the menu selector if menu module is enabled.
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu_ui')) {
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu')) {
|
||||
$form['tab_options']['name'] = array(
|
||||
'#title' => t('Menu'),
|
||||
'#type' => 'select',
|
||||
'#options' => menu_ui_get_menus(),
|
||||
'#options' => menu_get_menus(),
|
||||
'#default_value' => $tab_options['name'],
|
||||
'#description' => t('Insert item into an available menu.'),
|
||||
'#states' => array(
|
||||
|
|
|
@ -292,8 +292,8 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
|
|||
'#prefix' => '<div id="edit-page-link-properties-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu_ui')) {
|
||||
$menu_options = menu_ui_get_menus();
|
||||
if (\Drupal::moduleHandler()->moduleExists('menu')) {
|
||||
$menu_options = menu_get_menus();
|
||||
}
|
||||
else {
|
||||
// These are not yet translated.
|
||||
|
|
|
@ -59,7 +59,7 @@ class DisplayPath extends UITestBase {
|
|||
* Tests the menu and tab option form.
|
||||
*/
|
||||
public function testMenuOptions() {
|
||||
$this->container->get('module_handler')->install(array('menu_ui'));
|
||||
$this->container->get('module_handler')->install(array('menu'));
|
||||
$this->drupalGet('admin/structure/views/view/test_view');
|
||||
|
||||
// Add a new page display.
|
||||
|
|
|
@ -21,7 +21,7 @@ dependencies:
|
|||
- entity_reference
|
||||
- help
|
||||
- image
|
||||
- menu_ui
|
||||
- menu
|
||||
- options
|
||||
- path
|
||||
- taxonomy
|
||||
|
|
Loading…
Reference in New Issue