added prog's child TOC menu #1459
This commit is contained in:
parent
70d2ffc4c7
commit
552f407a8c
@ -45,6 +45,7 @@
|
||||
"drupal/structure_sync": "^2.0",
|
||||
"drupal/twig_xdebug": "^1.2",
|
||||
"drupal/video_embed_field": "^2.4",
|
||||
"drupal/views_argument_token": "2.0.x-dev@dev",
|
||||
"drupal/views_conditional": "^1.4",
|
||||
"geocoder-php/google-maps-provider": "^4.6",
|
||||
"geocoder-php/mapquest-provider": "^4.2",
|
||||
|
71
composer.lock
generated
71
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9d194093362fe369bebc140060e38193",
|
||||
"content-hash": "71c9833e93d4a0ac121d68314e543665",
|
||||
"packages": [
|
||||
{
|
||||
"name": "ajgl/breakpoint-twig-extension",
|
||||
@ -9404,6 +9404,72 @@
|
||||
"source": "https://git.drupalcode.org/project/video_embed_field"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drupal/views_argument_token",
|
||||
"version": "dev-2.0.x",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://git.drupalcode.org/project/views_argument_token.git",
|
||||
"reference": "2953247cfc4b41d1658fe0666ed76fb5a4fbd1c6"
|
||||
},
|
||||
"require": {
|
||||
"drupal/core": "^8 || ^9"
|
||||
},
|
||||
"type": "drupal-module",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-2.0.x": "2.0.x-dev"
|
||||
},
|
||||
"drupal": {
|
||||
"version": "2.0.0+1-dev",
|
||||
"datestamp": "1629465811",
|
||||
"security-coverage": {
|
||||
"status": "not-covered",
|
||||
"message": "Project has not opted into security advisory coverage!"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packages.drupal.org/8/downloads",
|
||||
"license": [
|
||||
"GPL-2.0+"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "eme",
|
||||
"homepage": "https://www.drupal.org/u/eme"
|
||||
},
|
||||
{
|
||||
"name": "Mohamed Anis Taktak",
|
||||
"homepage": "https://www.drupal.org/u/matio89"
|
||||
},
|
||||
{
|
||||
"name": "Dakwamine",
|
||||
"homepage": "https://www.drupal.org/u/dakwamine"
|
||||
},
|
||||
{
|
||||
"name": "Stephen Mulvihill",
|
||||
"homepage": "https://www.drupal.org/u/smulvih2"
|
||||
},
|
||||
{
|
||||
"name": "mh.marouan",
|
||||
"homepage": "https://www.drupal.org/user/3203501"
|
||||
},
|
||||
{
|
||||
"name": "smulvih2",
|
||||
"homepage": "https://www.drupal.org/user/795442"
|
||||
},
|
||||
{
|
||||
"name": "snake_plissken",
|
||||
"homepage": "https://www.drupal.org/user/3624793"
|
||||
}
|
||||
],
|
||||
"description": "Views Token Argument allows you to use token as contextual filter for Views.",
|
||||
"homepage": "http://drupal.org/project/views_argument_token",
|
||||
"support": {
|
||||
"source": "https://git.drupalcode.org/project/views_argument_token",
|
||||
"issues": "https://www.drupal.org/project/issues/views_argument_token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drupal/views_bulk_edit",
|
||||
"version": "2.6.0",
|
||||
@ -15819,6 +15885,7 @@
|
||||
"drupal/paragraphs": 20,
|
||||
"drupal/perimeter": 20,
|
||||
"drupal/selective_better_exposed_filters": 20,
|
||||
"drupal/views_argument_token": 20,
|
||||
"drupal/autocomplete_deluxe": 5,
|
||||
"drupal/bulkdelete": 20,
|
||||
"drupal/cshs": 20,
|
||||
@ -15854,5 +15921,5 @@
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.1.0"
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ module:
|
||||
user: 0
|
||||
video_embed_field: 0
|
||||
video_embed_wysiwyg: 0
|
||||
views_argument_token: 0
|
||||
views_bulk_edit: 0
|
||||
views_bulk_operations: 0
|
||||
views_conditional: 0
|
||||
|
@ -9,6 +9,7 @@ dependencies:
|
||||
- ctools
|
||||
- ctools_block
|
||||
- panels
|
||||
- popsu_link_block
|
||||
- views
|
||||
id: node-panels_variant-4
|
||||
label: Projets
|
||||
@ -147,7 +148,7 @@ variant_settings:
|
||||
third_party_settings: { }
|
||||
weight: 0
|
||||
region: first
|
||||
weight: -6
|
||||
weight: -7
|
||||
uuid: 516b4be2-1072-405a-9b08-7f5c6b629989
|
||||
context_mapping:
|
||||
entity: node
|
||||
@ -219,18 +220,6 @@ variant_settings:
|
||||
uuid: 80ceb299-5738-410f-8448-79f438df51e7
|
||||
context_mapping:
|
||||
entity: node
|
||||
9879675e-0278-482d-9ae0-bdffb5241640:
|
||||
id: 'views_block:programme_toc-block_4'
|
||||
label: ''
|
||||
provider: views
|
||||
label_display: '0'
|
||||
views_label: ''
|
||||
items_per_page: none
|
||||
region: first
|
||||
weight: -5
|
||||
uuid: 9879675e-0278-482d-9ae0-bdffb5241640
|
||||
context_mapping:
|
||||
field_programme_target_id: node
|
||||
9417d800-7b65-44cb-ac9d-a9d78249824d:
|
||||
id: 'entity_field:node:field_document'
|
||||
label: 'Pour aller plus loin'
|
||||
@ -248,6 +237,38 @@ variant_settings:
|
||||
uuid: 9417d800-7b65-44cb-ac9d-a9d78249824d
|
||||
context_mapping:
|
||||
entity: node
|
||||
7fd3954d-4223-48fd-8ed9-f719cdb706f0:
|
||||
id: 'views_block:programme_toc-block_10'
|
||||
label: ''
|
||||
provider: views
|
||||
label_display: '0'
|
||||
views_label: ''
|
||||
items_per_page: none
|
||||
region: first
|
||||
weight: -6
|
||||
uuid: 7fd3954d-4223-48fd-8ed9-f719cdb706f0
|
||||
context_mapping: { }
|
||||
b12c9988-1636-44e6-8de3-9f1d07a0561e:
|
||||
id: 'views_block:programme_toc-block_11'
|
||||
label: ''
|
||||
provider: views
|
||||
label_display: '0'
|
||||
views_label: ''
|
||||
items_per_page: none
|
||||
region: first
|
||||
weight: -5
|
||||
uuid: b12c9988-1636-44e6-8de3-9f1d07a0561e
|
||||
context_mapping: { }
|
||||
9d776e95-a9c0-4293-a62b-1689df4570cb:
|
||||
id: prog_ressource_link
|
||||
label: 'Prog ressource link'
|
||||
provider: popsu_link_block
|
||||
label_display: '0'
|
||||
region: first
|
||||
weight: -4
|
||||
uuid: 9d776e95-a9c0-4293-a62b-1689df4570cb
|
||||
link_title: Ressources
|
||||
context_mapping: { }
|
||||
id: panels_variant
|
||||
uuid: 905f0d96-a78c-40f1-bb80-f259e145444f
|
||||
label: null
|
||||
|
@ -440,6 +440,502 @@ display:
|
||||
- user.permissions
|
||||
tags:
|
||||
- 'config:field.storage.node.field_ville'
|
||||
block_10:
|
||||
display_plugin: block
|
||||
id: block_10
|
||||
display_title: 'Child Prog TOC Projets/villes Block'
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders:
|
||||
views_ef_fieldset: { }
|
||||
block_category: 'Prog TOC (Views)'
|
||||
display_description: ''
|
||||
title: 'Child Prog TOC Projets/Villes'
|
||||
defaults:
|
||||
title: false
|
||||
header: false
|
||||
filters: false
|
||||
filter_groups: false
|
||||
fields: false
|
||||
arguments: false
|
||||
relationships: false
|
||||
style: false
|
||||
row: false
|
||||
header:
|
||||
result:
|
||||
id: result
|
||||
table: views
|
||||
field: result
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
empty: false
|
||||
content: '@total Villes'
|
||||
plugin_id: result
|
||||
filters:
|
||||
status:
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
id: status
|
||||
expose:
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
group: 1
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: in
|
||||
value:
|
||||
projet: projet
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
field_programme_target_id:
|
||||
id: field_programme_target_id
|
||||
table: node__field_programme
|
||||
field: field_programme_target_id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: or
|
||||
value:
|
||||
4: '4'
|
||||
5: '5'
|
||||
6: '6'
|
||||
7: '7'
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
reduce_duplicates: false
|
||||
handler: 'default:node'
|
||||
handler_settings:
|
||||
target_bundles:
|
||||
programme: programme
|
||||
sort:
|
||||
field: _none
|
||||
direction: ASC
|
||||
auto_create: false
|
||||
auto_create_bundle: ''
|
||||
widget: select
|
||||
plugin_id: entity_reference
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
fields:
|
||||
field_ville:
|
||||
id: field_ville
|
||||
table: node__field_ville
|
||||
field: field_ville
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: true
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: target_id
|
||||
type: entity_reference_label
|
||||
settings:
|
||||
link: false
|
||||
group_column: target_id
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
plugin_id: field
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: true
|
||||
text: '{{ field_ville }}'
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
plugin_id: field
|
||||
arguments:
|
||||
field_programme_target_id:
|
||||
id: field_programme_target_id
|
||||
table: node__field_programme
|
||||
field: field_programme_target_id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
default_action: default
|
||||
exception:
|
||||
value: all
|
||||
title_enable: false
|
||||
title: All
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_type: token
|
||||
default_argument_options:
|
||||
argument: '[node:field_programme]'
|
||||
process: '1'
|
||||
and_or: ','
|
||||
all_option: '1'
|
||||
debug: 0
|
||||
default_argument_skip_url: false
|
||||
summary_options:
|
||||
base_path: ''
|
||||
count: true
|
||||
items_per_page: 25
|
||||
override: false
|
||||
summary:
|
||||
sort_order: asc
|
||||
number_of_records: 0
|
||||
format: default_summary
|
||||
specify_validation: false
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
break_phrase: false
|
||||
not: false
|
||||
plugin_id: numeric
|
||||
allow:
|
||||
configure_sorts: configure_sorts
|
||||
items_per_page: false
|
||||
offset: '0'
|
||||
pager: '0'
|
||||
hide_fields: '0'
|
||||
sort_fields: '0'
|
||||
disable_filters: '0'
|
||||
relationships: { }
|
||||
style:
|
||||
type: default
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
row:
|
||||
type: fields
|
||||
options:
|
||||
default_field_elements: true
|
||||
inline: { }
|
||||
separator: ''
|
||||
hide_empty: true
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags:
|
||||
- 'config:field.storage.node.field_ville'
|
||||
block_11:
|
||||
display_plugin: block
|
||||
id: block_11
|
||||
display_title: 'Child Prog TOC Themes Block'
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders:
|
||||
views_ef_fieldset: { }
|
||||
block_category: 'Prog TOC (Views)'
|
||||
display_description: ''
|
||||
filters:
|
||||
status:
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
id: status
|
||||
expose:
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
group: 1
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
value:
|
||||
theme: theme
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
expose:
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
field_programme_target_id:
|
||||
id: field_programme_target_id
|
||||
table: node__field_programme
|
||||
field: field_programme_target_id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: or
|
||||
value:
|
||||
3: '3'
|
||||
4: '4'
|
||||
5: '5'
|
||||
6: '6'
|
||||
7: '7'
|
||||
group: 1
|
||||
exposed: false
|
||||
expose:
|
||||
operator_id: ''
|
||||
label: ''
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: ''
|
||||
operator_limit_selection: false
|
||||
operator_list: { }
|
||||
identifier: ''
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
reduce: false
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
reduce_duplicates: false
|
||||
handler: 'default:node'
|
||||
handler_settings:
|
||||
target_bundles:
|
||||
programme: programme
|
||||
sort:
|
||||
field: _none
|
||||
direction: ASC
|
||||
auto_create: false
|
||||
auto_create_bundle: ''
|
||||
widget: select
|
||||
plugin_id: entity_reference
|
||||
defaults:
|
||||
filters: false
|
||||
filter_groups: false
|
||||
title: false
|
||||
arguments: false
|
||||
filter_groups:
|
||||
operator: AND
|
||||
groups:
|
||||
1: AND
|
||||
title: 'Child Prog TOC Themes'
|
||||
arguments:
|
||||
field_programme_target_id:
|
||||
id: field_programme_target_id
|
||||
table: node__field_programme
|
||||
field: field_programme_target_id
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
default_action: default
|
||||
exception:
|
||||
value: all
|
||||
title_enable: false
|
||||
title: All
|
||||
title_enable: false
|
||||
title: ''
|
||||
default_argument_type: token
|
||||
default_argument_options:
|
||||
argument: '[node:field_programme]'
|
||||
process: '1'
|
||||
and_or: +
|
||||
all_option: '1'
|
||||
debug: 0
|
||||
default_argument_skip_url: false
|
||||
summary_options:
|
||||
base_path: ''
|
||||
count: true
|
||||
items_per_page: 25
|
||||
override: false
|
||||
summary:
|
||||
sort_order: asc
|
||||
number_of_records: 0
|
||||
format: default_summary
|
||||
specify_validation: false
|
||||
validate:
|
||||
type: none
|
||||
fail: 'not found'
|
||||
validate_options: { }
|
||||
break_phrase: false
|
||||
not: false
|
||||
plugin_id: numeric
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags:
|
||||
- 'config:field.storage.node.field_ville'
|
||||
block_2:
|
||||
display_plugin: block
|
||||
id: block_2
|
||||
@ -846,6 +1342,8 @@ display:
|
||||
fields: false
|
||||
arguments: false
|
||||
relationships: false
|
||||
style: false
|
||||
row: false
|
||||
header:
|
||||
result:
|
||||
id: result
|
||||
@ -1147,6 +1645,19 @@ display:
|
||||
sort_fields: '0'
|
||||
disable_filters: '0'
|
||||
relationships: { }
|
||||
style:
|
||||
type: default
|
||||
options:
|
||||
grouping: { }
|
||||
row_class: ''
|
||||
default_row_class: true
|
||||
row:
|
||||
type: fields
|
||||
options:
|
||||
default_field_elements: true
|
||||
inline: { }
|
||||
separator: ''
|
||||
hide_empty: true
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
|
@ -63,7 +63,19 @@ class ProgRessourceLink extends BlockBase {
|
||||
$build = [];
|
||||
$node = \Drupal::routeMatch()->getParameter('node');
|
||||
if ($node instanceof \Drupal\node\Entity\Node) {
|
||||
// todo check if programme
|
||||
if($node->bundle() == 'programme'){
|
||||
// todo if yes get id
|
||||
$nid = $node->id();
|
||||
}else{
|
||||
// todo if not check if got field_programme
|
||||
$prog = $node->get('field_programme')->referencedEntities();
|
||||
if(count($prog)){
|
||||
$nid = $prog[0]->id();
|
||||
}
|
||||
}
|
||||
|
||||
if($nid){
|
||||
// $title = $config["link_title"];
|
||||
$token_service = \Drupal::token();
|
||||
$title = $token_service->replace($config["link_title"], array('node' => $node));
|
||||
@ -76,6 +88,7 @@ class ProgRessourceLink extends BlockBase {
|
||||
'#url' => $url
|
||||
);
|
||||
}
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user