Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
F
facets
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Custom Issue Tracker
Custom Issue Tracker
Labels
Merge Requests
7
Merge Requests
7
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
project
facets
Commits
706ce181
Commit
706ce181
authored
Apr 05, 2017
by
dragos-dumi
Committed by
borisson_
Apr 05, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue
#2717537
by dragos-dumi, borisson_: Breadcrumbs support
parent
ca4c9ccf
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
340 additions
and
1 deletion
+340
-1
config/schema/facets.facetsource.schema.yml
config/schema/facets.facetsource.schema.yml
+10
-0
facets.module
facets.module
+127
-0
src/Entity/FacetSource.php
src/Entity/FacetSource.php
+22
-1
src/FacetSourceInterface.php
src/FacetSourceInterface.php
+16
-0
src/Form/FacetSourceEditForm.php
src/Form/FacetSourceEditForm.php
+22
-0
tests/src/Functional/BreadcrumbIntegrationTest.php
tests/src/Functional/BreadcrumbIntegrationTest.php
+112
-0
tests/src/Functional/FacetSourceTest.php
tests/src/Functional/FacetSourceTest.php
+24
-0
tests/src/Kernel/Entity/FacetSourceTest.php
tests/src/Kernel/Entity/FacetSourceTest.php
+7
-0
No files found.
config/schema/facets.facetsource.schema.yml
View file @
706ce181
...
...
@@ -17,4 +17,14 @@ facets.facet_source.*:
url_processor
:
type
:
string
label
:
'
Url
processor'
breadcrumb
:
type
:
mapping
labal
:
'
Breadcrumb'
mapping
:
active
:
type
:
boolean
label
:
'
Append
active
facets
to
breadcrumb'
group
:
type
:
boolean
label
:
'
Group
active
items
under
same
crumb'
third_party_settings
:
{}
facets.module
View file @
706ce181
...
...
@@ -6,9 +6,12 @@
*/
use
Drupal\Component\Utility\Html
;
use
Drupal\Core\Breadcrumb\Breadcrumb
;
use
Drupal\Core\Link
;
use
Drupal\Core\Routing\RouteMatchInterface
;
use
Drupal\facets\Entity\Facet
;
use
Drupal\facets\Entity\FacetSource
;
use
Drupal\facets\FacetInterface
;
use
Drupal\search_api
\
Query\QueryInterface
;
use
Drupal\views\Entity\View
;
use
Drupal\Core\Entity\EntityInterface
;
...
...
@@ -211,3 +214,127 @@ function facets_entity_predelete(EntityInterface $entity) {
function
facets_preprocess_facets_item_list
(
&
$variables
)
{
template_preprocess_item_list
(
$variables
);
}
/**
* Implements hook_system_breadcrumb_alter().
*/
function
facets_system_breadcrumb_alter
(
Breadcrumb
&
$breadcrumb
,
RouteMatchInterface
$route_match
,
array
$context
)
{
/** @var \Drupal\facets\FacetSource\FacetSourcePluginManager $facet_source_manager */
$facet_source_manager
=
\
Drupal
::
service
(
'plugin.manager.facets.facet_source'
);
/** @var \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager */
$facet_manager
=
\
Drupal
::
service
(
'facets.manager'
);
/** @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */
$entity_type_manager
=
\
Drupal
::
service
(
'entity_type.manager'
);
/** @var \Drupal\Core\Entity\EntityStorageInterface $facet_source_storage */
$facet_source_storage
=
$entity_type_manager
->
getStorage
(
'facets_facet_source'
);
$facet_sources_definitions
=
$facet_source_manager
->
getDefinitions
();
// No facet sources found, so don't do anything.
if
(
empty
(
$facet_sources_definitions
))
{
return
;
}
foreach
(
$facet_sources_definitions
as
$definition
)
{
/* @var \Drupal\facets\FacetSource\FacetSourcePluginBase $facet_source_plugin */
$facet_source_plugin
=
$facet_source_manager
->
createInstance
(
$definition
[
'id'
]);
// If the current facet source is not being rendered, don't do anything with
// these facet sources.
if
(
!
$facet_source_plugin
->
isRenderedInCurrentRequest
())
{
continue
;
}
$source_id
=
str_replace
(
':'
,
'__'
,
$definition
[
'id'
]);
/** @var \Drupal\facets\FacetSourceInterface $facet_source */
$facet_source
=
$facet_source_storage
->
load
(
$source_id
);
// If the facet source is not loaded, or the facet source doesn't have
// breadcrumbs enabled, don't do anything.
if
(
!
(
$facet_source
&&
$facet_source
->
getBreadcrumbSettings
()[
'active'
]))
{
continue
;
}
// Add the required cacheability metadata.
$breadcrumb
->
addCacheContexts
([
'url'
]);
$breadcrumb
->
addCacheableDependency
(
$facet_source
);
// Process the facets if they are not already processed.
$facet_manager
->
processFacets
();
$facets
=
$facet_manager
->
getFacetsByFacetSourceId
(
$definition
[
'id'
]);
// Sort facets by weight.
uasort
(
$facets
,
function
(
FacetInterface
$a
,
FacetInterface
$b
)
{
if
(
$a
->
getWeight
()
==
$b
->
getWeight
())
{
return
0
;
}
return
(
$a
->
getWeight
()
<
$b
->
getWeight
())
?
-
1
:
1
;
});
/** @var \Drupal\facets\UrlProcessor\UrlProcessorPluginManager $url_processor_manager */
$url_processor_manager
=
\
Drupal
::
service
(
'plugin.manager.facets.url_processor'
);
// Get active facets and results to use them at building the crumbs.
$active_results
=
[];
$active_facets
=
[];
foreach
(
$facets
as
$facet
)
{
if
(
$active_items
=
$facet
->
getActiveItems
())
{
// Add the facet as a cacheable dependency.
$breadcrumb
->
addCacheableDependency
(
$facet
);
/** @var \Drupal\facets\UrlProcessor\UrlProcessorInterface $url_processor */
$url_processor
=
$url_processor_manager
->
createInstance
(
$facet_source
->
getUrlProcessorName
(),
[
'facet'
=>
$facet
]);
$facet_manager
->
build
(
$facet
);
foreach
(
$facet
->
getResults
()
as
$result
)
{
if
(
$result
->
isActive
())
{
// Clone the result so we can mark it as inactive to be added to the
// url parameters when calling buildUrls.
$cloned_result
=
clone
$result
;
$cloned_result
->
setActiveState
(
FALSE
);
$active_results
[
$facet
->
getUrlAlias
()][]
=
$cloned_result
;
}
}
$url_processor
->
buildUrls
(
$facet
,
$active_results
[
$facet
->
getUrlAlias
()]);
$active_facets
[
$facet
->
getUrlAlias
()]
=
$facet
;
}
}
// TODO find a better way to construct the url for a crumb maybe url
// processor will have a function to get params for a result
// without all the other request parameters; with this we could implement:
// @see https://www.drupal.org/node/2861586
// TODO handle not grouped facets.
foreach
(
$active_results
as
$facet_alias
=>
$facet_results
)
{
$facet_used_result
[]
=
$facet_alias
;
$facet_crumb_items
=
[];
reset
(
$facet_results
);
$facet_url
=
clone
current
(
$facet_results
)
->
getUrl
();
// Because we can't get the desired url trough a url processor method
// we iterate each result url and remove the facet params that haven't
// been used on previous crumbs
foreach
(
$facet_results
as
$res
)
{
$facet_url
=
$res
->
getUrl
();
/** @var \Drupal\Core\Url $facet_url */
$query
=
$facet_url
->
getOption
(
'query'
);
$source_filter
=
$query
[
$facet_source
->
getFilterKey
()];
$source_filter
=
array_unique
(
$source_filter
);
$source_filter
=
array_filter
(
$source_filter
);
$matches
=
preg_grep
(
'/^'
.
implode
(
'|^'
,
$facet_used_result
)
.
'/'
,
$source_filter
);
$query
[
$facet_source
->
getFilterKey
()]
=
$matches
;
$facet_crumb_items
[]
=
$res
->
getDisplayValue
();
}
// Set the new query and create the link.
$facet_url
->
setOption
(
'query'
,
$query
);
$crumb_text
=
$active_facets
[
$facet_alias
]
->
label
()
.
': '
.
implode
(
', '
,
$facet_crumb_items
);
$link
=
Link
::
fromTextAndUrl
(
$crumb_text
,
$facet_url
);
$breadcrumb
->
addLink
(
$link
);
}
}
}
src/Entity/FacetSource.php
View file @
706ce181
...
...
@@ -32,7 +32,8 @@ use Drupal\facets\FacetSourceInterface;
* "id",
* "name",
* "filter_key",
* "url_processor"
* "url_processor",
* "breadcrumb"
* },
* links = {
* "canonical" = "/admin/config/search/facets/facet-sources/",
...
...
@@ -70,6 +71,13 @@ class FacetSource extends ConfigEntityBase implements FacetSourceInterface {
*/
protected
$url_processor
=
'query_string'
;
/**
* The breadcrumb settings.
*
* @var array
*/
protected
$breadcrumb
=
[];
/**
* {@inheritdoc}
*/
...
...
@@ -105,4 +113,17 @@ class FacetSource extends ConfigEntityBase implements FacetSourceInterface {
return
$this
->
url_processor
;
}
/**
* {@inheritdoc}
*/
public
function
getBreadcrumbSettings
()
{
return
$this
->
breadcrumb
;
}
/**
* {@inheritdoc}
*/
public
function
setBreadcrumbSettings
(
array
$settings
)
{
$this
->
breadcrumb
=
$settings
;
}
}
src/FacetSourceInterface.php
View file @
706ce181
...
...
@@ -49,4 +49,20 @@ interface FacetSourceInterface extends ConfigEntityInterface {
*/
public
function
getUrlProcessorName
();
/**
* Returns an array with breadcrumb settings.
*
* @return array
* The breadcrumb settings.
*/
public
function
getBreadcrumbSettings
();
/**
* Sets breadcrumb settings.
*
* @param array $settings
* The breadcrumb settings.
*/
public
function
setBreadcrumbSettings
(
array
$settings
);
}
src/Form/FacetSourceEditForm.php
View file @
706ce181
...
...
@@ -89,6 +89,7 @@ class FacetSourceEditForm extends EntityForm {
/** @var \Drupal\facets\FacetSourceInterface $facet_source */
$facet_source
=
$this
->
getEntity
();
$form
[
'#tree'
]
=
TRUE
;
$form
[
'filter_key'
]
=
[
'#type'
=>
'textfield'
,
'#title'
=>
$this
->
t
(
'Filter key'
),
...
...
@@ -116,6 +117,27 @@ class FacetSourceEditForm extends EntityForm {
'The URL Processor defines the url structure used for this facet source.'
)
.
'<br />- '
.
implode
(
'<br>- '
,
$url_processors_description
),
];
$breadcrumb_settings
=
$facet_source
->
getBreadcrumbSettings
();
$form
[
'breadcrumb'
]
=
[
'#type'
=>
'fieldset'
,
'#title'
=>
$this
->
t
(
'Breadcrumb'
),
];
$form
[
'breadcrumb'
][
'active'
]
=
[
'#type'
=>
'checkbox'
,
'#title'
=>
$this
->
t
(
'Append active facets to breadcrumb'
),
'#default_value'
=>
isset
(
$breadcrumb_settings
[
'active'
])
?
$breadcrumb_settings
[
'active'
]
:
FALSE
,
];
$form
[
'breadcrumb'
][
'group'
]
=
[
'#type'
=>
'checkbox'
,
'#title'
=>
$this
->
t
(
'Group active items under same crumb (not implemented yet - now always grouping)'
),
'#default_value'
=>
isset
(
$breadcrumb_settings
[
'group'
])
?
$breadcrumb_settings
[
'group'
]
:
FALSE
,
'#states'
=>
[
'visible'
=>
[
':input[name="breadcrumb[active]"]'
=>
[
'checked'
=>
TRUE
],
]
]
];
// The parent's form build method will add a save button.
return
parent
::
buildForm
(
$form
,
$form_state
);
}
...
...
tests/src/Functional/BreadcrumbIntegrationTest.php
0 → 100644
View file @
706ce181
<?php
namespace
Drupal\Tests\facets\Functional
;
use
Drupal\Component\Utility\UrlHelper
;
/**
* Tests the overall functionality of the Facets admin UI.
*
* @group facets
*/
class
BreadcrumbIntegrationTest
extends
FacetsTestBase
{
/**
* {@inheritdoc}
*/
public
static
$modules
=
[
'views'
,
'node'
,
'search_api'
,
'facets'
,
'block'
,
'facets_search_api_dependency'
,
];
/**
* {@inheritdoc}
*/
public
function
setUp
()
{
parent
::
setUp
();
$this
->
drupalLogin
(
$this
->
adminUser
);
$this
->
setUpExampleStructure
();
$this
->
insertExampleContent
();
self
::
assertEquals
(
$this
->
indexItems
(
$this
->
indexId
),
5
,
'5 items were indexed.'
);
$block
=
[
'region'
=>
'footer'
,
'label'
=>
'Breadcrumbs'
,
'provider'
=>
'system'
,
];
$this
->
drupalPlaceBlock
(
'system_breadcrumb_block'
,
$block
);
$this
->
resetAll
();
}
/**
* Tests Breadcrumb integration with grouping.
*/
public
function
testGroupingIntegration
()
{
$this
->
drupalGet
(
'admin/config/search/facets'
);
$this
->
clickLink
(
'Configure'
,
1
);
$edit
=
[
'filter_key'
=>
'f'
,
'url_processor'
=>
'query_string'
,
'breadcrumb[active]'
=>
TRUE
,
'breadcrumb[group]'
=>
TRUE
,
];
$this
->
drupalPostForm
(
NULL
,
$edit
,
'Save'
);
$id
=
'keywords'
;
$name
=
'#Keywords'
;
$this
->
createFacet
(
$name
,
$id
,
'keywords'
);
$this
->
resetAll
();
$this
->
drupalGet
(
'admin/config/search/facets/'
.
$id
.
'/edit'
);
$id
=
'type'
;
$name
=
'#Type'
;
$this
->
createFacet
(
$name
,
$id
);
$this
->
resetAll
();
$this
->
drupalGet
(
'admin/config/search/facets/'
.
$id
.
'/edit'
);
$this
->
drupalPostForm
(
NULL
,
[
'facet_settings[weight]'
=>
'1'
],
'Save'
);
// Breadcrumb should show #Keywords: orange > #Type: article, item
$initial_query
=
[
'search_api_fulltext'
=>
'foo'
,
'test_param'
=>
1
];
$this
->
drupalGet
(
'search-api-test-fulltext'
,
[
'query'
=>
$initial_query
]);
$this
->
clickLink
(
'item'
);
$this
->
clickLink
(
'article'
);
$this
->
clickLink
(
'orange'
);
$this
->
assertSession
()
->
linkExists
(
'#Keywords: orange'
);
$this
->
assertSession
()
->
linkExists
(
'#Type: article, item'
);
$this
->
clickLink
(
'#Type: article, item'
);
$this
->
assertSession
()
->
linkExists
(
'#Keywords: orange'
);
$this
->
assertSession
()
->
linkExists
(
'#Type: article, item'
);
$this
->
checkFacetIsActive
(
'orange'
);
$this
->
checkFacetIsActive
(
'item'
);
$this
->
checkFacetIsActive
(
'article'
);
$this
->
clickLink
(
'#Keywords: orange'
);
$this
->
assertSession
()
->
linkExists
(
'#Keywords: orange'
);
$this
->
assertSession
()
->
linkNotExists
(
'#Type: article, item'
);
$this
->
checkFacetIsActive
(
'orange'
);
$this
->
checkFacetIsNotActive
(
'item'
);
$this
->
checkFacetIsNotActive
(
'article'
);
// Check that the current url still has the initial parameters.
$curr_url
=
UrlHelper
::
parse
(
$this
->
getUrl
());
$this
->
assertArraySubset
(
$initial_query
,
$curr_url
[
'query'
]);
}
/**
* Tests Breadcrumb integration without grouping.
*/
// public function testNonGroupingIntegration() {
// TODO test it after we implement non grouping functionality.
// }
}
tests/src/Functional/FacetSourceTest.php
View file @
706ce181
...
...
@@ -83,4 +83,28 @@ class FacetSourceTest extends FacetsTestBase {
$this
->
assertEquals
(
'dummy_query'
,
$elements
[
0
]
->
getValue
());
}
/**
* Tests editing the breadcrumb settings.
*/
public
function
testEditBreadcrumbSettings
()
{
$this
->
assertSession
()
->
fieldExists
(
'breadcrumb[active]'
);
$this
->
assertSession
()
->
fieldExists
(
'breadcrumb[group]'
);
$this
->
assertSession
()
->
checkboxNotChecked
(
'breadcrumb[group]'
);
$this
->
assertSession
()
->
checkboxNotChecked
(
'breadcrumb[active]'
);
// Change the breadcrumb settings.
$edit
=
array
(
'breadcrumb[active]'
=>
TRUE
,
'breadcrumb[group]'
=>
TRUE
,
);
$this
->
drupalPostForm
(
NULL
,
$edit
,
'Save'
);
$this
->
assertSession
()
->
statusCodeEquals
(
200
);
$this
->
assertSession
()
->
addressEquals
(
'admin/config/search/facets'
);
$this
->
assertSession
()
->
pageTextContains
(
'Facet source search_api:views_block__search_api_test_view__block_1 has been saved.'
);
$this
->
clickLink
(
'Configure'
);
// Test that saving worked and that the url processor has the new value.
$this
->
assertSession
()
->
checkboxChecked
(
'breadcrumb[group]'
);
$this
->
assertSession
()
->
checkboxChecked
(
'breadcrumb[active]'
);
}
}
tests/src/Kernel/Entity/FacetSourceTest.php
View file @
706ce181
...
...
@@ -60,6 +60,8 @@ class FacetSourceTest extends KernelTestBase {
* @covers ::getFilterKey
* @covers ::setUrlProcessor
* @covers ::getUrlProcessorName
* @covers ::setBreadcrumbSettings
* @covers ::getBreadcrumbSettings
*/
public
function
testGetterSetters
()
{
$fs
=
new
FacetSource
([
'id'
=>
'llama'
],
'facets_facet_source'
);
...
...
@@ -67,12 +69,17 @@ class FacetSourceTest extends KernelTestBase {
$this
->
assertNull
(
$fs
->
getFilterKey
());
$this
->
assertNull
(
$fs
->
getName
());
$this
->
assertEquals
(
'query_string'
,
$fs
->
getUrlProcessorName
());
$this
->
assertEmpty
(
$fs
->
getBreadcrumbSettings
());
$fs
->
setFilterKey
(
'ab'
);
$this
->
assertEquals
(
'ab'
,
$fs
->
getFilterKey
());
$fs
->
setUrlProcessor
(
'test'
);
$this
->
assertEquals
(
'test'
,
$fs
->
getUrlProcessorName
());
$breadcrumb_settings
=
[
'active'
=>
1
,
'group'
=>
1
];
$fs
->
setBreadcrumbSettings
(
$breadcrumb_settings
);
$this
->
assertEquals
(
$breadcrumb_settings
,
$fs
->
getBreadcrumbSettings
());
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment