summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Roskolii2018-08-30 23:40:47 (GMT)
committerKirill Roskolii2018-08-30 23:40:47 (GMT)
commit4594ce7afd76941398b34d8c0e4c77beabb2b3b9 (patch)
tree0b3c8cfa055b1a9a44a147874820a291ec481eb5
parentbb77121b17ff56fb4a3d00758fb69b6896a9615f (diff)
parent87c14bf3196270f70aaec0c0ceb83311a32a262d (diff)
Issue #2874755 by RoSk0, edurenye: Port user sync module.HEAD8.x-1.x
-rw-r--r--modules/crm_core_user_sync/config/install/crm_core_user_sync.settings.yml4
-rw-r--r--modules/crm_core_user_sync/config/optional/views.view.contact_to_user_management.yml715
-rw-r--r--modules/crm_core_user_sync/config/optional/views.view.user_to_contact_management.yml744
-rw-r--r--modules/crm_core_user_sync/config/schema/crm_core_user_sync.schema.yml36
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.admin.inc601
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.info.yml3
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.install61
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.links.action.yml6
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.links.menu.yml6
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.links.task.yml10
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.module625
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.pages.inc4
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.permissions.yml6
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.routing.yml49
-rw-r--r--modules/crm_core_user_sync/crm_core_user_sync.services.yml18
-rw-r--r--modules/crm_core_user_sync/src/Controller/RuleStatusController.php69
-rw-r--r--modules/crm_core_user_sync/src/CrmCoreUserSyncRelation.php188
-rw-r--r--modules/crm_core_user_sync/src/CrmCoreUserSyncRelationInterface.php62
-rw-r--r--modules/crm_core_user_sync/src/CrmCoreUserSyncRelationRules.php101
-rw-r--r--modules/crm_core_user_sync/src/Entity/Relation.php172
-rw-r--r--modules/crm_core_user_sync/src/EventSubscriber/RequestSubscriber.php95
-rw-r--r--modules/crm_core_user_sync/src/Form/RelationForm.php62
-rw-r--r--modules/crm_core_user_sync/src/Form/RuleDeleteConfirmForm.php59
-rw-r--r--modules/crm_core_user_sync/src/Form/RuleForm.php133
-rw-r--r--modules/crm_core_user_sync/src/Form/SettingsForm.php201
-rw-r--r--modules/crm_core_user_sync/src/Plugin/Block/EditOwnContactInformationBlock.php129
-rw-r--r--modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraint.php26
-rw-r--r--modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraintValidator.php45
-rw-r--r--modules/crm_core_user_sync/src/RelationInterface.php87
-rw-r--r--modules/crm_core_user_sync/src/RelationListBuilder.php112
-rw-r--r--modules/crm_core_user_sync/src/RelationViewBuilder.php23
-rw-r--r--modules/crm_core_user_sync/src/UserSyncBatch.php60
-rw-r--r--modules/crm_core_user_sync/tests/src/Kernel/CrmCoreUserSyncRelationTest.php206
-rw-r--r--modules/crm_core_user_sync/tests/src/Kernel/RelationEntityTest.php62
-rw-r--r--modules/crm_core_user_sync/tests/src/Unit/CrmCoreUserSyncRelationRulesTest.php96
-rw-r--r--modules/crm_core_user_sync/tests/src/Unit/RequestSubscriberTest.php180
-rw-r--r--modules/crm_core_user_sync/views/crm_core_user_sync.views.inc22
-rw-r--r--modules/crm_core_user_sync/views/crm_core_user_sync.views_default.inc382
-rw-r--r--modules/crm_core_user_sync/views/views_plugin_argument_default_contact_id.inc92
39 files changed, 3849 insertions, 1703 deletions
diff --git a/modules/crm_core_user_sync/config/install/crm_core_user_sync.settings.yml b/modules/crm_core_user_sync/config/install/crm_core_user_sync.settings.yml
new file mode 100644
index 0000000..cdf0fee
--- /dev/null
+++ b/modules/crm_core_user_sync/config/install/crm_core_user_sync.settings.yml
@@ -0,0 +1,4 @@
+rules: {}
+auto_sync_user_create: FALSE
+contact_load: FALSE
+contact_show: FALSE
diff --git a/modules/crm_core_user_sync/config/optional/views.view.contact_to_user_management.yml b/modules/crm_core_user_sync/config/optional/views.view.contact_to_user_management.yml
new file mode 100644
index 0000000..80fc41d
--- /dev/null
+++ b/modules/crm_core_user_sync/config/optional/views.view.contact_to_user_management.yml
@@ -0,0 +1,715 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - crm_core_contact
+ - crm_core_user_sync
+ - name
+ - user
+id: contact_to_user_management
+label: 'Contact to User Management'
+module: views
+description: ''
+tag: ''
+base_table: crm_core_individual
+base_field: individual_id
+core: 8.x
+display:
+ default:
+ display_plugin: default
+ id: default
+ display_title: Master
+ position: 0
+ display_options:
+ access:
+ type: perm
+ options:
+ perm: 'administer crm-core-user-sync'
+ cache:
+ type: tag
+ options: { }
+ query:
+ type: views_query
+ options:
+ disable_sql_rewrite: false
+ distinct: false
+ replica: false
+ query_comment: ''
+ query_tags: { }
+ exposed_form:
+ type: basic
+ options:
+ submit_button: Apply
+ reset_button: true
+ reset_button_label: Reset
+ exposed_sorts_label: 'Sort by'
+ expose_sort_order: true
+ sort_asc_label: Asc
+ sort_desc_label: Desc
+ pager:
+ type: full
+ options:
+ items_per_page: 50
+ offset: 0
+ id: 0
+ total_pages: null
+ tags:
+ previous: ‹‹
+ next: ››
+ first: '« First'
+ last: 'Last »'
+ expose:
+ items_per_page: false
+ items_per_page_label: 'Items per page'
+ items_per_page_options: '5, 10, 25, 50'
+ items_per_page_options_all: false
+ items_per_page_options_all_label: '- All -'
+ offset: false
+ offset_label: Offset
+ quantity: 9
+ style:
+ type: table
+ row:
+ type: fields
+ fields:
+ individual_id:
+ id: individual_id
+ table: crm_core_individual
+ field: individual_id
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'Individual ID'
+ exclude: false
+ 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: true
+ 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: number_unformatted
+ settings: { }
+ 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
+ entity_type: crm_core_individual
+ entity_field: individual_id
+ plugin_id: field
+ name__title:
+ id: name__title
+ table: crm_core_individual
+ field: name__title
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'Individual name'
+ exclude: false
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: family
+ type: name_default
+ settings:
+ format: default
+ markup: false
+ output: default
+ multiple: default
+ multiple_delimiter: ', '
+ multiple_and: text
+ multiple_delimiter_precedes_last: never
+ multiple_el_al_min: '3'
+ multiple_el_al_first: '1'
+ group_column: ''
+ 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
+ entity_type: crm_core_individual
+ entity_field: name
+ plugin_id: field
+ type:
+ id: type
+ table: crm_core_individual
+ field: type
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'Individual type'
+ exclude: false
+ 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: true
+ 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
+ entity_type: crm_core_individual
+ entity_field: type
+ plugin_id: field
+ id:
+ id: id
+ table: crm_core_user_sync_relation
+ field: id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: ''
+ label: 'Relation ID'
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: true
+ path: '/admin/config/crm-core/user-sync/relation/{{id}}/edit?destination=/admin/config/crm-core/user-sync/contact'
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: 'No relation'
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: value
+ type: number_unformatted
+ settings: { }
+ 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
+ entity_type: crm_core_user_sync_relation
+ entity_field: id
+ plugin_id: field
+ user_id:
+ id: user_id
+ table: crm_core_user_sync_relation
+ field: user_id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: ''
+ label: User
+ exclude: false
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: '<a href="/admin/config/crm-core/user-sync/relation/add?individual_id={{ individual_id }}&destination=/admin/config/crm-core/user-sync/contact">Add relation</a>'
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: target_id
+ type: entity_reference_label
+ settings:
+ link: true
+ 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
+ entity_type: crm_core_user_sync_relation
+ entity_field: user_id
+ plugin_id: field
+ filters:
+ id:
+ id: id
+ table: crm_core_user_sync_relation
+ field: id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: 'Have related user'
+ operator: '='
+ value:
+ min: ''
+ max: ''
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: id_op
+ label: ID
+ description: null
+ use_operator: false
+ operator: id_op
+ identifier: id
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ placeholder: null
+ min_placeholder: null
+ max_placeholder: null
+ is_grouped: true
+ group_info:
+ label: 'Have related user'
+ description: ''
+ identifier: id
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items:
+ 1:
+ title: 'Yes'
+ operator: 'not empty'
+ value:
+ value: ''
+ min: ''
+ max: ''
+ 2:
+ title: 'No'
+ operator: empty
+ value:
+ value: ''
+ min: ''
+ max: ''
+ 3:
+ title: ''
+ operator: '='
+ value:
+ value: ''
+ min: ''
+ max: ''
+ entity_type: crm_core_user_sync_relation
+ entity_field: id
+ plugin_id: numeric
+ name__given:
+ id: name__given
+ table: crm_core_individual
+ field: name__given
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: name__given_op
+ label: 'First name (given)'
+ description: ''
+ use_operator: false
+ operator: name__given_op
+ identifier: given
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ placeholder: ''
+ 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: crm_core_individual
+ entity_field: name
+ plugin_id: string
+ name__middle:
+ id: name__middle
+ table: crm_core_individual
+ field: name__middle
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: name__middle_op
+ label: 'Middle name (middle)'
+ description: ''
+ use_operator: false
+ operator: name__middle_op
+ identifier: middle
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ placeholder: ''
+ 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: crm_core_individual
+ entity_field: name
+ plugin_id: string
+ name__family:
+ id: name__family
+ table: crm_core_individual
+ field: name__family
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: name__family_op
+ label: 'Last name (family)'
+ description: ''
+ use_operator: false
+ operator: name__family_op
+ identifier: family
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ placeholder: ''
+ 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: crm_core_individual
+ entity_field: name
+ plugin_id: string
+ type:
+ id: type
+ table: crm_core_individual
+ field: type
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: in
+ value: { }
+ group: 1
+ exposed: true
+ expose:
+ operator_id: type_op
+ label: 'Individual type'
+ description: ''
+ use_operator: false
+ operator: type_op
+ identifier: type
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ 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: crm_core_individual
+ entity_field: type
+ plugin_id: bundle
+ sorts: { }
+ title: 'Contacts with related users'
+ header:
+ result:
+ id: result
+ table: views
+ field: result
+ relationship: none
+ group_type: group
+ admin_label: ''
+ empty: false
+ content: 'Displaying @start - @end of @total'
+ plugin_id: result
+ footer: { }
+ empty:
+ area:
+ id: area
+ table: views
+ field: area
+ relationship: none
+ group_type: group
+ admin_label: ''
+ empty: true
+ tokenize: false
+ content:
+ value: 'There is no individual in the system yet.'
+ format: basic_html
+ plugin_id: text
+ relationships:
+ crm_core_user_sync_relation:
+ id: crm_core_user_sync_relation
+ table: crm_core_individual
+ field: crm_core_user_sync_relation
+ relationship: none
+ group_type: group
+ admin_label: 'CRM Core User Sync relation'
+ required: false
+ entity_type: crm_core_individual
+ plugin_id: standard
+ arguments: { }
+ display_extenders: { }
+ filter_groups:
+ operator: AND
+ groups:
+ 1: AND
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - user.permissions
+ tags: { }
+ page_1:
+ display_plugin: page
+ id: page_1
+ display_title: Page
+ position: 1
+ display_options:
+ display_extenders: { }
+ path: admin/config/crm-core/user-sync/contact
+ menu:
+ type: tab
+ title: 'Contacts with related users'
+ description: ''
+ expanded: false
+ parent: crm_core_user_sync.config
+ weight: 1
+ context: '0'
+ menu_name: admin
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - user.permissions
+ tags: { }
diff --git a/modules/crm_core_user_sync/config/optional/views.view.user_to_contact_management.yml b/modules/crm_core_user_sync/config/optional/views.view.user_to_contact_management.yml
new file mode 100644
index 0000000..659da30
--- /dev/null
+++ b/modules/crm_core_user_sync/config/optional/views.view.user_to_contact_management.yml
@@ -0,0 +1,744 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - crm_core_user_sync
+ - user
+id: user_to_contact_management
+label: 'User to contact management'
+module: views
+description: ''
+tag: ''
+base_table: users_field_data
+base_field: uid
+core: 8.x
+display:
+ default:
+ display_plugin: default
+ id: default
+ display_title: Master
+ position: 0
+ display_options:
+ access:
+ type: perm
+ options:
+ perm: 'administer crm-core-user-sync'
+ cache:
+ type: tag
+ options: { }
+ query:
+ type: views_query
+ options:
+ disable_sql_rewrite: false
+ distinct: false
+ replica: false
+ query_comment: ''
+ query_tags: { }
+ exposed_form:
+ type: basic
+ options:
+ submit_button: Apply
+ reset_button: true
+ reset_button_label: Reset
+ exposed_sorts_label: 'Sort by'
+ expose_sort_order: true
+ sort_asc_label: Asc
+ sort_desc_label: Desc
+ pager:
+ type: mini
+ options:
+ items_per_page: 50
+ offset: 0
+ id: 0
+ total_pages: null
+ expose:
+ items_per_page: false
+ items_per_page_label: 'Items per page'
+ items_per_page_options: '5, 10, 25, 50'
+ items_per_page_options_all: false
+ items_per_page_options_all_label: '- All -'
+ offset: false
+ offset_label: Offset
+ tags:
+ previous: ‹‹
+ next: ››
+ style:
+ type: table
+ row:
+ type: fields
+ fields:
+ uid:
+ id: uid
+ table: users_field_data
+ field: uid
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'User ID'
+ exclude: false
+ 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: true
+ 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: number_unformatted
+ settings: { }
+ 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
+ entity_type: user
+ entity_field: uid
+ plugin_id: field
+ name:
+ id: name
+ table: users_field_data
+ field: name
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: Name
+ exclude: false
+ 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: false
+ ellipsis: false
+ 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: true
+ 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
+ entity_type: user
+ entity_field: name
+ plugin_id: field
+ mail:
+ id: mail
+ table: users_field_data
+ field: mail
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: Email
+ exclude: false
+ 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: true
+ 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: basic_string
+ settings: { }
+ 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
+ entity_type: user
+ entity_field: mail
+ plugin_id: field
+ roles_target_id:
+ id: roles_target_id
+ table: user__roles
+ field: roles_target_id
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: Roles
+ exclude: false
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ type: separator
+ separator: ', '
+ entity_type: user
+ entity_field: roles
+ plugin_id: user_roles
+ id:
+ id: id
+ table: crm_core_user_sync_relation
+ field: id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: ''
+ label: 'Relation ID'
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: true
+ path: '/admin/config/crm-core/user-sync/relation/{{id}}/edit?destination=/admin/config/crm-core/user-sync/contact'
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: 'No relation'
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: value
+ type: number_unformatted
+ settings: { }
+ 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
+ entity_type: crm_core_user_sync_relation
+ entity_field: id
+ plugin_id: field
+ individual_id:
+ id: individual_id
+ table: crm_core_user_sync_relation
+ field: individual_id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: ''
+ label: 'Individual name'
+ exclude: false
+ 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: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: '<a href="/admin/config/crm-core/user-sync/relation/add?user_id={{ uid }}&destination=/admin/config/crm-core/user-sync/user">Add relation</a>'
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: target_id
+ type: entity_reference_label
+ settings:
+ link: true
+ 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
+ entity_type: crm_core_user_sync_relation
+ entity_field: individual_id
+ plugin_id: field
+ filters:
+ uid_raw:
+ id: uid_raw
+ table: users_field_data
+ field: uid_raw
+ relationship: none
+ group_type: group
+ admin_label: 'Not anonymous'
+ operator: '!='
+ value:
+ min: ''
+ max: ''
+ value: '0'
+ group: 1
+ exposed: false
+ expose:
+ operator_id: ''
+ label: ''
+ description: ''
+ use_operator: false
+ operator: ''
+ identifier: ''
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ placeholder: ''
+ min_placeholder: ''
+ max_placeholder: ''
+ 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: user
+ plugin_id: numeric
+ id:
+ id: id
+ table: crm_core_user_sync_relation
+ field: id
+ relationship: crm_core_user_sync_relation
+ group_type: group
+ admin_label: ''
+ operator: '='
+ value:
+ min: ''
+ max: ''
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: id_op
+ label: ID
+ description: null
+ use_operator: false
+ operator: id_op
+ identifier: id
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ placeholder: null
+ min_placeholder: null
+ max_placeholder: null
+ is_grouped: true
+ group_info:
+ label: 'Have related contact'
+ description: ''
+ identifier: id
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items:
+ 1:
+ title: 'Yes'
+ operator: 'not empty'
+ value:
+ value: ''
+ min: ''
+ max: ''
+ 2:
+ title: 'No'
+ operator: empty
+ value:
+ value: ''
+ min: ''
+ max: ''
+ 3:
+ title: ''
+ operator: '='
+ value:
+ value: ''
+ min: ''
+ max: ''
+ entity_type: crm_core_user_sync_relation
+ entity_field: id
+ plugin_id: numeric
+ uid:
+ id: uid
+ table: users_field_data
+ field: uid
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: in
+ value: { }
+ group: 1
+ exposed: true
+ expose:
+ operator_id: uid_op
+ label: 'Username (autocomplete)'
+ description: ''
+ use_operator: false
+ operator: uid_op
+ identifier: uid
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ 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: user
+ entity_field: uid
+ plugin_id: user_name
+ mail:
+ id: mail
+ table: users_field_data
+ field: mail
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: mail_op
+ label: Email
+ description: ''
+ use_operator: false
+ operator: mail_op
+ identifier: email
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ placeholder: ''
+ 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: user
+ entity_field: mail
+ plugin_id: string
+ roles_target_id:
+ id: roles_target_id
+ table: user__roles
+ field: roles_target_id
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: or
+ value: { }
+ group: 1
+ exposed: true
+ expose:
+ operator_id: roles_target_id_op
+ label: Roles
+ description: ''
+ use_operator: false
+ operator: roles_target_id_op
+ identifier: roles_target_id
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ 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
+ entity_type: user
+ entity_field: roles
+ plugin_id: user_roles
+ sorts: { }
+ title: 'Users with related contacts'
+ header:
+ result:
+ id: result
+ table: views
+ field: result
+ relationship: none
+ group_type: group
+ admin_label: ''
+ empty: false
+ content: 'Displaying @start - @end of @total'
+ plugin_id: result
+ footer: { }
+ empty: { }
+ relationships:
+ crm_core_user_sync_relation:
+ id: crm_core_user_sync_relation
+ table: users_field_data
+ field: crm_core_user_sync_relation
+ relationship: none
+ group_type: group
+ admin_label: 'CRM Core User Sync Relation'
+ required: false
+ entity_type: user
+ plugin_id: standard
+ arguments: { }
+ display_extenders: { }
+ filter_groups:
+ operator: AND
+ groups:
+ 1: AND
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - user.permissions
+ tags: { }
+ page_1:
+ display_plugin: page
+ id: page_1
+ display_title: Page
+ position: 1
+ display_options:
+ display_extenders: { }
+ path: admin/config/crm-core/user-sync/user
+ menu:
+ type: tab
+ title: 'Users with related contacts'
+ description: ''
+ expanded: false
+ parent: crm_core_user_sync.config
+ weight: 2
+ context: '0'
+ menu_name: admin
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - user.permissions
+ tags: { }
diff --git a/modules/crm_core_user_sync/config/schema/crm_core_user_sync.schema.yml b/modules/crm_core_user_sync/config/schema/crm_core_user_sync.schema.yml
new file mode 100644
index 0000000..713554a
--- /dev/null
+++ b/modules/crm_core_user_sync/config/schema/crm_core_user_sync.schema.yml
@@ -0,0 +1,36 @@
+# Schema for the configuration files of the CRM Core User Synchronization module.
+crm_core_user_sync.settings:
+ type: config_object
+ label: 'CRM Core User Synchronization settings'
+ mapping:
+ rules:
+ type: sequence
+ label: 'Rules'
+ sequence:
+ type: crm_core_user_sync.rule
+ auto_sync_user_create:
+ type: boolean
+ label: 'Auto sync user create'
+ contact_load:
+ type: boolean
+ label: 'Load contact related to the current user'
+ contact_show:
+ type: boolean
+ label: 'Show related contact information on the user profile'
+
+crm_core_user_sync.rule:
+ type: mapping
+ label: 'Rule'
+ mapping:
+ role:
+ type: string
+ label: 'Role'
+ contact_type:
+ type: string
+ label: 'Contact type'
+ enabled:
+ type: boolean
+ label: 'Enabled'
+ weight:
+ type: integer
+ label: 'Weight'
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.admin.inc b/modules/crm_core_user_sync/crm_core_user_sync.admin.inc
deleted file mode 100644
index 79a0f2a..0000000
--- a/modules/crm_core_user_sync/crm_core_user_sync.admin.inc
+++ /dev/null
@@ -1,601 +0,0 @@
-<?php
-
-use Drupal\crm_core_contact\Entity\ContactType;
-use Drupal\crm_core_contact\Entity\Contact;
-use Drupal\relation\Entity\Relation;
-
-/**
- * Admin form.
- */
-function crm_core_user_sync_admin_form($form, &$form_state) {
- $form = array();
-
- $roles = user_roles(TRUE);
- $types = ContactType::loadMultiple();
-
- $types_options = array();
- foreach ($types as $key => $type) {
- $types_options[$key] = $type->name;
- }
-
- $rules = variable_get('crm_core_user_sync_rules', array());
- uasort($rules, 'crm_core_user_sync_weight_cmp');
-
- $form['crm_core_user_sync_description'] = array(
- '#markup' => t('CRM Core User Synchronization can automatically create contact records associated with user accounts under certain conditions.')
- );
-
- $form['crm_core_user_sync_rules'] = array(
- '#type' => 'container'
- );
-
- $form['#tree'] = TRUE;
- foreach ($rules as $key => $rule) {
- $form['crm_core_user_sync_rules'][$key]['role'] = array('#markup' => $roles[$rule['rid']]);
- $form['crm_core_user_sync_rules'][$key]['contact_type'] = array('#markup' => $types_options[$rule['contact_type']]);
- $form['crm_core_user_sync_rules'][$key]['enabled'] = array('#markup' => $rule['enabled'] ? 'Yes' : 'No');
- $form['crm_core_user_sync_rules'][$key]['weight'] = array(
- '#type' => 'weight',
- '#title_display' => 'invisible',
- '#default_value' => $rule['weight'],
- );
-
- $form['crm_core_user_sync_rules'][$key]['operations'] = array(
- '#theme' => 'links',
- '#links' => array(),
- '#attributes' => array('class' => array('links', 'inline')),
- );
-
- $links = & $form['crm_core_user_sync_rules'][$key]['operations']['#links'];
- $path = 'admin/config/crm-core/user-sync/' . $key;
- $links['edit'] = array('title' => 'Edit', 'href' => $path . '/edit');
- $links['delete'] = array('title' => 'Delete', 'href' => $path . '/delete');
-
- if ($rule['enabled']) {
- $links['disable'] = array(
- 'title' => 'Disable',
- 'href' => $path . '/disable'
- );
- }
- else {
- $links['enable'] = array(
- 'title' => 'Enable',
- 'href' => $path . '/enable'
- );
- }
- }
-
- $form['crm_core_user_sync_auto_sync_user_create'] = array(
- '#type' => 'checkbox',
- '#title' => t('Automatically create an associated contact when account is created'),
- '#description' => t('When checked, this checkbox will automatically create new contacts when a new user account is created according to rules listed above. Rules will be processed in order until a new contact is created.'),
- '#default_value' => variable_get('crm_core_user_sync_auto_sync_user_create', 1),
- );
-
- $form['crm_core_user_sync_wrapper'] = array(
- '#type' => 'fieldset',
- '#title' => t('Sync Current Users'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- );
- $form['crm_core_user_sync_wrapper']['user_sync'] = array(
- '#type' => 'submit',
- '#value' => t('Synchronize Users'),
- '#submit' => array('crm_core_user_sync_admin_form_user_sync_submit'),
- );
- $form['crm_core_user_sync_wrapper']['description_wrapper'] = array(
- '#type' => 'container',
- );
- $form['crm_core_user_sync_wrapper']['description_wrapper']['description'] = array(
- '#type' => 'item',
- '#markup' => t('Click this button to apply user synchronization rules to all user accounts that are currently not'
- . ' associated with a contact in the system. It will create an associated contact record for each user according'
- . ' to the rules configured above. Warning: this cannot be undone.'),
- );
-
- $form['actions'] = array('#type' => 'actions');
- $form['actions']['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Save changes')
- );
-
- return $form;
-}
-
-/**
- * Validation callback.
- */
-function crm_core_user_sync_admin_form_validate($form, &$form_state) {
-}
-
-/**
- * Submit callback. Handles synchronization changes.
- */
-function crm_core_user_sync_admin_form_submit($form, &$form_state) {
- $rules = variable_get('crm_core_user_sync_rules', array());
-
- foreach ($form_state['values']['crm_core_user_sync_rules'] as $key => $values) {
- if (!empty($values['weight'])) {
- $rules[$key]['weight'] = $values['weight'];
- }
- }
-
- uasort($rules, 'crm_core_user_sync_weight_cmp');
-
- variable_set('crm_core_user_sync_rules', $rules);
-
- variable_set('crm_core_user_sync_auto_sync_user_create', $form_state['values']['crm_core_user_sync_auto_sync_user_create']);
-
- drupal_set_message('Your changes have been saved');
-}
-
-/**
- * Theme implementation of the crm_core_user_sync_settings form.
- */
-function theme_crm_core_user_sync_admin_form($variables) {
- $form = $variables['form'];
-
- $rows = array();
-
- foreach (element_children($form['crm_core_user_sync_rules']) as $key) {
- $form['crm_core_user_sync_rules'][$key]['weight']['#attributes']['class'] = array('crm-user-sync-settings-order-weight');
- $rows[] = array(
- 'data' => array(
- drupal_render($form['crm_core_user_sync_rules'][$key]['role']),
- drupal_render($form['crm_core_user_sync_rules'][$key]['contact_type']),
- drupal_render($form['crm_core_user_sync_rules'][$key]['enabled']),
- drupal_render($form['crm_core_user_sync_rules'][$key]['weight']),
- drupal_render($form['crm_core_user_sync_rules'][$key]['operations']),
- ),
- 'class' => array('draggable'),
- );
- }
-
- $header = array(
- t('Role'),
- t('Contact Type'),
- t('Enabled'),
- t('Weight'),
- t('Operations')
- );
- $form['crm_core_user_sync_rules']['content']['#markup'] = theme('table', array(
- 'header' => $header,
- 'rows' => $rows,
- 'attributes' => array('id' => 'crm-user-sync-settings-order')
- ));
- $output = drupal_render_children($form);
-
- drupal_add_tabledrag('crm-user-sync-settings-order', 'order', 'sibling', 'crm-user-sync-settings-order-weight');
-
- return $output;
-}
-
-/**
- * Add new rule form.
- */
-function crm_core_user_sync_admin_edit_rule_form($form, &$form_state, $rule_key = NULL) {
- $form = array();
-
- $roles = array('' => t('- Select -')) + user_roles(TRUE);
- $types = ContactType::loadMultiple();
-
- $types_options = array('' => t('- Select -'));
- foreach ($types as $key => $type) {
- $types_options[$key] = $type->name;
- }
-
- $rules = variable_get('crm_core_user_sync_rules', array());
-
- if (isset($rule_key) && isset($rules[$rule_key])) {
- $form_state['rule'] = $rule = $rules[$rule_key];
- $form_state['rule_key'] = $rule_key;
- drupal_set_title(t('Edit user syncrhonzation rule'));
- }
- else {
- drupal_set_title(t('Add user syncrhonzation rule'));
- }
-
- $form['rid'] = array(
- '#type' => 'select',
- '#title' => t('User Role'),
- '#options' => $roles,
- '#default_value' => isset($rule['rid']) ? $rule['rid'] : '',
- '#required' => TRUE,
- );
-
- $form['contact_type'] = array(
- '#type' => 'select',
- '#title' => t('Contact Type'),
- '#options' => $types_options,
- '#default_value' => isset($rule['contact_type']) ? $rule['contact_type'] : '',
- '#required' => TRUE,
- );
-
- $form['weight'] = array(
- '#type' => 'weight',
- '#title' => t('Weight'),
- '#default_value' => isset($rule['weight']) ? $rule['weight'] : 0,
- );
-
- $form['enabled'] = array(
- '#type' => 'checkbox',
- '#title' => t('Enabled'),
- '#default_value' => isset($rule['enabled']) ? $rule['enabled'] : TRUE,
- '#description' => 'When checked, this rule will be used to synchronize user accounts. When unchecked, it will be ignored throughout the system.'
- );
-
- $form['actions'] = array('#type' => 'actions');
- $form['actions']['save'] = array('#type' => 'submit', '#value' => t('Save'));
- $form['actions']['cancel'] = array(
- '#type' => 'submit',
- '#value' => t('Cancel')
- );
-
- return $form;
-}
-
-/**
- * Submit handler for add new rule form.
- */
-function crm_core_user_sync_admin_edit_rule_form_submit($form, &$form_state) {
- if ($form_state['values']['op'] == $form['actions']['save']['#value']) {
- $rules = variable_get('crm_core_user_sync_rules', array());
-
- $rule = array(
- 'rid' => $form_state['values']['rid'],
- 'contact_type' => $form_state['values']['contact_type'],
- 'weight' => $form_state['values']['weight'],
- 'enabled' => $form_state['values']['enabled'],
- );
-
- if (isset($form_state['rule_key'])) {
- $rules[$form_state['rule_key']] = $rule;
- }
- else {
- $rules[] = $rule;
- }
-
- uasort($rules, 'crm_core_user_sync_weight_cmp');
- variable_set('crm_core_user_sync_rules', $rules);
-
- $form_state['redirect'] = 'admin/config/crm-core/user-sync';
- drupal_set_message(t('User syncrhonzation rule has been saved.'));
- }
- elseif ($form_state['values']['op'] == $form['actions']['cancel']['#value']) {
- $form_state['redirect'] = 'admin/config/crm-core/user-sync';
- }
-}
-
-/**
- * Delete rule form.
- */
-function crm_core_user_sync_admin_delete_rule_form($form, &$form_state, $rule_key) {
- $form['rule_key'] = array(
- '#type' => 'value',
- '#value' => $rule_key,
- );
-
- $question = t('Are you sure you want to delete the user synchronization rule?');
- $path = 'admin/config/crm-core/user-sync';
-
- return confirm_form($form, $question, $path);
-}
-
-/**
- * Submission handler for delete rule form.
- */
-function crm_core_user_sync_admin_delete_rule_form_submit($form, &$form_state) {
- $rule_key = $form_state['values']['rule_key'];
-
- $rules = variable_get('crm_core_user_sync_rules', array());
- unset($rules[$rule_key]);
- variable_set('crm_core_user_sync_rules', $rules);
-
- $form_state['redirect'] = 'admin/config/crm-core/user-sync';
- drupal_set_message(t('User syncrhonzation rule has been deleted.'));
-}
-
-/**
- * Change status callback.
- */
-function crm_core_user_sync_admin_update_rule_status($rule_key, $status) {
- $rules = variable_get('crm_core_user_sync_rules', array());
- $rules[$rule_key]['enabled'] = $status;
- variable_set('crm_core_user_sync_rules', $rules);
-
- drupal_goto('admin/config/crm-core/user-sync');
-}
-
-/**
- * Contact->User relation edit form.
- */
-function crm_core_user_sync_edit_relation_form($form, &$form_state, $relation) {
- if (empty($relation)) {
- drupal_set_title('Create a new relation');
-
- if (!empty($_GET['uid'])) {
- $user = user_load($_GET['uid']);
- $disabled_user_field = !empty($user);
- }
-
- if (!empty($_GET['contact_id'])) {
- $contact = Contact::load($_GET['contact_id']);
- $disabled_contact_field = !empty($contact);
- }
- }
- else {
- drupal_set_title('Edit relation');
-
- if (!empty($relation->endpoints[LANGUAGE_NONE][0]['entity_id'])) {
- $user = user_load($relation->endpoints[LANGUAGE_NONE][0]['entity_id']);
- }
-
- if (!empty($relation->endpoints[LANGUAGE_NONE][1]['entity_id'])) {
- $contact = Contact::load($relation->endpoints[LANGUAGE_NONE][1]['entity_id']);
- }
- }
-
- $form['relation'] = array(
- '#type' => 'value',
- '#value' => $relation,
- );
-
- $form['description'] = array(
- '#type' => 'item',
- '#markup' => t('You can edit the details of a contact record to user account relationship using the following form.'),
- );
-
- $form['contact'] = array(
- '#title' => t('Contact record'),
- '#type' => 'textfield',
- '#default_value' => empty($contact) ? '' : $contact->label() . " [contact_id:{$contact->contact_id}]",
- '#disabled' => empty($disabled_contact_field) ? FALSE : TRUE,
- '#autocomplete_path' => 'admin/config/crm-core/user-sync/contact-to-user-management/contact-autocomplete',
- );
-
- $form['user'] = array(
- '#title' => t('User record'),
- '#type' => 'textfield',
- '#default_value' => empty($user) ? '' : $user->name . " [uid:{$user->uid}]",
- '#disabled' => empty($disabled_user_field) ? FALSE : TRUE,
- '#autocomplete_path' => 'admin/config/crm-core/user-sync/contact-to-user-management/user-autocomplete',
- );
-
- $form['actions'] = array('#type' => 'actions');
-
- $form['actions']['save'] = array(
- '#type' => 'submit',
- '#value' => t('Save'),
- );
-
- if (!empty($relation)) {
- $form['actions']['delete'] = array(
- '#type' => 'submit',
- '#value' => t('Delete'),
- );
- }
-
- $form['actions']['cancel'] = array(
- '#markup' => l(t('Cancel'), 'admin/config/crm-core/user-sync/contact-to-user-management'),
- );
-
- return $form;
-}
-
-/**
- * Validate callback on edit form.
- */
-function crm_core_user_sync_edit_relation_form_validate($form, &$form_state) {
- if ($form_state['values']['op'] == $form['actions']['save']['#value']) {
- $user = _crm_core_user_sync_get_entity_id_from_text($form_state['values']['user'], 'user');
- $contact = _crm_core_user_sync_get_entity_id_from_text($form_state['values']['contact'], 'crm_core_contact');
-
- if (empty($user)) {
- form_set_error('user', t('Could not load a user account.'));
- }
-
- if (empty($contact)) {
- form_set_error('contact', t('Could not load a contact.'));
- }
-
- if (empty($user) || empty($contact)) {
- return;
- }
-
- // Check if the same user->contact relation exists when adding or editing relation.
- if (crm_core_user_sync_get_contact_from_uid($user->uid) && (empty($form_state['values']['relation']) ||
- $form_state['values']['relation']->endpoints[LANGUAGE_NONE][0]['entity_id'] != $user->uid)
- ) {
- form_set_error('user', t('The user account has been already synchronized.'));
- }
-
- // Check if the same user->contact relation exists when adding or editing relation.
- if (crm_core_user_sync_get_user_from_contact_id($contact->contact_id) && (empty($form_state['values']['relation']) ||
- $form_state['values']['relation']->endpoints[LANGUAGE_NONE][1]['entity_id'] != $contact->contact_id)
- ) {
- form_set_error('contact', t('The contact record has been already synchronized.'));
- }
- }
-}
-
-/**
- * Submit callback on edit form.
- */
-function crm_core_user_sync_edit_relation_form_submit($form, &$form_state) {
- if ($form_state['values']['op'] == $form['actions']['save']['#value']) {
- $user = _crm_core_user_sync_get_entity_id_from_text($form_state['values']['user'], 'user');
- $contact = _crm_core_user_sync_get_entity_id_from_text($form_state['values']['contact'], 'crm_core_contact');
-
- if (!empty($form_state['values']['relation'])) {
- $relation = $form_state['values']['relation'];
-
- $relation->endpoints[LANGUAGE_NONE][0]['entity_id'] = $user->uid;
- $relation->endpoints[LANGUAGE_NONE][1]['entity_id'] = $contact->contact_id;
-
- $relation->save();
- }
- else {
- $relation = Relation::create(array(
- 'relation_type' => 'crm_core_user_sync',
- array(
- array('entity_type' => 'user', 'entity_id' => $user->uid),
- array(
- 'entity_type' => 'crm_core_contact',
- 'entity_id' => $contact->contact_id,
- ),
- ),
- ));
- $relation->save();
- }
-
- $form_state['redirect'] = 'admin/config/crm-core/user-sync/contact-to-user-management';
- drupal_set_message('Relation has been saved.');
- }
- elseif ($form_state['values']['op'] == $form['actions']['delete']['#value']) {
- $relation = $form_state['values']['relation'];
- $form_state['redirect'] = 'admin/config/crm-core/user-sync/contact-to-user-management/' . $relation->id() . '/delete';
- }
-}
-
-/**
- * User autocomplete for user->contact relation form.
- */
-function crm_core_user_sync_user_autocomplete($search_string) {
- $matches = array();
-
- $query = db_select('users', 'user');
- $on_cond = "endpoints.endpoints_entity_type = 'user' AND user.uid = endpoints.endpoints_entity_id";
- $query->leftJoin('field_data_endpoints', 'endpoints', $on_cond);
- $query->addField('user', 'uid');
- $query->isNull('endpoints_entity_id');
- $query->condition('name', $search_string . '%', 'LIKE');
- watchdog('debug', $query->__toString());
- $uids = $query->range(0, 20)->execute()->fetchCol();
-
- if (!empty($uids)) {
- $users = entity_load('user', $uids);
- foreach ($users as $user) {
- $matches[$user->name . " [uid:$user->uid]"] = $user->name;
- }
- }
-
- drupal_json_output($matches);
-}
-
-/**
- * User autocomplete for user->contact relation form.
- */
-function crm_core_user_sync_contact_autocomplete($search_string) {
- $matches = array();
-
- $query = new EntityFieldQuery;
- $query->entityCondition('entity_type', 'crm_core_contact')
- ->range(0, 20);
-
- $query->addMetaData('match', $search_string)
- ->addTag(variable_get('crm_core_contact_search_query_tag', 'crm_core_contact_search'));
- $query->addMetaData('user', FALSE);
-
- $result = $query->execute();
- if (!empty($result)) {
- $contacts = entity_load('crm_core_contact', array_keys($result['crm_core_contact']));
- foreach ($contacts as $contact) {
- $crm_core_contact_title = $contact->label();
- $matches[$crm_core_contact_title . " [contact_id:$contact->contact_id]"] = $crm_core_contact_title;
- }
- }
- drupal_json_output($matches);
-}
-
-/**
- * Delete relation form.
- */
-function crm_core_user_sync_delete_relation_form($form, &$form_state, $relation) {
- $form['relation'] = array(
- '#type' => 'value',
- '#value' => $relation,
- );
-
- $question = t('Are you sure you want to delete the relation?');
- $path = 'admin/config/crm-core/user-sync/contact-to-user-management';
-
- return confirm_form($form, $question, $path);
-}
-
-/**
- * Submission handler for delete relation form.
- */
-function crm_core_user_sync_delete_relation_form_submit($form, &$form_state) {
- $relation = $form_state['values']['relation'];
-
- Relation::load($relation->id())->delete();
-
- $form_state['redirect'] = 'admin/config/crm-core/user-sync/contact-to-user-management';
- drupal_set_message(t('Relation has been deleted.'));
-}
-
-/**
- * Submit callback. Handles user synchronization.
- */
-function crm_core_user_sync_admin_form_user_sync_submit($form, &$form_state) {
- $operations[] = array('_crm_core_user_sync_batch_processing', array());
- $batch = array(
- 'operations' => $operations,
- 'title' => t('Processing user synchronization'),
- 'finished' => '_crm_core_user_sync_batch_processing_finished',
- 'file' => drupal_get_path('module', 'crm_core_user_sync') . '/crm_core_user_sync.admin.inc'
- );
- batch_set($batch);
-}
-
-/**
- * Helper function for batch processing of users synchronization.
- *
- * @param $uid
- * User id for which contact should be created.
- */
-function _crm_core_user_sync_batch_processing(&$context) {
- $query = db_select('users', 'users');
- $query->leftJoin('field_data_endpoints', 'endpoints', "endpoints.endpoints_entity_id = users.uid AND endpoints.endpoints_entity_type = 'user'");
- $query->addField('users', 'uid');
- $query->addField('endpoints', 'entity_id', 'rid');
- $query->condition('users.status', "'0'", '<>');
- $query->isNull('endpoints.entity_id');
-
- if (empty($context['sandbox'])) {
- $context['sandbox'] = array();
- $count_query = $query->countQuery();
- $context['sandbox']['max'] = $count_query->execute()->fetchField();
- $context['sandbox']['progress'] = 0;
- }
- // Limit users quantity to process per request.
- $limit = 20;
- $uids = $query->range(0, $limit)->execute()->fetchCol();
- $users = user_load_multiple($uids);
- foreach ($users as $user) {
- crm_core_user_sync_sync($user);
- $context['sandbox']['progress']++;
- }
-
- if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
- $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
- }
- else {
- $context['results']['synced'] = $context['sandbox']['max'];
- }
-}
-
-/**
- * Helper to set message to user when batch processing finished.
- */
-function _crm_core_user_sync_batch_processing_finished($success, $results, $operations) {
- if ($success) {
- drupal_set_message(t('@count users have been associated with contacts.', array('@count' => $results['synced'])));
- }
- else {
- drupal_set_message(t('Something went wrong. Please check !dblog.', array(
- '!dblog' =>
- l(t('Recent log messages'), 'admin/reports/dblog')
- )), 'error');
- }
-}
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.info.yml b/modules/crm_core_user_sync/crm_core_user_sync.info.yml
index 16ab539..000e223 100644
--- a/modules/crm_core_user_sync/crm_core_user_sync.info.yml
+++ b/modules/crm_core_user_sync/crm_core_user_sync.info.yml
@@ -1,6 +1,6 @@
name: CRM Core User Synchronization
type: module
-description: 'Synchronizes crm contacts with users.'
+description: 'Synchronizes CRM contacts with users.'
package: CRM Core
core: 8.x
@@ -8,4 +8,3 @@ configure: crm_core_user_sync.sync
dependencies:
- crm_core:crm_core_contact
- - relation:relation
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.install b/modules/crm_core_user_sync/crm_core_user_sync.install
deleted file mode 100644
index 0e7e698..0000000
--- a/modules/crm_core_user_sync/crm_core_user_sync.install
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-use Drupal\relation\Entity\RelationType;
-
-/**
- * Implements hook_install()
- */
-function crm_core_user_sync_install() {
- $t = get_t();
-
- // Add relation type
- $relation_type_info = array(
- 'relation_type' => 'crm_core_user_sync',
- 'label' => $t('Contact'),
- 'reverse_label' => $t('User'),
- 'source_bundles' => array('user:user'),
- 'target_bundles' => array('crm_core_contact:*'),
- 'r_unique' => TRUE,
- 'directional' => TRUE,
- );
- RelationType::create($relation_type_info)->save();
-}
-
-/**
- * Implements hook_uninstall()
- */
-function crm_core_user_sync_uninstall() {
- relation_type_delete('crm_core_user_sync');
-
- variable_del('crm_core_user_sync_rules');
- variable_del('crm_core_user_sync_auto_sync_user_create');
-}
-
-/**
- * Implements hook_enable().
- */
-function crm_core_user_sync_enable() {
- $menu_items = array(
- array(
- 'link_path' => 'admin/config/crm-core/user-sync',
- 'link_title' => 'Administer User Synchronization',
- 'menu_name' => 'crm-core-admin-menu',
- ),
- );
- foreach ($menu_items as $item) {
- menu_link_save($item);
- }
-}
-
-/**
- * Implements hook_disable().
- */
-function crm_core_user_sync_disable() {
- //Remove links from crm-core-menu and crm-core-admin-menu.
- $conditions = array(
- 'crm-core-admin-menu' => array(
- 'admin/config/crm-core/user-sync'
- ),
- );
- crm_core_ui_remove_links($conditions);
-}
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.links.action.yml b/modules/crm_core_user_sync/crm_core_user_sync.links.action.yml
new file mode 100644
index 0000000..61d2a96
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.links.action.yml
@@ -0,0 +1,6 @@
+crm_core_user_sync.rule.new:
+ route_name: crm_core_user_sync.rule.new
+ title: Add new synchronization rule
+ weight: 1
+ appears_on:
+ - crm_core_user_sync.config
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.links.menu.yml b/modules/crm_core_user_sync/crm_core_user_sync.links.menu.yml
new file mode 100644
index 0000000..efa1a02
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.links.menu.yml
@@ -0,0 +1,6 @@
+crm_core_user_sync.config:
+ title: 'User Synchronization'
+ description: 'Manage CRM Core user synchronization settings.'
+ route_name: crm_core_user_sync.config
+ parent: crm_core.config
+ weight: 0
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.links.task.yml b/modules/crm_core_user_sync/crm_core_user_sync.links.task.yml
new file mode 100644
index 0000000..f3a38ff
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.links.task.yml
@@ -0,0 +1,10 @@
+crm_core_user_sync.config:
+ title: Configuration
+ route_name: crm_core_user_sync.config
+ base_route: crm_core_user_sync.config
+
+crm_core_user_sync.relations:
+ title: Relations
+ route_name: entity.crm_core_user_sync_relation.collection
+ base_route: crm_core_user_sync.config
+ weight: 3
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.module b/modules/crm_core_user_sync/crm_core_user_sync.module
index 3b36245..50693fa 100644
--- a/modules/crm_core_user_sync/crm_core_user_sync.module
+++ b/modules/crm_core_user_sync/crm_core_user_sync.module
@@ -1,581 +1,128 @@
<?php
-use Drupal\relation\Entity\Relation;
-use Drupal\crm_core_contact\Entity\Individual;
-
-/**
- * Implements hook_menu()
- */
-function crm_core_user_sync_menu() {
- $items = array();
- if (\Drupal::moduleHandler()->moduleExists('crm_core_ui')) {
- $items['admin/config/crm-core/user-sync'] = array(
- 'title' => 'User Synchronization',
- 'description' => 'Manage CRM Core user synchronization settings',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_admin_form'),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'weight' => 0,
- );
-
- $items['admin/config/crm-core/user-sync/settings'] = array(
- 'title' => 'User Synchronization Settings',
- 'weight' => -10,
- 'type' => MENU_DEFAULT_LOCAL_TASK,
- );
-
- $items['admin/config/crm-core/user-sync/new'] = array(
- 'title' => 'Add a new rule',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_admin_edit_rule_form', NULL),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_LOCAL_ACTION,
- );
-
- $items['admin/config/crm-core/user-sync/%/edit'] = array(
- 'title' => 'Edit a rule',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_admin_edit_rule_form', 4),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_CALLBACK,
- );
-
- $items['admin/config/crm-core/user-sync/%/delete'] = array(
- 'title' => 'Delete a rule',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_admin_delete_rule_form', 4),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- );
-
- $items['admin/config/crm-core/user-sync/%/enable'] = array(
- 'title' => 'Delete a rule',
- 'page callback' => 'crm_core_user_sync_admin_update_rule_status',
- 'page arguments' => array(4, TRUE),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- );
-
- $items['admin/config/crm-core/user-sync/%/disable'] = array(
- 'title' => 'Delete a rule',
- 'page callback' => 'crm_core_user_sync_admin_update_rule_status',
- 'page arguments' => array(4, FALSE),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- );
-
- $items['admin/config/crm-core/user-sync/contact-to-user-management/add'] = array(
- 'title' => 'Add a new relation',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_edit_relation_form', NULL),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_LOCAL_ACTION,
- );
-
- $items['admin/config/crm-core/user-sync/contact-to-user-management/%relation/edit'] = array(
- 'title' => 'Edit relation',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_edit_relation_form', 5),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_CALLBACK,
- );
-
- $items['admin/config/crm-core/user-sync/contact-to-user-management/%relation/delete'] = array(
- 'title' => 'Delete relation',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('crm_core_user_sync_delete_relation_form', 5),
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_CALLBACK,
- );
-
- $items['admin/config/crm-core/user-sync/contact-to-user-management/user-autocomplete/%'] = array(
- 'page callback' => 'crm_core_user_sync_user_autocomplete',
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_CALLBACK,
- );
-
- $items['admin/config/crm-core/user-sync/contact-to-user-management/contact-autocomplete/%'] = array(
- 'page callback' => 'crm_core_user_sync_contact_autocomplete',
- 'access arguments' => array('administer user-sync'),
- 'file' => 'crm_core_user_sync.admin.inc',
- 'type' => MENU_CALLBACK,
- );
- }
-
- return $items;
-}
-
/**
- * Implements hook_permission()
+ * @file
+ * CRM Core User Synchronization module.
*/
-function crm_core_user_sync_permission() {
- return array(
- 'administer user-sync' => array(
- 'title' => t('Administer User Synchronization'),
- 'description' => t('Access to configuration pages for User Synchronization'),
- ),
- 'edit own contact information' => array(
- 'title' => t('Edit own contact information'),
- 'description' => t('Allows user to edit his/her own contact record from the user profile form'),
- ),
- );
-}
-
-/**
- * Implements hook_views_api().
- */
-function crm_core_user_sync_views_api() {
- return array(
- 'api' => 2,
- 'path' => drupal_get_path('module', 'crm_core_user_sync') . '/views',
- );
-}
-
-/**
- * Implements hook_user_insert()
- */
-function crm_core_user_sync_user_insert(&$edit, $account, $category) {
- if (variable_get('crm_core_user_sync_auto_sync_user_create', 1)) {
- crm_core_user_sync_sync($account);
- }
-}
-
-/**
- * Implements hook_user_update()
- */
-function crm_core_user_sync_user_update(&$edit, $account, $category) {
- // user update only ensures that for the given user it should have a corresponding
- // contact record associated with it.
- $related_contact = _crm_core_user_sync_get_related_entity('user', $account->uid, 'crm_core_user_sync');
- if (empty($related_contact)) {
- if (variable_get('crm_core_user_sync_auto_sync_user_create', 1)) {
- crm_core_user_sync_sync($account);
- }
- }
-}
-
-/**
- * Implements hook_user_delete()
- */
-function crm_core_user_sync_user_delete($account) {
- // @TODO: For now we delete the relation only.
- // We should handle this properly in hook_user_cancel() regarding other
- // cancellation methods.
- $query = relation_query('user', $account->uid);
- $query->propertyCondition('relation_type', 'crm_core_user_sync');
- $query->propertyCondition('arity', 2);
- $relations = $query->execute();
- $relation_ids = array();
- foreach ($relations as $relation) {
- $relation_ids[] = $relation->relation_id;
- }
- if (!empty($relation_ids)) {
- \Drupal::entityTypeManager()->getStorage('relation')
- ->delete(Relation::loadMultiple($relation_ids));
- }
-}
-
-/**
- * Returns corresponding contact type for user account to synchronize with.
- */
-function crm_core_user_sync_get_contact_type_for_account($account) {
- $rules = variable_get('crm_core_user_sync_rules', array());
- uasort($rules, 'crm_core_user_sync_weight_cmp');
-
- foreach ($rules as $rule) {
- if ($rule['enabled'] && in_array($rule['rid'], array_keys($account->roles))) {
- return $rule['contact_type'];
- }
- }
-
- return FALSE;
-}
-
-/**
- * Checks if user->contact relation exists.
- */
-function crm_core_user_sync_exists($uid, $contact_id) {
- if (is_object($uid)) {
- $uid = $uid->uid;
- }
-
- if (is_object(($contact_id))) {
- $contact_id = $contact_id->contact_id;
- }
-
- return \Drupal::service('entity.repository.relation')->relationExists(array(
- array('entity_type' => 'user', 'entity_id' => $uid),
- array('entity_type' => 'crm_core_contact', 'entity_id' => $contact_id)
- ), 'crm_core_user_sync');
-}
-
-/**
- * Validates user amd contact.
- *
- * @param $account to be synchronized
- * @param $contact_type to be associated with $account. It can be contact object either.
- */
-function crm_core_user_sync_validate($account, $contact_type) {
- if (is_object($contact_type)) {
- $contact_type = $contact_type->type;
- }
-
- $rules = variable_get('crm_core_user_sync_rules', array());
-
- foreach ($rules as $rule) {
- if ($rule['enabled'] && in_array($rule['rid'], array_keys($account->roles))
- && $rule['contact_type'] == $contact_type) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- * Synchronizes user amd contact.
- *
- * @param $account to be synchronized
- * @param $contact to be associated with $account
- *
- * @return contact object
- */
-function crm_core_user_sync_sync($account, $contact = NULL) {
- // Property crm_core_no_auto_sync skips creation of contact.
- if (empty($contact) && empty($account->crm_core_no_auto_sync)) {
-
- // Get corresponding contact type
- $contact_type = crm_core_user_sync_get_contact_type_for_account($account);
-
- if (!$contact_type) {
- return;
- }
-
- // Create the contact.
- $contact = Individual::create(array('type' => $contact_type));
- $contact->setOwner($account->uid);
-
- // For now we just add the name.
- $contact_name = field_info_instance('crm_core_contact', 'contact_name', $contact_type);
- if (!empty($contact_name)) {
- $contact->contact_name[LANGUAGE_NONE][0] = array(
- 'title' => '',
- 'family' => '',
- 'generational' => '',
- 'credentials' => '',
- 'given' => $account->name,
- );
- }
-
- $contact->save();
- }
- else {
- $contact_type = $contact->type;
-
- // Check if contact can be synchronized to a contact.
- if (!crm_core_user_sync_validate($account, $contact)) {
- return;
- }
- }
-
- // Check if crm_core_user_sync relation exists for any of endpoint.
- if (crm_core_user_sync_get_contact_from_uid($account->uid) ||
- crm_core_user_sync_get_user_from_contact_id($contact->contact_id)) {
- return;
- }
-
- // Create the relation
- $endpoints = array(
- array(
- 'entity_type' => 'user',
- 'entity_bundle' => 'user',
- 'entity_id' => $account->uid,
- ),
- array(
- 'entity_type' => 'crm_core_contact',
- 'entity_bundle' => $contact_type,
- 'entity_id' => $contact->contact_id,
- ),
- );
-
- $relation = Relation::create(['relation_type' => 'crm_core_user_sync', 'endpoints' => $endpoints])->save();
- watchdog('crm_core_user_sync', 'User @user has been synchronized to the contact @contact_id, relation @rid has been created.',
- array('@user' => $account->name, '@contact_id' => $contact->contact_id, '@rid' => $relation->id())
- );
-
- return $contact;
-}
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\crm_core_contact\Entity\Individual;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\crm_core_user_sync\Entity\Relation;
+use Drupal\user\UserInterface;
/**
- * Loosely based on relation_rules_get_related_entities.
+ * Implements hook_user_insert().
*/
-function _crm_core_user_sync_get_related_entities($entity_type, $entity_id, $relation_type) {
- $rids = array_keys(relation_query($entity_type, $entity_id)->entityCondition('bundle', $relation_type)->execute());
-
- $entities_ids = array();
- if (!$rids) {
- return $entities_ids;
- }
-
- $target_entity_type = ($entity_type == 'user')?'crm_core_contact':'user';
- $rmap = array();
-
- foreach (Relation::loadMultiple($rids) as $relation) {
- $data = array();
- foreach ($relation->endpoints[LANGUAGE_NONE] as $endpoint) {
- $data[$endpoint['entity_type']] = $endpoint['entity_id'];
- }
- $entities_ids[] = $data[$target_entity_type];
- $rmap[$data[$target_entity_type]] = $data[$entity_type];
- }
-
- $entities = entity_load($target_entity_type, $entities_ids);
-
- $targets = array();
-
- foreach ($entities as $entity_id => $entity) {
- $targets[$rmap[$entity_id]] = $entity;
+function crm_core_user_sync_user_insert(UserInterface $account) {
+ $auto_sync_user_create = \Drupal::config('crm_core_user_sync.settings')->get('auto_sync_user_create');
+ if ($auto_sync_user_create) {
+ \Drupal::service('crm_core_user_sync.relation')->relate($account);
}
- return $targets;
}
/**
- * Copied from relation.module, (beta 1)
- * gives an error if the entity id is not found, so need to fix that
+ * Implements hook_user_update().
*/
-function _crm_core_user_sync_get_related_entity($entity_type, $entity_id, $relation_type = NULL, $r_index = NULL) {
- $query = relation_query($entity_type, $entity_id);
- if ($relation_type) {
- $query->propertyCondition('relation_type', $relation_type);
- }
- if (isset($r_index)) {
- // $query->propertyCondition('r_index', $r_index);
- $query->fieldCondition('endpoints', 'r_index', $r_index);
- }
- $results = $query->execute();
-
- if (empty($results)) {
- return;
- }
-
- $result = reset($results);
- $relation = Relation::load($result->relation_id);
- $request_key = $entity_type . ':' . $entity_id;
- $entities = $relation->endpoints[LANGUAGE_NONE];
- if (isset($entities[0]['entity_type']) && isset($entities[0]['entity_id'])) {
- $first_entity_key = $entities[0]['entity_type'] . ':' . $entities[0]['entity_id'];
- if (isset($r_index)) {
- $request_key = $request_key . ':' . $r_index;
- $first_entity_key = $first_entity_key . ':' . $entities[0]['r_index'];
- }
- if ($request_key == $first_entity_key) {
- $other_endpoints = entity_load($entities[1]['entity_type'], array($entities[1]['entity_id']));
- return reset($other_endpoints);
+function crm_core_user_sync_user_update(UserInterface $account) {
+ // User update only ensures that for the given user account there is a
+ // corresponding contact record.
+ $related_contact_id = \Drupal::service('crm_core_user_sync.relation')->getUserIndividualId($account->id());
+ if (empty($related_contact_id)) {
+ $auto_sync_user_create = \Drupal::config('crm_core_user_sync.settings')->get('auto_sync_user_create');
+ if ($auto_sync_user_create) {
+ \Drupal::service('crm_core_user_sync.relation')->relate($account);
}
- $other_endpoints = entity_load($entities[0]['entity_type'], array($entities[0]['entity_id']));
- return reset($other_endpoints);
}
}
/**
- * Retrieves the related entity based on entity type, ids and relation type.
+ * Implements hook_user_delete().
*/
-function crm_core_user_sync_get_related_entity($entity_type, $entity_id, $relation_type = 'crm_core_user_sync') {
- if (is_array($entity_id)) {
- return _crm_core_user_sync_get_related_entities($entity_type, $entity_id, $relation_type);
+function crm_core_user_sync_user_delete(UserInterface $account) {
+ $relation_id = \Drupal::service('crm_core_user_sync.relation')->getUserRelationId($account->id());
+ if ($relation_id) {
+ $relation = Relation::load($relation_id);
+ $relation->delete();
}
- elseif (is_numeric($entity_id)) {
- return _crm_core_user_sync_get_related_entity($entity_type, $entity_id, $relation_type);
- }
- return FALSE;
-}
-
-/**
- * Retrieves the related contacts for given uid(s).
- */
-function crm_core_user_sync_get_contact_from_uid($uid) {
- return crm_core_user_sync_get_related_entity('user', $uid, 'crm_core_user_sync');
-}
-
-/**
- * Retrieves the related contacts for given uids.
- */
-function crm_core_user_sync_get_contacts_from_uids($uids) {
- return crm_core_user_sync_get_related_entity('user', $uids, 'crm_core_user_sync');
}
/**
- * Retrieves the related users for given contact id(s).
+ * Implements hook_crm_core_individual_delete().
*/
-function crm_core_user_sync_get_user_from_contact_id($contact_id) {
- return crm_core_user_sync_get_related_entity('crm_core_contact', $contact_id, 'crm_core_user_sync');
-}
-
-/**
- * Retrieves the related users for given contact ids.
- */
-function crm_core_user_sync_get_users_from_contact_ids($contact_ids) {
- return crm_core_user_sync_get_related_entity('crm_core_contact', $contact_ids, 'crm_core_user_sync');
-}
-
-/**
- * Implements hook_entity_property_info_alter().
- *
- * We need to extend Contact entity with related user for Rules integration.
- */
-function crm_core_user_sync_entity_property_info_alter(&$info) {
- $info['crm_core_contact']['properties']['crm_core_user_sync_uid'] = array(
- 'label' => t('Linked Account'),
- 'description' => t('Account related to Contact by crm_core_user_sync module.'),
- 'type' => 'user',
- 'getter callback' => 'crm_core_user_sync_contact_get_user_properties',
- );
-}
-
-function crm_core_user_sync_contact_get_user_properties($entity, array $options, $name, $entity_type) {
- if ($account = _crm_core_user_sync_get_related_entity('crm_core_contact', $entity->contact_id, 'crm_core_user_sync')) {
- return $account->uid;
+function crm_core_user_sync_crm_core_individual_delete(IndividualInterface $individual) {
+ $relation_id = \Drupal::service('crm_core_user_sync.relation')->getIndividualRelationId($individual->id());
+ if ($relation_id) {
+ $relation = Relation::load($relation_id);
+ $relation->delete();
}
}
/**
- * Implements hook_form_FORM_ID_alter().
+ * Implements hook_entity_extra_field_info().
*/
-function crm_core_user_sync_form_crm_core_ui_admin_config_form_alter(&$form, &$form_state, $form_id) {
- $form['contacts'] = array(
- '#type' => 'fieldset',
- '#title' => t('Contacts'),
- '#weight' => 0,
- );
- $description = 'When checked, this will allow contact information to be loaded as part of the user entity. '
- . 'It will create an array containing contact information associated with the current user. In certain situations,'
- . ' loading contact data as part of a user entity can create performance issues (for instance, when there are '
- .'hundreds of fields associated with each contact). Uncheck this box if it is creating problems with performance.';
- $form['contacts']['crm_core_contact_load'] = array(
- '#type' => 'checkbox',
- '#title' => t('Load contact information as part of the user entity?'),
- '#description' => t($description),
- '#default_value' => variable_get('crm_core_contact_load', FALSE),
- '#weight' => 0,
- );
-}
+function crm_core_user_sync_entity_extra_field_info() {
+ $contact_show = \Drupal::config('crm_core_user_sync.settings')->get('contact_show');
+ if ($contact_show) {
+ $fields['user']['user']['display']['contact_information'] = [
+ 'label' => t('Contact information'),
+ 'description' => t('Display related contact information'),
+ 'weight' => 0,
+ ];
-/**
- * Implements hook_init().
- */
-function crm_core_user_sync_init() {
- if (variable_get('crm_core_contact_load', FALSE)) {
- global $user;
- $user->crm_core['contact'] = crm_core_user_sync_get_contact_from_uid($user->uid);
+ return $fields;
}
}
/**
- * Implements hook_theme
- */
-function crm_core_user_sync_theme() {
- return array(
- 'crm_core_user_sync_admin_form' => array(
- 'render element' => 'form',
- 'file' => 'crm_core_user_sync.admin.inc',
- ),
- );
-}
-
-/**
* Implements hook_user_view().
*/
-function crm_core_user_sync_user_view($account, $view_mode, $langcode) {
- $contact = crm_core_user_sync_get_contact_from_uid($account->uid);
- if ($contact) {
- $content = array(
- '#type' => 'user_profile_item',
- '#title' => t('Contact Information'),
- );
- $contact_label = t('Contact name: ');
- global $user;
- if (user_access('edit any crm_core_contact entity', $user)) {
- $uri = $contact->uri();
- $content['#markup'] = $contact_label . l($contact->label(), $uri['path']);
- }
- else {
- $content['#markup'] = $contact_label . $contact->label();
+function crm_core_user_sync_user_view(array &$build, UserInterface $account, EntityViewDisplayInterface $display) {
+ $contact_show = \Drupal::config('crm_core_user_sync.settings')->get('contact_show');
+ if ($contact_show) {
+ if ($display->getComponent('contact_information')) {
+ $individual_id = \Drupal::service('crm_core_user_sync.relation')->getUserIndividualId($account->id());
+ if ($individual_id) {
+ $individual = Individual::load($individual_id);
+ $build['contact_information'] = [
+ '#type' => 'item',
+ '#title' => t('Contact Information'),
+ '#markup' => '<h4 class="label">' . t('Contact name') . '</h4> ' . $individual->label(),
+ ];
+ }
}
- $account->content['crm_core'] = $content;
}
}
/**
- * Weight comparison function
- */
-function crm_core_user_sync_weight_cmp($a, $b) {
- if ($a['weight'] == $b['weight']) {
- return 0;
- }
- return ($a['weight'] < $b['weight']) ? -1 : 1;
-}
-
-/**
- * Implemets hook_views_pre_execute().
- */
-function crm_core_user_sync_views_pre_execute(&$view) {
- return; // TODO: update this
-
- if ($view->name == 'crm_core_contact_to_user_management') {
- // Implementing "FULL OUTER JOIN" by union of queries.
- // Reciept from http://drupal.org/node/748844#comment-7070234
- $left_query = db_select('crm_core_contact');
- $left_query->leftJoin('field_data_endpoints', 'field_data_endpoints', "crm_core_contact.contact_id = field_data_endpoints.endpoints_entity_id AND field_data_endpoints.bundle = 'crm_core_user_sync' AND field_data_endpoints.endpoints_entity_type = 'crm_core_contact'");
- $left_query->leftJoin('field_data_endpoints', 'field_data_endpoints2', "field_data_endpoints.entity_id = field_data_endpoints2.entity_id AND field_data_endpoints2.endpoints_entity_type = 'user'");
- $left_query->leftJoin('users', 'users_crm_core_contact', "field_data_endpoints2.endpoints_entity_id = users_crm_core_contact.uid AND field_data_endpoints2.endpoints_entity_type = 'user'");
- $left_query->addField('crm_core_contact', 'contact_id', 'contact_id');
- $left_query->addField('users_crm_core_contact', 'uid', 'users_crm_core_contact_uid');
- $left_query->addField('users_crm_core_contact', 'name', 'users_crm_core_contact_name');
- $left_query->addExpression("'crm_core_contact'", 'field_data_contact_name_crm_core_contact_entity_type');
-
- $right_query = db_select('crm_core_contact');
- $right_query->leftJoin('field_data_endpoints', 'field_data_endpoints', "crm_core_contact.contact_id = field_data_endpoints.endpoints_entity_id AND field_data_endpoints.bundle = 'crm_core_user_sync' AND field_data_endpoints.endpoints_entity_type = 'crm_core_contact'");
- $right_query->leftJoin('field_data_endpoints', 'field_data_endpoints2', "field_data_endpoints.entity_id = field_data_endpoints2.entity_id AND field_data_endpoints2.endpoints_entity_type = 'user'");
- $right_query->rightJoin('users', 'users_crm_core_contact', "field_data_endpoints2.endpoints_entity_id = users_crm_core_contact.uid AND field_data_endpoints2.endpoints_entity_type = 'user'");
- $right_query->addField('crm_core_contact', 'contact_id', 'contact_id');
- $right_query->addField('users_crm_core_contact', 'uid', 'users_crm_core_contact_uid');
- $right_query->addField('users_crm_core_contact', 'name', 'users_crm_core_contact_name');
- $right_query->addExpression("'crm_core_contact'", 'field_data_contact_name_crm_core_contact_entity_type');
-
- $left_query->union($right_query);
- $total_query = db_select($left_query, 'total')->fields('total');
- $view->build_info['count_query'] = $view->build_info['query'] = $total_query;
- }
-}
-
-/**
- * Retrieves entity object from a text in a format like 'Title [id_key: 123]'.
- */
-function _crm_core_user_sync_get_entity_id_from_text($text, $entity_type) {
- $entity_info = entity_get_info($entity_type);
-
- if (empty($entity_info) || empty($entity_info['entity keys']['id'])) {
- return FALSE;
- }
-
- $id_key = $entity_info['entity keys']['id'];
-
- $matches = array();
- preg_match('/\[' . $id_key . ':([0-9]+)\]/', $text, $matches);
- if (!array_key_exists(1, $matches) || !is_numeric($matches[1])) {
- return FALSE;
- }
- $entities = entity_load($entity_type, array($matches[1]));
- if (empty($entities)) {
- return FALSE;
- }
- return $entities[$matches[1]];
+ * Implements hook_views_data_alter().
+ *
+ * @todo Remove once https://www.drupal.org/project/drupal/issues/2706431 is
+ * resolved.
+ */
+function crm_core_user_sync_views_data_alter(array &$data) {
+ $title = t('CRM Core User Sync Relation');
+ $data['users_field_data']['crm_core_user_sync_relation'] = [
+ 'title' => $title,
+ 'help' => t('Adds relation to CRM Core User Sync Relation that point to current user.'),
+ 'relationship' => [
+ 'base' => 'crm_core_user_sync_relation',
+ 'base field' => 'user_id',
+ 'field' => 'uid',
+ 'id' => 'standard',
+ 'label' => $title,
+ ],
+ ];
+
+ $data['crm_core_individual']['crm_core_user_sync_relation'] = [
+ 'title' => $title,
+ 'help' => t('Adds relation to CRM Core User Sync Relation that point to current individual.'),
+ 'relationship' => [
+ 'base' => 'crm_core_user_sync_relation',
+ 'base field' => 'individual_id',
+ 'field' => 'individual_id',
+ 'id' => 'standard',
+ 'label' => $title,
+ ],
+ ];
}
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.pages.inc b/modules/crm_core_user_sync/crm_core_user_sync.pages.inc
deleted file mode 100644
index 8955daa..0000000
--- a/modules/crm_core_user_sync/crm_core_user_sync.pages.inc
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-/**
- * @file Non admin pages.
- */
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.permissions.yml b/modules/crm_core_user_sync/crm_core_user_sync.permissions.yml
new file mode 100644
index 0000000..ba4ae1e
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.permissions.yml
@@ -0,0 +1,6 @@
+administer crm-core-user-sync:
+ title: 'Administer User Synchronization'
+ description: 'Access to configuration pages for User Synchronization'
+edit own contact information:
+ title: 'Edit own contact information'
+ description: 'Allows user to edit his/her own contact record from the user profile form'
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.routing.yml b/modules/crm_core_user_sync/crm_core_user_sync.routing.yml
new file mode 100644
index 0000000..02afa38
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.routing.yml
@@ -0,0 +1,49 @@
+crm_core_user_sync.config:
+ path: '/admin/config/crm-core/user-sync'
+ defaults:
+ _form: 'Drupal\crm_core_user_sync\Form\SettingsForm'
+ _title: 'User Synchronization'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
+
+crm_core_user_sync.rule.new:
+ path: '/admin/config/crm-core/user-sync/new'
+ defaults:
+ _title: 'Add a new rule'
+ _form: 'Drupal\crm_core_user_sync\Form\RuleForm'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
+
+crm_core_user_sync.rule.edit:
+ path: '/admin/config/crm-core/user-sync/{rule_key}/edit'
+ defaults:
+ _title: 'Edit rule'
+ _form: 'Drupal\crm_core_user_sync\Form\RuleForm'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
+ rule_key: \d+
+
+crm_core_user_sync.rule.delete:
+ path: '/admin/config/crm-core/user-sync/{rule_key}/delete'
+ defaults:
+ _title: 'Are you sure you want to delete this rule?'
+ _form: 'Drupal\crm_core_user_sync\Form\RuleDeleteConfirmForm'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
+ rule_key: \d+
+
+crm_core_user_sync.rule.enable:
+ path: '/admin/config/crm-core/user-sync/{rule_key}/enable'
+ defaults:
+ _title: 'Enable rule'
+ _controller: '\Drupal\crm_core_user_sync\Controller\RuleStatusController::enable'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
+
+crm_core_user_sync.rule.disable:
+ path: '/admin/config/crm-core/user-sync/{rule_key}/disable'
+ defaults:
+ _title: 'Disable rule'
+ _controller: '\Drupal\crm_core_user_sync\Controller\RuleStatusController::disable'
+ requirements:
+ _permission: 'administer crm-core-user-sync'
diff --git a/modules/crm_core_user_sync/crm_core_user_sync.services.yml b/modules/crm_core_user_sync/crm_core_user_sync.services.yml
new file mode 100644
index 0000000..81f4ba0
--- /dev/null
+++ b/modules/crm_core_user_sync/crm_core_user_sync.services.yml
@@ -0,0 +1,18 @@
+services:
+ crm_core_user_sync.relation:
+ class: Drupal\crm_core_user_sync\CrmCoreUserSyncRelation
+ arguments: ['@entity_type.manager', '@crm_core_user_sync.relation_rules', '@logger.channel.crm_core_user_sync']
+
+ crm_core_user_sync.relation_rules:
+ class: Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules
+ arguments: ['@config.factory', 'crm_core_user_sync.settings']
+
+ crm_core_user_sync.request.event_subscriber:
+ class: Drupal\crm_core_user_sync\EventSubscriber\RequestSubscriber
+ arguments: ['@current_user', '@config.factory', '@crm_core_user_sync.relation', '@entity_type.manager']
+ tags:
+ - { name: event_subscriber }
+
+ logger.channel.crm_core_user_sync:
+ parent: logger.channel_base
+ arguments: ['crm_core_user_sync']
diff --git a/modules/crm_core_user_sync/src/Controller/RuleStatusController.php b/modules/crm_core_user_sync/src/Controller/RuleStatusController.php
new file mode 100644
index 0000000..a0e459a
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Controller/RuleStatusController.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Controller;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Controller\ControllerBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Returns responses for CRM Core User Synchronization routes.
+ */
+class RuleStatusController extends ControllerBase {
+
+ /**
+ * Current request.
+ *
+ * @var \Symfony\Component\HttpFoundation\Request
+ */
+ protected $request;
+
+ /**
+ * Constructs the controller object.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * Current request.
+ * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
+ * Config factory.
+ */
+ public function __construct(Request $request, ConfigFactoryInterface $configFactory) {
+ $this->request = $request;
+ $this->configFactory = $configFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('request_stack')->getCurrentRequest(),
+ $container->get('config.factory')
+ );
+ }
+
+ /**
+ * Enable rule.
+ */
+ public function enable() {
+ $rule_key = $this->request->get('rule_key');
+ $rules = $this->configFactory->getEditable('crm_core_user_sync.settings')->get('rules');
+ $rules[$rule_key]['enabled'] = TRUE;
+ $this->configFactory->getEditable('crm_core_user_sync.settings')->set('rules', $rules)->save();
+
+ return $this->redirect('crm_core_user_sync.config');
+ }
+
+ /**
+ * Disable rule.
+ */
+ public function disable() {
+ $rule_key = $this->request->get('rule_key');
+ $rules = $this->configFactory->getEditable('crm_core_user_sync.settings')->get('rules');
+ $rules[$rule_key]['enabled'] = FALSE;
+ $this->configFactory->getEditable('crm_core_user_sync.settings')->set('rules', $rules)->save();
+
+ return $this->redirect('crm_core_user_sync.config');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/CrmCoreUserSyncRelation.php b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelation.php
new file mode 100644
index 0000000..695c931
--- /dev/null
+++ b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelation.php
@@ -0,0 +1,188 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Logger\LoggerChannelInterface;
+use Drupal\crm_core_contact\Entity\Individual;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\crm_core_user_sync\Entity\Relation;
+use Drupal\user\UserInterface;
+
+/**
+ * Relation service.
+ *
+ * @package Drupal\crm_core_user_sync
+ */
+class CrmCoreUserSyncRelation implements CrmCoreUserSyncRelationInterface {
+
+ /**
+ * Relation storage.
+ *
+ * @var \Drupal\Core\Entity\EntityStorageInterface
+ */
+ protected $storage;
+
+ /**
+ * Relation rules service.
+ *
+ * @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules
+ */
+ protected $rules;
+
+ /**
+ * Logger channel.
+ *
+ * @var \Drupal\Core\Logger\LoggerChannelInterface
+ */
+ protected $logger;
+
+ /**
+ * Constructs a CrmCoreUserSyncRelation object.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+ * The entity type manager.
+ * @param \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules $rules
+ * Relation rules service.
+ * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
+ * Logger channel.
+ */
+ public function __construct(EntityTypeManagerInterface $entity_type_manager, CrmCoreUserSyncRelationRules $rules, LoggerChannelInterface $logger) {
+ $this->storage = $entity_type_manager->getStorage('crm_core_user_sync_relation');
+ $this->rules = $rules;
+ $this->logger = $logger;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUserIndividualId($user_id) {
+ $individual_id = NULL;
+
+ $rids = $this->storage->getQuery()
+ ->condition('user_id', $user_id)
+ ->range(0, 1)
+ ->execute();
+
+ if (!empty($rids)) {
+ $relation_id = reset($rids);
+ /* @var $relation \Drupal\crm_core_user_sync\Entity\Relation */
+ $relation = $this->storage->load($relation_id);
+ $individual_id = $relation->getIndividualId();
+ }
+
+ return $individual_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIndividualUserId($individual_id) {
+ $user_id = NULL;
+
+ $rids = $this->storage->getQuery()
+ ->condition('individual_id', $individual_id)
+ ->range(0, 1)
+ ->execute();
+
+ if (!empty($rids)) {
+ $relation_id = reset($rids);
+ /* @var $relation \Drupal\crm_core_user_sync\Entity\Relation */
+ $relation = $this->storage->load($relation_id);
+ $user_id = $relation->getIndividualId();
+ }
+
+ return $user_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUserRelationId($user_id) {
+ $rids = $this->storage->getQuery()
+ ->condition('user_id', $user_id)
+ ->range(0, 1)
+ ->execute();
+
+ if (!empty($rids)) {
+ return reset($rids);
+ }
+
+ return NULL;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIndividualRelationId($individual_id) {
+ $rids = $this->storage->getQuery()
+ ->condition('individual_id', $individual_id)
+ ->range(0, 1)
+ ->execute();
+
+ if (!empty($rids)) {
+ return reset($rids);
+ }
+
+ return NULL;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function relate(UserInterface $account, IndividualInterface $contact = NULL) {
+ // No contact and $account->crm_core_no_auto_sync => no sync.
+ if (empty($contact) && !empty($account->crm_core_no_auto_sync)) {
+ return NULL;
+ }
+
+ if (empty($contact)) {
+
+ // Account already have related contact.
+ if ($this->getUserIndividualId($account->id())) {
+ return NULL;
+ }
+ // Get corresponding contact type.
+ $contact_type = $this->rules->getContactType($account);
+
+ // No rules configured.
+ if (!$contact_type) {
+ return NULL;
+ }
+
+ // Create the contact.
+ $contact = Individual::create(['type' => $contact_type]);
+ $contact->setOwner($account);
+ // For now we just add the name.
+ $contact->name->given = $account->getAccountName();
+
+ $contact->save();
+ }
+
+ // Check if contact can be synchronized to a contact.
+ if (!$this->rules->valid($account, $contact)) {
+ return NULL;
+ }
+
+ // Check if crm_core_user_sync relation exists for any of endpoint.
+ if ($this->getUserIndividualId($account->id()) ||
+ $this->getIndividualUserId($contact->id())) {
+ return NULL;
+ }
+
+ $relation = Relation::create();
+ $relation->setUser($account);
+ $relation->setIndividual($contact);
+ $relation->save();
+
+ $this->logger->notice('User @user @uid has been synchronized to the contact @contact_id, relation @rid has been created.', [
+ '@user' => $account->getDisplayName(),
+ '@uid' => $account->id(),
+ '@contact_id' => $contact->id(),
+ '@rid' => $relation->id(),
+ ]);
+
+ return $contact;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationInterface.php b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationInterface.php
new file mode 100644
index 0000000..515cb2b
--- /dev/null
+++ b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationInterface.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * CrmCoreUserSyncRelation service.
+ */
+interface CrmCoreUserSyncRelationInterface {
+
+ /**
+ * Retrieves the individual contact id for specified user.
+ *
+ * @return int|null
+ * Individual id, if relation exists.
+ */
+ public function getUserIndividualId($user_id);
+
+ /**
+ * Retrieves the user id for specified individual contact.
+ *
+ * @return int|null
+ * User id, if relation exists.
+ */
+ public function getIndividualUserId($individual_id);
+
+ /**
+ * Retrieves the relation for specified user.
+ *
+ * @return int|null
+ * Relation ID, if exists.
+ */
+ public function getUserRelationId($user_id);
+
+ /**
+ * Retrieves the user id for specified individual contact.
+ *
+ * @return int|null
+ * Relation ID, if exists.
+ */
+ public function getIndividualRelationId($individual_id);
+
+ /**
+ * Synchronizes user and contact.
+ *
+ * @param \Drupal\user\UserInterface $account
+ * Account to be synchronized. Programmatically created accounts can
+ * override default behavior by setting
+ * $account->crm_core_no_auto_sync = TRUE.
+ * @param \Drupal\crm_core_contact\IndividualInterface $contact
+ * Contact to be associated with $account.
+ *
+ * @return \Drupal\crm_core_contact\ContactInterface
+ * A contact object.
+ *
+ * @throws \Drupal\Core\Entity\EntityStorageException
+ */
+ public function relate(UserInterface $account, IndividualInterface $contact = NULL);
+
+}
diff --git a/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationRules.php b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationRules.php
new file mode 100644
index 0000000..a0ce934
--- /dev/null
+++ b/modules/crm_core_user_sync/src/CrmCoreUserSyncRelationRules.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * CrmCoreUserSyncRelation service.
+ */
+class CrmCoreUserSyncRelationRules {
+
+ /**
+ * The configuration factory.
+ *
+ * @var \Drupal\Core\Config\ConfigFactoryInterface
+ */
+ protected $configFactory;
+
+ protected $rules;
+
+ /**
+ * Constructs a CrmCoreUserSyncRelationRules object.
+ *
+ * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+ * The configuration factory.
+ * @param string $configName
+ * Name of the configuration object that stores rules.
+ */
+ public function __construct(ConfigFactoryInterface $config_factory, $configName) {
+ $this->configFactory = $config_factory;
+ $this->configName = $configName;
+ }
+
+ /**
+ * Retrieves the individual contact id for specified user.
+ *
+ * @return int|null
+ * Individual id, if relation exists.
+ */
+ protected function getRules() {
+ if ($this->rules === NULL) {
+ $rules = $this
+ ->configFactory
+ ->get($this->configName)
+ ->get('rules');
+
+ uasort($rules, [$this, 'weightCmp']);
+ $this->rules = $rules;
+ }
+
+ return $this->rules;
+ }
+
+ /**
+ * Rules weight comparison function.
+ */
+ protected function weightCmp(array $a, array $b) {
+ if ($a['weight'] == $b['weight']) {
+ return 0;
+ }
+ return ($a['weight'] < $b['weight']) ? -1 : 1;
+ }
+
+ /**
+ * Checks if provided contact can be linked to this account.
+ *
+ * @param \Drupal\user\UserInterface $account
+ * User account to check.
+ * @param \Drupal\crm_core_contact\IndividualInterface $contact
+ * Contact record to check.
+ *
+ * @return bool
+ * TRUE if the contact is valid.
+ */
+ public function valid(UserInterface $account, IndividualInterface $contact) {
+ return $contact->bundle() === $this->getContactType($account);
+ }
+
+ /**
+ * Get contact type resolved from configured synchronization rules.
+ *
+ * @param \Drupal\user\UserInterface $account
+ * User account to check.
+ *
+ * @return string|false
+ * Intividual contact type (bundle) to be user for this user account.
+ */
+ public function getContactType(UserInterface $account) {
+
+ foreach ($this->getRules() as $rule) {
+ if ($rule['enabled'] && $account->hasRole($rule['role'])) {
+ return $rule['contact_type'];
+ }
+ }
+
+ return FALSE;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Entity/Relation.php b/modules/crm_core_user_sync/src/Entity/Relation.php
new file mode 100644
index 0000000..a14ef38
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Entity/Relation.php
@@ -0,0 +1,172 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Entity;
+
+use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\crm_core_user_sync\RelationInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Defines the relation entity class.
+ *
+ * @ContentEntityType(
+ * id = "crm_core_user_sync_relation",
+ * label = @Translation("Relation"),
+ * label_collection = @Translation("Relations"),
+ * handlers = {
+ * "view_builder" = "Drupal\crm_core_user_sync\RelationViewBuilder",
+ * "list_builder" = "Drupal\crm_core_user_sync\RelationListBuilder",
+ * "views_data" = "Drupal\views\EntityViewsData",
+ * "form" = {
+ * "add" = "Drupal\crm_core_user_sync\Form\RelationForm",
+ * "edit" = "Drupal\crm_core_user_sync\Form\RelationForm",
+ * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm"
+ * },
+ * "route_provider" = {
+ * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
+ * }
+ * },
+ * base_table = "crm_core_user_sync_relation",
+ * data_table = "crm_core_user_sync_relation_field_data",
+ * admin_permission = "administer crm-core-user-sync",
+ * entity_keys = {
+ * "id" = "id",
+ * "uuid" = "uuid"
+ * },
+ * links = {
+ * "add-form" = "/admin/config/crm-core/user-sync/relation/add",
+ * "canonical" = "/admin/config/crm-core/user-sync/relation/{crm_core_user_sync_relation}",
+ * "edit-form" = "/admin/config/crm-core/user-sync/relation/{crm_core_user_sync_relation}/edit",
+ * "delete-form" = "/admin/config/crm-core/user-sync/relation/{crm_core_user_sync_relation}/delete",
+ * "collection" = "/admin/config/crm-core/user-sync/relation"
+ * }
+ * )
+ */
+class Relation extends ContentEntityBase implements RelationInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUser() {
+ return $this->get('user_id')->entity;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUserId() {
+ return $this->get('user_id')->target_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUserId($uid) {
+ $this->set('user_id', $uid);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUser(UserInterface $account) {
+ $this->set('user_id', $account->id());
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIndividual() {
+ return $this->get('individual_id')->entity;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIndividualId() {
+ return $this->get('individual_id')->target_id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setIndividualId($individual_id) {
+ $this->set('individual_id', $individual_id);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setIndividual(IndividualInterface $individual) {
+ $this->set('individual_id', $individual->id());
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
+
+ $fields = parent::baseFieldDefinitions($entity_type);
+
+ $fields['user_id'] = BaseFieldDefinition::create('entity_reference')
+ ->setRequired(TRUE)
+ ->setCardinality(1)
+ // @todo Replace with what ever would work with entity reference
+ // from core. https://www.drupal.org/project/drupal/issues/2973455
+ ->addConstraint('UniqueReference')
+ ->setLabel(t('User'))
+ ->setDescription(t('The user ID of the relation.'))
+ ->setSetting('target_type', 'user')
+ ->setDisplayOptions('form', [
+ 'type' => 'entity_reference_autocomplete',
+ 'settings' => [
+ 'match_operator' => 'CONTAINS',
+ 'size' => 60,
+ 'placeholder' => '',
+ ],
+ 'weight' => 10,
+ ])
+ ->setDisplayConfigurable('form', TRUE)
+ ->setDisplayOptions('view', [
+ 'label' => 'above',
+ 'type' => 'entity_reference_label',
+ 'weight' => 10,
+ ])
+ ->setDisplayConfigurable('view', TRUE);
+
+ $fields['individual_id'] = BaseFieldDefinition::create('entity_reference')
+ ->setRequired(TRUE)
+ ->setCardinality(1)
+ // @todo Replace with what ever would work with entity reference
+ // from core. https://www.drupal.org/project/drupal/issues/2973455
+ ->addConstraint('UniqueReference')
+ ->setLabel(t('Individual'))
+ ->setDescription(t('The individual ID of the relation.'))
+ ->setSetting('target_type', 'crm_core_individual')
+ ->setDisplayOptions('form', [
+ 'type' => 'entity_reference_autocomplete',
+ 'settings' => [
+ 'match_operator' => 'CONTAINS',
+ 'size' => 60,
+ 'placeholder' => '',
+ ],
+ 'weight' => 15,
+ ])
+ ->setDisplayConfigurable('form', TRUE)
+ ->setDisplayOptions('view', [
+ 'label' => 'above',
+ 'type' => 'entity_reference_label',
+ 'weight' => 15,
+ ])
+ ->setDisplayConfigurable('view', TRUE);
+
+ return $fields;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/EventSubscriber/RequestSubscriber.php b/modules/crm_core_user_sync/src/EventSubscriber/RequestSubscriber.php
new file mode 100644
index 0000000..5f9758a
--- /dev/null
+++ b/modules/crm_core_user_sync/src/EventSubscriber/RequestSubscriber.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\EventSubscriber;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * CRM Core User Synchronization event subscriber.
+ */
+class RequestSubscriber implements EventSubscriberInterface {
+
+ /**
+ * Current logged in user.
+ *
+ * @var \Drupal\Core\Session\AccountProxyInterface
+ */
+ protected $currentUser;
+
+ /**
+ * The configuration factory.
+ *
+ * @var \Drupal\Core\Config\ConfigFactoryInterface
+ */
+ protected $configFactory;
+
+ /**
+ * Relation service.
+ *
+ * @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface
+ */
+ protected $relationService;
+
+ /**
+ * Entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * Constructs event subscriber.
+ *
+ * @param \Drupal\Core\Session\AccountProxyInterface $current_user
+ * Current logged in user.
+ * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+ * The configuration factory.
+ * @param \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface $relation_service
+ * The relation service.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
+ * Entity type manager.
+ */
+ public function __construct(AccountProxyInterface $current_user, ConfigFactoryInterface $config_factory, CrmCoreUserSyncRelationInterface $relation_service, EntityTypeManagerInterface $entityTypeManager) {
+ $this->currentUser = $current_user;
+ $this->configFactory = $config_factory;
+ $this->relationService = $relation_service;
+ $this->entityTypeManager = $entityTypeManager;
+ }
+
+ /**
+ * Kernel request event handler.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+ * Response event.
+ */
+ public function onKernelRequest(GetResponseEvent $event) {
+ if ($this->currentUser->isAuthenticated()) {
+ $config = $this->configFactory->get('crm_core_user_sync.settings');
+ if ($config->get('contact_load')) {
+ $individual_id = $this->relationService->getUserIndividualId($this->currentUser->id());
+ if ($individual_id) {
+ $individual = $this->entityTypeManager->getStorage('crm_core_individual')->load($individual_id);
+ $account = $this->currentUser->getAccount();
+ $account->crm_core['contact'] = $individual;
+ $this->currentUser->setAccount($account);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents() {
+ return [
+ KernelEvents::REQUEST => 'onKernelRequest',
+ ];
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Form/RelationForm.php b/modules/crm_core_user_sync/src/Form/RelationForm.php
new file mode 100644
index 0000000..c978910
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Form/RelationForm.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Form;
+
+use Drupal\Core\Entity\ContentEntityForm;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Form controller for the relation entity edit forms.
+ */
+class RelationForm extends ContentEntityForm {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function form(array $form, FormStateInterface $form_state) {
+ $individual_id = $this->getRequest()->query->get('individual_id');
+ $user_id = $this->getRequest()->query->get('user_id');
+ if ($individual_id || $user_id) {
+ $relation = $this->getEntity();
+ $relation->setIndividualId($individual_id);
+ $relation->setUserId($user_id);
+ $this->setEntity($relation);
+ }
+
+ $form = parent::form($form, $form_state);
+
+ if ($individual_id) {
+ $form['individual_id']['widget']['#disabled'] = TRUE;
+ }
+
+ if ($user_id) {
+ $form['user_id']['widget']['#disabled'] = TRUE;
+ }
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save(array $form, FormStateInterface $form_state) {
+
+ $entity = $this->getEntity();
+ $result = $entity->save();
+ $link = $entity->toLink($this->t('View'))->toString();
+
+ $logger_arguments = ['link' => $link];
+
+ if ($result == SAVED_NEW) {
+ $this->messenger()->addMessage($this->t('New relation has been created.'));
+ $this->logger('crm_core_user_sync')->notice('Created new relation', $logger_arguments);
+ }
+ else {
+ $this->messenger()->addMessage($this->t('The relation has been updated.'));
+ $this->logger('crm_core_user_sync')->notice('Relation updated', $logger_arguments);
+ }
+
+ $form_state->setRedirect('entity.crm_core_user_sync_relation.collection');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Form/RuleDeleteConfirmForm.php b/modules/crm_core_user_sync/src/Form/RuleDeleteConfirmForm.php
new file mode 100644
index 0000000..e62e5f3
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Form/RuleDeleteConfirmForm.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Form;
+
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a confirmation form before clearing out the examples.
+ */
+class RuleDeleteConfirmForm extends ConfirmFormBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'crm_core_user_sync_rule_delete_confirm_form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Are you sure you want to delete this rule?');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return new Url('crm_core_user_sync.config');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $rule_key = $this->getRequest()->get('rule_key');
+ $rules = $this->configFactory()->getEditable('crm_core_user_sync.settings')->get('rules');
+ unset($rules[$rule_key]);
+ // Re-key.
+ $rules = array_values($rules);
+ $this->configFactory()->getEditable('crm_core_user_sync.settings')->set('rules', $rules)->save();
+
+ $this->messenger()->addMessage('Rule was deleted');
+
+ $form_state->setRedirectUrl($this->getCancelUrl());
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Form/RuleForm.php b/modules/crm_core_user_sync/src/Form/RuleForm.php
new file mode 100644
index 0000000..0d96063
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Form/RuleForm.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\crm_core_contact\Entity\IndividualType;
+
+/**
+ * Configure CRM Core User Synchronization settings for this site.
+ */
+class RuleForm extends ConfigFormBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'crm_core_user_sync_rule_form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getEditableConfigNames() {
+ return ['crm_core_user_sync.settings'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state, $rule_key = 'new') {
+ $config = $this->config('crm_core_user_sync.settings');
+ $rules = $config->get('rules');
+
+ if ($rule_key === 'new') {
+ $rule = [
+ 'role' => '',
+ 'contact_type' => '',
+ 'enabled' => TRUE,
+ 'weight' => 0,
+ ];
+ $form_state->set('rule_key', 'new');
+ }
+ else {
+ if (isset($rules[$rule_key])) {
+ $rule = $rules[$rule_key];
+ $form_state->set('rule', $rule);
+ $form_state->set('rule_key', $rule_key);
+ }
+ else {
+ $rule = [
+ 'role' => '',
+ 'contact_type' => '',
+ 'enabled' => TRUE,
+ 'weight' => 0,
+ ];
+ $form_state->set('rule_key', 'new');
+ }
+ }
+
+ $types_options = ['' => $this->t('- Select -')];
+ foreach (IndividualType::loadMultiple() as $type) {
+ $types_options[$type->id()] = $type->label();
+ }
+
+ $role_options = ['' => $this->t('- Select -')];
+ foreach (user_roles(TRUE) as $role) {
+ $role_options[$role->id()] = $role->label();
+ }
+
+ $form['role'] = [
+ '#type' => 'select',
+ '#title' => $this->t('User Role'),
+ '#options' => $role_options,
+ '#default_value' => isset($rule['role']) ? $rule['role'] : '',
+ '#required' => TRUE,
+ ];
+
+ $form['contact_type'] = [
+ '#type' => 'select',
+ '#title' => $this->t('Contact Type'),
+ '#options' => $types_options,
+ '#default_value' => isset($rule['contact_type']) ? $rule['contact_type'] : '',
+ '#required' => TRUE,
+ ];
+
+ $form['weight'] = [
+ '#type' => 'weight',
+ '#title' => $this->t('Weight'),
+ '#default_value' => isset($rule['weight']) ? $rule['weight'] : 0,
+ ];
+
+ $form['enabled'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Enabled'),
+ '#default_value' => isset($rule['enabled']) ? $rule['enabled'] : TRUE,
+ '#description' => $this->t('When checked, this rule will be used to synchronize user accounts. When unchecked, it will be ignored throughout the system.'),
+ ];
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $rule = $form_state->get('rule');
+ foreach (['role', 'contact_type', 'weight', 'enabled'] as $key) {
+ $rule[$key] = $form_state->getValue($key);
+ }
+
+ $rules = $this
+ ->config('crm_core_user_sync.settings')
+ ->get('rules');
+
+ $rule_key = $form_state->get('rule_key');
+ if ($rule_key === 'new') {
+ $rules[] = $rule;
+ }
+ else {
+ $rules[$rule_key] = $rule;
+ }
+
+ $this->config('crm_core_user_sync.settings')
+ ->set('rules', $rules)
+ ->save();
+
+ $form_state->setRedirect('crm_core_user_sync.config');
+
+ parent::submitForm($form, $form_state);
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Form/SettingsForm.php b/modules/crm_core_user_sync/src/Form/SettingsForm.php
new file mode 100644
index 0000000..c889ce1
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Form/SettingsForm.php
@@ -0,0 +1,201 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Drupal\crm_core_contact\Entity\IndividualType;
+use Drupal\crm_core_user_sync\UserSyncBatch;
+
+/**
+ * Configure crm_core_user_sync settings.
+ */
+class SettingsForm extends ConfigFormBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEditableConfigNames() {
+ return ['crm_core_user_sync.settings'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'crm_core_user_sync_settings_form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $roles = user_roles(TRUE);
+ $types = IndividualType::loadMultiple();
+
+ $config = $this->config('crm_core_user_sync.settings');
+ $rules = $config->get('rules');
+ uasort($rules, [$this, 'weightCmp']);
+
+ $form['description'] = [
+ '#plain_text' => $this->t('CRM Core User Synchronization can automatically create contact records associated with user accounts under certain conditions.'),
+ ];
+
+ $form['auto_sync_user_create'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Automatically create an associated contact when account is created'),
+ '#description' => $this->t('When checked, this checkbox will automatically create new contacts when a new user account is created according to rules listed above. Rules will be processed in order until a new contact is created.'),
+ '#default_value' => $config->get('auto_sync_user_create'),
+ ];
+
+ $form['contact_load'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Load contact related to the current user'),
+ '#description' => $this->t('When checked, contact related to the current user will be loaded as part of the user account object in $account->crm_core["contact"]. In certain situations, loading contact data as part of a user entity can create performance issues (for instance, when there are hundreds of fields associated with each contact). Uncheck this box if it is creating problems with performance.'),
+ '#default_value' => $config->get('contact_load'),
+ ];
+
+ $form['contact_show'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Show contact information'),
+ '#description' => $this->t('When checked, contact related to the current user will be shown on user profile page. Configurable from "Manage display" page.'),
+ '#default_value' => $config->get('contact_show'),
+ ];
+
+ $form['rules'] = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Role'),
+ $this->t('Contact type'),
+ $this->t('Status'),
+ $this->t('Operations'),
+ $this->t('Weight'),
+ ],
+ '#tabledrag' => [
+ [
+ 'action' => 'order',
+ 'relationship' => 'sibling',
+ 'group' => 'rule-weight',
+ ],
+ ],
+ '#empty' => $this->t('No rules configured'),
+ ];
+
+ foreach ($rules as $key => $rule) {
+ $row = [];
+ $row['#attributes']['class'][] = 'draggable';
+ $row['#weight'] = $rule['weight'];
+
+ $row['role'] = ['#plain_text' => $roles[$rule['role']]->label()];
+ $row['contact_type'] = ['#plain_text' => $types[$rule['contact_type']]->label()];
+ $row['enabled'] = ['#plain_text' => $rule['enabled'] ? 'Enabled' : 'Disabled'];
+ $row['operations'] = [
+ '#type' => 'operations',
+ '#links' => [],
+ ];
+
+ $row['weight'] = [
+ '#type' => 'weight',
+ '#title_display' => 'invisible',
+ '#default_value' => $rule['weight'],
+ '#attributes' => ['class' => ['rule-weight']],
+ ];
+
+ $links = & $row['operations']['#links'];
+ $links['edit'] = [
+ 'title' => 'Edit',
+ 'url' => Url::fromRoute('crm_core_user_sync.rule.edit', ['rule_key' => $key]),
+ ];
+ $links['delete'] = [
+ 'title' => 'Delete',
+ 'url' => Url::fromRoute('crm_core_user_sync.rule.delete', ['rule_key' => $key]),
+ ];
+
+ if ($rule['enabled']) {
+ $links['disable'] = [
+ 'title' => 'Disable',
+ 'url' => Url::fromRoute('crm_core_user_sync.rule.disable', ['rule_key' => $key]),
+ ];
+ }
+ else {
+ $links['enable'] = [
+ 'title' => 'Enable',
+ 'url' => Url::fromRoute('crm_core_user_sync.rule.enable', ['rule_key' => $key]),
+ ];
+ }
+
+ $form['rules'][$key] = $row;
+ }
+
+ $form['crm_core_user_sync_wrapper'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Sync Current Users'),
+ ];
+ $form['crm_core_user_sync_wrapper']['user_sync'] = [
+ '#type' => 'submit',
+ '#value' => $this->t('Synchronize Users'),
+ '#submit' => ['::bulkUserSync'],
+ ];
+
+ $form['crm_core_user_sync_wrapper']['description'] = [
+ '#type' => 'item',
+ '#markup' => $this->t('Click this button to apply user synchronization rules to all user accounts that are currently not associated with a contact in the system. It will create an associated contact record for each user according to the rules configured above. Warning: this cannot be undone.'),
+ ];
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * Sets batch for bulk user synchronization.
+ */
+ public function bulkUserSync(array $form, FormStateInterface $form_state) {
+ $operations[] = [[UserSyncBatch::class, 'progress'], []];
+ $batch = [
+ 'operations' => $operations,
+ 'title' => $this->t('Processing user synchronization'),
+ 'finished' => [UserSyncBatch::class, 'finished'],
+ ];
+ batch_set($batch);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $config = $this->config('crm_core_user_sync.settings');
+ $rules = $config->get('rules');
+
+ $rule_values = $form_state->getValue('rules', []);
+ if (!empty($rule_values)) {
+ foreach ($rule_values as $key => $values) {
+ if (!empty($values['weight'])) {
+ $rules[$key]['weight'] = $values['weight'];
+ }
+ }
+ }
+
+ uasort($rules, [$this, 'weightCmp']);
+
+ $config
+ ->set('rules', $rules)
+ ->set('auto_sync_user_create', $form_state->getValue('auto_sync_user_create'))
+ ->set('contact_load', $form_state->getValue('contact_load'))
+ ->set('contact_show', $form_state->getValue('contact_show'))
+ ->save();
+
+ parent::submitForm($form, $form_state);
+ }
+
+ /**
+ * Weight comparison callback.
+ */
+ private function weightCmp($a, $b) {
+ if ($a['weight'] == $b['weight']) {
+ return 0;
+ }
+
+ return ($a['weight'] < $b['weight']) ? -1 : 1;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Plugin/Block/EditOwnContactInformationBlock.php b/modules/crm_core_user_sync/src/Plugin/Block/EditOwnContactInformationBlock.php
new file mode 100644
index 0000000..66cc62e
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Plugin/Block/EditOwnContactInformationBlock.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Plugin\Block;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormBuilderInterface;
+use Drupal\Core\Form\FormState;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Block\BlockBase;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\crm_core_contact\Entity\Individual;
+use Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a 'Edit own contact information' block.
+ *
+ * @Block(
+ * id = "crm_core_user_sync_edit_own_contact_information",
+ * admin_label = @Translation("Edit own contact information"),
+ * category = @Translation("CRM Core")
+ * )
+ */
+class EditOwnContactInformationBlock extends BlockBase implements ContainerFactoryPluginInterface {
+
+ /**
+ * Relation service.
+ *
+ * @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface
+ */
+ protected $relation;
+
+ /**
+ * Entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * Form builder.
+ *
+ * @var \Drupal\Core\Form\FormBuilderInterface
+ */
+ protected $formBuilder;
+
+ /**
+ * Current user.
+ *
+ * @var \Drupal\Core\Session\AccountProxyInterface
+ */
+ protected $accountProxy;
+
+ /**
+ * Constructs a new EditOwnContactInformationBlock instance.
+ *
+ * @param array $configuration
+ * The plugin configuration, i.e. an array with configuration values keyed
+ * by configuration option name. The special key 'context' may be used to
+ * initialize the defined contexts by setting it to an array of context
+ * values keyed by context names.
+ * @param string $plugin_id
+ * The plugin_id for the plugin instance.
+ * @param mixed $plugin_definition
+ * The plugin implementation definition.
+ * @param \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface $relation
+ * Relation service.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
+ * Entity type manager.
+ * @param \Drupal\Core\Form\FormBuilderInterface $formBuilder
+ * Form builder.
+ * @param \Drupal\Core\Session\AccountProxyInterface $accountProxy
+ * Current user.
+ */
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, CrmCoreUserSyncRelationInterface $relation, EntityTypeManagerInterface $entityTypeManager, FormBuilderInterface $formBuilder, AccountProxyInterface $accountProxy) {
+ parent::__construct($configuration, $plugin_id, $plugin_definition);
+ $this->relation = $relation;
+ $this->entityTypeManager = $entityTypeManager;
+ $this->formBuilder = $formBuilder;
+ $this->accountProxy = $accountProxy;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $configuration,
+ $plugin_id,
+ $plugin_definition,
+ $container->get('crm_core_user_sync.relation'),
+ $container->get('entity_type.manager'),
+ $container->get('form_builder'),
+ $container->get('current_user')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockAccess(AccountInterface $account) {
+ return AccessResult::allowedIfHasPermission($account, 'edit own contact information');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function build() {
+
+ if ($individualId = $this->relation->getUserIndividualId($this->accountProxy->id())) {
+ /* @var $individual \Drupal\crm_core_contact\Entity\Individual */
+ /* @var $form \Drupal\crm_core_contact\Form\IndividualForm */
+ $individual = Individual::load($individualId);
+
+ $form = $this->entityTypeManager->getFormObject($individual->getEntityTypeId(), 'default');
+ $form->setEntity($individual);
+ $form_state = new FormState();
+ $form_state->disableRedirect();
+ $build = $this->formBuilder->buildForm($form, $form_state);
+
+ unset($build['actions']['delete']);
+
+ return $build;
+ }
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraint.php b/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraint.php
new file mode 100644
index 0000000..4c24d45
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraint.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Entity Reference unique reference constraint.
+ *
+ * Verifies that referenced entities referenced only once.
+ *
+ * @Constraint(
+ * id = "UniqueReference",
+ * label = @Translation("Unique Entity Reference reference", context = "Validation")
+ * )
+ */
+class UniqueReferenceConstraint extends Constraint {
+
+ /**
+ * The default violation message.
+ *
+ * @var string
+ */
+ public $message = 'A @entity_type with @field_name referencing entity with ID @id already exists.';
+
+}
diff --git a/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraintValidator.php b/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraintValidator.php
new file mode 100644
index 0000000..9e66b6c
--- /dev/null
+++ b/modules/crm_core_user_sync/src/Plugin/Validation/Constraint/UniqueReferenceConstraintValidator.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\crm_core_user_sync\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+/**
+ * Validates that a field is unique for the given entity type.
+ */
+class UniqueReferenceConstraintValidator extends ConstraintValidator {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($items, Constraint $constraint) {
+ if (!$item = $items->first()) {
+ return;
+ }
+ $field_name = $items->getFieldDefinition()->getName();
+ /** @var \Drupal\Core\Entity\EntityInterface $entity */
+ $entity = $items->getEntity();
+ $entity_type_id = $entity->getEntityTypeId();
+ $id_key = $entity->getEntityType()->getKey('id');
+ $id = (int) $items->getEntity()->id();
+ $target_id = $item->target_id;
+
+ $value_taken = (bool) \Drupal::entityQuery($entity_type_id)
+ // The id could be NULL, so we cast it to 0 in that case.
+ ->condition($id_key, $id, '<>')
+ ->condition($field_name, $target_id)
+ ->range(0, 1)
+ ->count()
+ ->execute();
+
+ if ($value_taken) {
+ $this->context->addViolation($constraint->message, [
+ '@id' => $target_id,
+ '@entity_type' => $entity->getEntityType()->getLowercaseLabel(),
+ '@field_name' => mb_strtolower($items->getFieldDefinition()->getLabel()),
+ ]);
+ }
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/RelationInterface.php b/modules/crm_core_user_sync/src/RelationInterface.php
new file mode 100644
index 0000000..5d819d5
--- /dev/null
+++ b/modules/crm_core_user_sync/src/RelationInterface.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Provides an interface defining a relation entity type.
+ */
+interface RelationInterface extends ContentEntityInterface {
+
+ /**
+ * Returns the relation user entity.
+ *
+ * @return \Drupal\user\UserInterface
+ * The relation user entity.
+ */
+ public function getUser();
+
+ /**
+ * Sets the relation user entity.
+ *
+ * @param \Drupal\user\UserInterface $account
+ * The relation user entity.
+ *
+ * @return $this
+ */
+ public function setUser(UserInterface $account);
+
+ /**
+ * Returns the relation user ID.
+ *
+ * @return int|null
+ * The relation user ID, or NULL in case the user ID field has not been set.
+ */
+ public function getUserId();
+
+ /**
+ * Sets the relation user ID.
+ *
+ * @param int $uid
+ * The relation user id.
+ *
+ * @return $this
+ */
+ public function setUserId($uid);
+
+ /**
+ * Returns the relation individual entity.
+ *
+ * @return \Drupal\crm_core_contact\IndividualInterface
+ * The relation individual entity.
+ */
+ public function getIndividual();
+
+ /**
+ * Sets the relation individual entity.
+ *
+ * @param \Drupal\crm_core_contact\IndividualInterface $individual
+ * The relation individual entity.
+ *
+ * @return $this
+ */
+ public function setIndividual(IndividualInterface $individual);
+
+ /**
+ * Returns the relation individual ID.
+ *
+ * @return int|null
+ * The relation individual ID, or NULL in case the individual ID field has
+ * not been set.
+ */
+ public function getIndividualId();
+
+ /**
+ * Sets the relation individual ID.
+ *
+ * @param int $individual_id
+ * The relation individual id.
+ *
+ * @return $this
+ */
+ public function setIndividualId($individual_id);
+
+}
diff --git a/modules/crm_core_user_sync/src/RelationListBuilder.php b/modules/crm_core_user_sync/src/RelationListBuilder.php
new file mode 100644
index 0000000..1d10a3d
--- /dev/null
+++ b/modules/crm_core_user_sync/src/RelationListBuilder.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityListBuilder;
+use Drupal\Core\Datetime\DateFormatterInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Routing\RedirectDestinationInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a list controller for the relation entity type.
+ */
+class RelationListBuilder extends EntityListBuilder {
+
+ /**
+ * The date formatter service.
+ *
+ * @var \Drupal\Core\Datetime\DateFormatterInterface
+ */
+ protected $dateFormatter;
+
+ /**
+ * The redirect destination service.
+ *
+ * @var \Drupal\Core\Routing\RedirectDestinationInterface
+ */
+ protected $redirectDestination;
+
+ /**
+ * Constructs a new RelationListBuilder object.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+ * The entity type definition.
+ * @param \Drupal\Core\Entity\EntityStorageInterface $storage
+ * The entity storage class.
+ * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
+ * The date formatter service.
+ * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
+ * The redirect destination service.
+ */
+ public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) {
+ parent::__construct($entity_type, $storage);
+ $this->dateFormatter = $date_formatter;
+ $this->redirectDestination = $redirect_destination;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+ return new static(
+ $entity_type,
+ $container->get('entity_type.manager')->getStorage($entity_type->id()),
+ $container->get('date.formatter'),
+ $container->get('redirect.destination')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render() {
+ $total = \Drupal::database()
+ ->query('SELECT COUNT(*) FROM {crm_core_user_sync_relation}')
+ ->fetchField();
+
+ $build['summary']['#markup'] = $this->t('Total relations: @total', ['@total' => $total]);
+
+ $build['table'] = parent::render();
+
+ return $build;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildHeader() {
+ $header['id'] = $this->t('ID');
+ $header['user'] = $this->t('User');
+ $header['individual'] = $this->t('Individual');
+
+ return $header + parent::buildHeader();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildRow(EntityInterface $entity) {
+ /* @var $entity \Drupal\crm_core_user_sync\Entity\Relation */
+ $row['id'] = $entity->id();
+ $row['user'] = $entity->getUser()->label();
+ $row['individual'] = $entity->getIndividual()->label();
+
+ return $row + parent::buildRow($entity);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getDefaultOperations(EntityInterface $entity) {
+ $operations = parent::getDefaultOperations($entity);
+ $destination = $this->redirectDestination->getAsArray();
+ foreach ($operations as $key => $operation) {
+ $operations[$key]['query'] = $destination;
+ }
+ return $operations;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/RelationViewBuilder.php b/modules/crm_core_user_sync/src/RelationViewBuilder.php
new file mode 100644
index 0000000..815f20b
--- /dev/null
+++ b/modules/crm_core_user_sync/src/RelationViewBuilder.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityViewBuilder;
+
+/**
+ * Provides a view controller for a relation entity type.
+ */
+class RelationViewBuilder extends EntityViewBuilder {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getBuildDefaults(EntityInterface $entity, $view_mode) {
+ $build = parent::getBuildDefaults($entity, $view_mode);
+ // The relation has no entity template itself.
+ unset($build['#theme']);
+ return $build;
+ }
+
+}
diff --git a/modules/crm_core_user_sync/src/UserSyncBatch.php b/modules/crm_core_user_sync/src/UserSyncBatch.php
new file mode 100644
index 0000000..7c8b4ee
--- /dev/null
+++ b/modules/crm_core_user_sync/src/UserSyncBatch.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\crm_core_user_sync;
+
+/**
+ * Methods for running the ConfigImporter in a batch.
+ *
+ * @package Drupal\crm_core_user_sync
+ */
+class UserSyncBatch {
+
+ /**
+ * Batch operation callback.
+ */
+ public static function progress(&$context) {
+ $userStorage = \Drupal::entityTypeManager()->getStorage('user');
+
+ if (empty($context['sandbox'])) {
+ $max = $userStorage
+ ->getQuery()
+ ->condition('uid', 1, '>')
+ ->count()
+ ->execute();
+
+ $context['sandbox']['max'] = $max;
+ $context['sandbox']['progress'] = 0;
+ $context['results']['synced'] = 0;
+ $context['sandbox']['last_uid'] = 1;
+ }
+
+ $limit = 20;
+ $uids = $userStorage
+ ->getQuery()
+ ->sort('uid')
+ ->condition('uid', $context['sandbox']['last_uid'], '>')
+ ->range(0, $limit)
+ ->execute();
+
+ $accounts = $userStorage->loadMultiple($uids);
+ foreach ($accounts as $account) {
+ if (\Drupal::service('crm_core_user_sync.relation')->relate($account)) {
+ $context['results']['synced']++;
+ }
+ $context['sandbox']['last_uid'] = $account->id();
+ $context['sandbox']['progress']++;
+ }
+
+ if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
+ $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
+ }
+ }
+
+ /**
+ * Batch finished callback.
+ */
+ public static function finished($success, $results, $operations) {
+ \Drupal::messenger()->addMessage(t('@count users have been associated with contacts.', ['@count' => $results['synced']]));
+ }
+
+}
diff --git a/modules/crm_core_user_sync/tests/src/Kernel/CrmCoreUserSyncRelationTest.php b/modules/crm_core_user_sync/tests/src/Kernel/CrmCoreUserSyncRelationTest.php
new file mode 100644
index 0000000..54aa98b
--- /dev/null
+++ b/modules/crm_core_user_sync/tests/src/Kernel/CrmCoreUserSyncRelationTest.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace Drupal\Tests\crm_core_user_sync\Kernel;
+
+use Drupal\crm_core_contact\Entity\Individual;
+use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
+use Drupal\user\Entity\User;
+
+/**
+ * Test description.
+ *
+ * @group crm_core_user_sync
+ */
+class CrmCoreUserSyncRelationTest extends EntityKernelTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $modules = [
+ 'user',
+ 'name',
+ 'crm_core_contact',
+ 'crm_core_user_sync',
+ ];
+
+ /**
+ * Relation service.
+ *
+ * @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface
+ */
+ protected $relationService;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ // User::delete() fails without this.
+ $this->installSchema('user', ['users_data']);
+
+ $this->installEntitySchema('crm_core_individual');
+ $this->installEntitySchema('crm_core_user_sync_relation');
+
+ $this->installConfig(['crm_core_user_sync']);
+
+ $role_storage = $this->container->get('entity.manager')->getStorage('user_role');
+ $role_storage->create(['id' => 'customer'])->save();
+
+ $config = $this->config('crm_core_user_sync.settings');
+ $rules[] = [
+ 'role' => 'customer',
+ 'contact_type' => 'customer',
+ 'enabled' => TRUE,
+ 'weight' => 1,
+ ];
+
+ $rules[] = [
+ 'role' => 'authenticated',
+ 'contact_type' => 'individual',
+ 'enabled' => TRUE,
+ 'weight' => 10,
+ ];
+
+ $config
+ ->set('rules', $rules)
+ ->set('auto_sync_user_create', TRUE)
+ ->save();
+
+ $individual_type = $this
+ ->container
+ ->get('entity_type.manager')
+ ->getStorage('crm_core_individual_type')
+ ->create([
+ 'type' => 'individual',
+ 'primary_fields' => [],
+ ]);
+ $individual_type->save();
+
+ $customer_type = $this
+ ->container
+ ->get('entity_type.manager')
+ ->getStorage('crm_core_individual_type')
+ ->create(['type' => 'customer', 'primary_fields' => []]);
+ $customer_type->save();
+
+ $this->relationService = $this->container->get('crm_core_user_sync.relation');
+ }
+
+ /**
+ * Tests that relation and related individual was created.
+ */
+ public function testRelationCreated() {
+ $account_authenticated = User::create(['name' => 'authenticated']);
+ $account_authenticated->save();
+
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
+
+ $authenticated_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_individual_id, 'Related contact was created');
+
+ $related_account_id = $this->relationService->getIndividualUserId($authenticated_individual_id);
+ $this->assertEquals($related_account_id, $account_authenticated->id(), 'Related ');
+ }
+
+ /**
+ * Tests that configured rules are respected when related contacts created.
+ */
+ public function testRulesRespected() {
+ $account_authenticated = User::create(['name' => 'authenticated']);
+ $account_authenticated->save();
+ $contact_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
+ $this->assertNotEmpty($contact_individual_id, 'Individual contact was created when authenticated user account was created.');
+ $contact_individual = Individual::load($contact_individual_id);
+ $this->assertEquals('individual', $contact_individual->bundle(), 'Individual contact has correct bundle');
+
+ $customer_values = [
+ 'name' => 'customer',
+ 'roles' => ['customer'],
+ ];
+ $account_customer = User::create($customer_values);
+ $account_customer->save();
+
+ $contact_customer_id = $this->relationService->getUserIndividualId($account_customer->id());
+ $this->assertNotEmpty($contact_customer_id, 'Individual contact was created when customer user account was created.');
+ $contact_customer = Individual::load($contact_customer_id);
+ $this->assertEquals('customer', $contact_customer->bundle(), 'Individual contact has correct bundle');
+ }
+
+ /**
+ * Tests that relation is deleted when user account id deleted.
+ */
+ public function testRelationDeleted() {
+ $account_authenticated = User::create(['name' => 'authenticated']);
+ $account_authenticated->save();
+
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
+
+ $authenticated_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_individual_id, 'Related contact was created');
+
+ $account_authenticated->delete();
+
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertEmpty($authenticated_relation_id, 'Relation was deleted');
+
+ $authenticated_individual = Individual::load($authenticated_individual_id);
+ $this->assertTrue(is_object($authenticated_individual), 'Related contact still exists');
+
+ $individual_relation_id = $this->relationService->getIndividualRelationId($authenticated_individual->id());
+ $this->assertEmpty($individual_relation_id, 'Relation was deleted');
+ }
+
+ /**
+ * Tests that configured rules could be programmatically overridden.
+ *
+ * @see \Drupal\crm_core_user_sync\CrmCoreUserSyncRelation::relate()
+ */
+ public function testRulesOverride() {
+ $account_authenticated = User::create([
+ 'name' => 'authenticated',
+ 'crm_core_no_auto_sync' => TRUE,
+ ]);
+ $account_authenticated->save();
+
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertEmpty($authenticated_relation_id, 'Relation was not created');
+
+ $individual_customer = Individual::create(['type' => 'customer']);
+ $individual_customer->save();
+
+ $this->relationService->relate($account_authenticated, $individual_customer);
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertEmpty($authenticated_relation_id, 'Relation was not created');
+
+ $individual_individual = Individual::create(['type' => 'individual']);
+ $individual_individual->save();
+
+ $this->relationService->relate($account_authenticated, $individual_individual);
+ $authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
+ }
+
+ /**
+ * Tests that "relate" method is idempotent.
+ *
+ * @see \Drupal\crm_core_user_sync\CrmCoreUserSyncRelation::relate()
+ */
+ public function testNoDuplicatedContactsCreated() {
+ $account_name = $this->randomString();
+ $account_authenticated = User::create([
+ 'name' => $account_name,
+ ]);
+ $account_authenticated->save();
+
+ $authenticated_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
+ $this->assertNotEmpty($authenticated_individual_id, 'Related contact was created');
+
+ $this->relationService->relate($account_authenticated);
+ $contacts_with_name = $this->entityManager->getStorage('crm_core_individual')->getQuery()->condition('name.given', $account_name)->count()->execute();
+ $this->assertEquals(1, $contacts_with_name, 'There is only one contact was created');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/tests/src/Kernel/RelationEntityTest.php b/modules/crm_core_user_sync/tests/src/Kernel/RelationEntityTest.php
new file mode 100644
index 0000000..f94e508
--- /dev/null
+++ b/modules/crm_core_user_sync/tests/src/Kernel/RelationEntityTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\Tests\crm_core_user_sync\Kernel;
+
+use Drupal\crm_core_user_sync\Entity\Relation;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests the relation entity class.
+ *
+ * @group crm_core_user_sync
+ */
+class RelationEntityTest extends KernelTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $modules = [
+ 'system',
+ 'user',
+ 'name',
+ 'crm_core_contact',
+ 'crm_core_user_sync',
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+ $this->installEntitySchema('crm_core_user_sync_relation');
+ }
+
+ /**
+ * Tests some of the methods.
+ *
+ * @see \Drupal\crm_core_user_sync\Entity\Relation::setUserId()
+ * @see \Drupal\crm_core_user_sync\Entity\Relation::setIndividualId()
+ * @see \Drupal\crm_core_user_sync\Entity\Relation::getUserId()
+ * @see \Drupal\crm_core_user_sync\Entity\Relation::getIndividualId()
+ */
+ public function testRelationMethods() {
+ $user_id_1 = 1;
+ $individual_id_1 = 1;
+ $user_id_2 = 2;
+ $individual_id_2 = 2;
+
+ $relation = Relation::create([
+ 'user_id' => $user_id_1,
+ 'individual_id' => $individual_id_1,
+ ]);
+ $this->assertEquals($user_id_1, $relation->getUserId(), 'User ID match');
+ $this->assertEquals($individual_id_1, $relation->getIndividualId(), 'Individual ID match');
+
+ $relation->setUserId($user_id_2);
+ $this->assertEquals($user_id_2, $relation->getUserId(), 'User ID match');
+
+ $relation->setIndividualId($individual_id_2);
+ $this->assertEquals($individual_id_2, $relation->getIndividualId(), 'Individual ID match');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/tests/src/Unit/CrmCoreUserSyncRelationRulesTest.php b/modules/crm_core_user_sync/tests/src/Unit/CrmCoreUserSyncRelationRulesTest.php
new file mode 100644
index 0000000..98390bf
--- /dev/null
+++ b/modules/crm_core_user_sync/tests/src/Unit/CrmCoreUserSyncRelationRulesTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Drupal\Tests\crm_core_user_sync\Unit;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ImmutableConfig;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules;
+use Drupal\Tests\UnitTestCase;
+use Drupal\user\UserInterface;
+
+/**
+ * Test CrmCoreUserSyncRelationRules service.
+ *
+ * @property \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules rulesService
+ * @group crm_core_user_sync
+ * @coversDefaultClass \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules
+ */
+class CrmCoreUserSyncRelationRulesTest extends UnitTestCase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ $rules = [];
+ $rules[] = [
+ 'role' => 'customer',
+ 'contact_type' => 'customer',
+ 'enabled' => TRUE,
+ 'weight' => 1,
+ ];
+
+ $rules[] = [
+ 'role' => 'authenticated',
+ 'contact_type' => 'individual',
+ 'enabled' => TRUE,
+ 'weight' => 10,
+ ];
+
+ $config = $this->getMockBuilder(ImmutableConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config
+ ->expects($this->once())
+ ->method('get')
+ ->with('rules')
+ ->willReturn($rules);
+
+ $config_name = 'crm_core_user_sync.settings';
+ $configFactory = $this->createMock(ConfigFactoryInterface::class);
+ $configFactory
+ ->expects($this->once())
+ ->method('get')
+ ->with($config_name)
+ ->willReturn($config);
+
+ $this->rulesService = new CrmCoreUserSyncRelationRules($configFactory, $config_name);
+ }
+
+ /**
+ * Tests CrmCoreUserSyncRelationRules service.
+ */
+ public function testCrmCoreUserSyncRelationRulesService() {
+ $account_authenticated = $this->createMock(UserInterface::class);
+ $account_authenticated
+ ->expects($this->any())
+ ->method('hasRole')
+ ->willReturnMap([['authenticated', TRUE], ['customer', FALSE]]);
+
+ $account_customer = $this->createMock(UserInterface::class);
+ $account_customer
+ ->expects($this->any())
+ ->method('hasRole')
+ ->willReturnMap([['authenticated', FALSE], ['customer', TRUE]]);
+
+ $contact_individual = $this->createMock(IndividualInterface::class);
+ $contact_individual
+ ->expects($this->any())
+ ->method('bundle')
+ ->willReturn('individual');
+
+ $contact_customer = $this->createMock(IndividualInterface::class);
+ $contact_customer
+ ->expects($this->any())
+ ->method('bundle')
+ ->willReturn('customer');
+
+ $this->assertFalse($this->rulesService->valid($account_customer, $contact_individual), 'Individual contact cannot be related to customer user.');
+ $this->assertFalse($this->rulesService->valid($account_authenticated, $contact_customer), 'Customer contact can be related to authenticated user.');
+ $this->assertTrue($this->rulesService->valid($account_authenticated, $contact_individual), 'Individual contact can be related to authenticated user.');
+ $this->assertTrue($this->rulesService->valid($account_customer, $contact_customer), 'Customer contact can be related to customer user.');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/tests/src/Unit/RequestSubscriberTest.php b/modules/crm_core_user_sync/tests/src/Unit/RequestSubscriberTest.php
new file mode 100644
index 0000000..c9a79b7
--- /dev/null
+++ b/modules/crm_core_user_sync/tests/src/Unit/RequestSubscriberTest.php
@@ -0,0 +1,180 @@
+<?php
+
+namespace Drupal\Tests\crm_core_user_sync\Unit;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ImmutableConfig;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\crm_core_contact\IndividualInterface;
+use Drupal\crm_core_user_sync\CrmCoreUserSyncRelationInterface;
+use Drupal\crm_core_user_sync\EventSubscriber\RequestSubscriber;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+/**
+ * Test description.
+ *
+ * @group crm_core_user_sync
+ */
+class RequestSubscriberTest extends UnitTestCase {
+
+ /**
+ * Tests nothing happens for Anonymous.
+ */
+ public function testRequestSubscriberAnonymous() {
+ $current_user = $this->createMock(AccountProxyInterface::class);
+ $current_user->expects($this->once())
+ ->method('isAuthenticated')
+ ->willReturn(FALSE);
+
+ $configFactory = $this->createMock(ConfigFactoryInterface::class);
+ $configFactory
+ ->expects($this->never())
+ ->method('get');
+
+ $relationService = $this->createMock(CrmCoreUserSyncRelationInterface::class);
+
+ $entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
+ $entityTypeManager
+ ->expects($this->never())
+ ->method('getStorage');
+
+ $kernel = $this->prophesize(HttpKernelInterface::class);
+ $request = Request::create('/', 'GET');
+
+ $subscriber = new RequestSubscriber($current_user, $configFactory, $relationService, $entityTypeManager);
+ $event = new GetResponseEvent($kernel->reveal(), $request, HttpKernelInterface::MASTER_REQUEST);
+ $subscriber->onKernelRequest($event);
+ // Nothing to assert as we should exit immediately. Current user expectation
+ // will fail the test if something...
+ }
+
+ /**
+ * Tests nothing loaded for user without related contact.
+ */
+ public function testRequestSubscriberAuthenticatedWithoutContact() {
+ $current_user = $this->createMock(AccountProxyInterface::class);
+ $current_user->expects($this->once())
+ ->method('isAuthenticated')
+ ->willReturn(TRUE);
+ $current_user
+ ->expects($this->once())
+ ->method('id')
+ ->willReturn('101');
+
+ $config = $this->getMockBuilder(ImmutableConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config
+ ->expects($this->once())
+ ->method('get')
+ ->with('contact_load')
+ ->willReturn(TRUE);
+
+ $config_name = 'crm_core_user_sync.settings';
+ $configFactory = $this->createMock(ConfigFactoryInterface::class);
+ $configFactory
+ ->expects($this->once())
+ ->method('get')
+ ->with($config_name)
+ ->willReturn($config);
+
+ $relationService = $this->createMock(CrmCoreUserSyncRelationInterface::class);
+ $relationService
+ ->expects($this->once())
+ ->method('getUserIndividualId')
+ ->willReturn(FALSE);
+
+ $entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
+ $entityTypeManager
+ ->expects($this->never())
+ ->method('getStorage');
+
+ $kernel = $this->prophesize(HttpKernelInterface::class);
+ $request = Request::create('/', 'GET');
+
+ $subscriber = new RequestSubscriber($current_user, $configFactory, $relationService, $entityTypeManager);
+ $event = new GetResponseEvent($kernel->reveal(), $request, HttpKernelInterface::MASTER_REQUEST);
+ $subscriber->onKernelRequest($event);
+ // Nothing to assert. Entity type manager expectations will the test.
+ }
+
+ /**
+ * Tests contact loaded for the user with related contact.
+ */
+ public function testRequestSubscriberAuthenticatedWithContact() {
+ $current_user = $this->createMock(AccountProxyInterface::class);
+ $current_user->expects($this->once())
+ ->method('isAuthenticated')
+ ->willReturn(TRUE);
+ $current_user
+ ->expects($this->once())
+ ->method('id')
+ ->willReturn('101');
+
+ $account = $this->createMock(AccountInterface::class);
+ $current_user
+ ->expects($this->once())
+ ->method('getAccount')
+ ->willReturn($account);
+
+ $current_user
+ ->expects($this->at(0))
+ ->method('setAccount')
+ ->willReturnReference($account);
+
+ $config = $this->getMockBuilder(ImmutableConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config
+ ->expects($this->once())
+ ->method('get')
+ ->with('contact_load')
+ ->willReturn(TRUE);
+
+ $config_name = 'crm_core_user_sync.settings';
+ $configFactory = $this->createMock(ConfigFactoryInterface::class);
+ $configFactory
+ ->expects($this->once())
+ ->method('get')
+ ->with($config_name)
+ ->willReturn($config);
+
+ $individualId = 101;
+ $individual = $this->createMock(IndividualInterface::class);
+
+ $relationService = $this->createMock(CrmCoreUserSyncRelationInterface::class);
+ $relationService
+ ->expects($this->once())
+ ->method('getUserIndividualId')
+ ->willReturn($individualId);
+
+ $entityStorage = $this->createMock(EntityStorageInterface::class);
+ $entityStorage
+ ->expects($this->once())
+ ->method('load')
+ ->with($individualId)
+ ->willReturn($individual);
+
+ $entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
+ $entityTypeManager
+ ->expects($this->once())
+ ->method('getStorage')
+ ->with('crm_core_individual')
+ ->willReturn($entityStorage);
+
+ $kernel = $this->prophesize(HttpKernelInterface::class);
+ $request = Request::create('/', 'GET');
+
+ $subscriber = new RequestSubscriber($current_user, $configFactory, $relationService, $entityTypeManager);
+ $event = new GetResponseEvent($kernel->reveal(), $request, HttpKernelInterface::MASTER_REQUEST);
+ $subscriber->onKernelRequest($event);
+ $this->assertEquals($individual, $account->crm_core['contact'], 'Related contact was loaded');
+ }
+
+}
diff --git a/modules/crm_core_user_sync/views/crm_core_user_sync.views.inc b/modules/crm_core_user_sync/views/crm_core_user_sync.views.inc
deleted file mode 100644
index 4e57305..0000000
--- a/modules/crm_core_user_sync/views/crm_core_user_sync.views.inc
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-
-/**
- * @file
- * Provides support for the Views module.
- */
-
-/**
- * Implements hook_views_plugins().
- */
-function crm_core_user_sync_views_plugins() {
- return array(
- 'argument default' => array(
- 'crm_core_user_sync' => array(
- 'title' => t('CRM Contact ID (from user id from URL)'),
- 'handler' => 'views_plugin_argument_default_contact_id',
- 'parent' => 'views_plugin_argument_default',
- ),
- ),
- );
-}
diff --git a/modules/crm_core_user_sync/views/crm_core_user_sync.views_default.inc b/modules/crm_core_user_sync/views/crm_core_user_sync.views_default.inc
deleted file mode 100644
index eff6edf..0000000
--- a/modules/crm_core_user_sync/views/crm_core_user_sync.views_default.inc
+++ /dev/null
@@ -1,382 +0,0 @@
-<?php
-
-/**
- * Implements hook_views_default_views().
- */
-function crm_core_user_sync_views_default_views() {
- $view = new view();
- $view->name = 'crm_core_contact_to_user_management';
- $view->description = '';
- $view->tag = 'default';
- $view->base_table = 'crm_core_contact';
- $view->human_name = 'CRM Core Contact to User Management';
- $view->core = 7;
- $view->api_version = '3.0';
- $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
-
- /* Display: Master */
- $handler = $view->new_display('default', 'Master', 'default');
- $handler->display->display_options['title'] = 'Contact to User Management';
- $handler->display->display_options['use_more_always'] = FALSE;
- $handler->display->display_options['access']['type'] = 'perm';
- $handler->display->display_options['access']['perm'] = 'administer relations';
- $handler->display->display_options['cache']['type'] = 'none';
- $handler->display->display_options['query']['type'] = 'views_query';
- $handler->display->display_options['exposed_form']['type'] = 'basic';
- $handler->display->display_options['pager']['type'] = 'full';
- $handler->display->display_options['pager']['options']['items_per_page'] = '25';
- $handler->display->display_options['pager']['options']['offset'] = '0';
- $handler->display->display_options['pager']['options']['id'] = '0';
- $handler->display->display_options['pager']['options']['quantity'] = '9';
- $handler->display->display_options['style_plugin'] = 'table';
- $handler->display->display_options['style_options']['columns'] = array(
- 'contact_id' => 'contact_id',
- 'uid' => 'uid',
- 'rid' => 'rid',
- 'contact_name' => 'contact_name',
- 'name' => 'name',
- 'uid_2' => 'uid_2',
- 'nothing' => 'nothing',
- 'nothing_1' => 'nothing',
- 'nothing_2' => 'nothing',
- 'rid_1' => 'nothing',
- 'contact_id_1' => 'contact_id_1',
- 'uid_1' => 'nothing',
- 'nothing_3' => 'nothing',
- );
- $handler->display->display_options['style_options']['default'] = '-1';
- $handler->display->display_options['style_options']['info'] = array(
- 'contact_id' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'uid' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'rid' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'contact_name' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'name' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'uid_2' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'nothing' => array(
- 'align' => '',
- 'separator' => ' | ',
- 'empty_column' => 0,
- ),
- 'nothing_1' => array(
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'nothing_2' => array(
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'rid_1' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'contact_id_1' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'uid_1' => array(
- 'sortable' => 0,
- 'default_sort_order' => 'asc',
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- 'nothing_3' => array(
- 'align' => '',
- 'separator' => '',
- 'empty_column' => 0,
- ),
- );
- /* Header: Global: Text area */
- $handler->display->display_options['header']['area']['id'] = 'area';
- $handler->display->display_options['header']['area']['table'] = 'views';
- $handler->display->display_options['header']['area']['field'] = 'area';
- $handler->display->display_options['header']['area']['content'] = 'Occasionally, a contact will be mismatched with a user account. This tool provides you with manual control over the relations between contact records and user accounts. [nothing_4] for automated contact synchronization.';
- $handler->display->display_options['header']['area']['format'] = 'filtered_html';
- $handler->display->display_options['header']['area']['tokenize'] = TRUE;
- /* Relationship: CRM Contact: Relation: User (crm_core_contact → user) */
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['id'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['table'] = 'crm_core_contact';
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['field'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['r_index'] = '-1';
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['entity_deduplication_left'] = 0;
- $handler->display->display_options['relationships']['relation_crm_core_user_sync_user']['entity_deduplication_right'] = 0;
- /* Relationship: User: Relation: Contact (user → relation) */
- $handler->display->display_options['relationships']['relation_base_left_crm_core_user_sync']['id'] = 'relation_base_left_crm_core_user_sync';
- $handler->display->display_options['relationships']['relation_base_left_crm_core_user_sync']['table'] = 'users';
- $handler->display->display_options['relationships']['relation_base_left_crm_core_user_sync']['field'] = 'relation_base_left_crm_core_user_sync';
- $handler->display->display_options['relationships']['relation_base_left_crm_core_user_sync']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['relationships']['relation_base_left_crm_core_user_sync']['label'] = 'Relation';
- /* Field: CRM Contact: Contact ID */
- $handler->display->display_options['fields']['contact_id']['id'] = 'contact_id';
- $handler->display->display_options['fields']['contact_id']['table'] = 'crm_core_contact';
- $handler->display->display_options['fields']['contact_id']['field'] = 'contact_id';
- $handler->display->display_options['fields']['contact_id']['label'] = '';
- $handler->display->display_options['fields']['contact_id']['exclude'] = TRUE;
- $handler->display->display_options['fields']['contact_id']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['contact_id']['link_to_contact'] = 0;
- /* Field: User: Uid */
- $handler->display->display_options['fields']['uid']['id'] = 'uid';
- $handler->display->display_options['fields']['uid']['table'] = 'users';
- $handler->display->display_options['fields']['uid']['field'] = 'uid';
- $handler->display->display_options['fields']['uid']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['fields']['uid']['label'] = '';
- $handler->display->display_options['fields']['uid']['exclude'] = TRUE;
- $handler->display->display_options['fields']['uid']['alter']['alter_text'] = TRUE;
- $handler->display->display_options['fields']['uid']['alter']['text'] = '[name]';
- $handler->display->display_options['fields']['uid']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['uid']['link_to_user'] = FALSE;
- /* Field: Relation: Rid */
- $handler->display->display_options['fields']['rid']['id'] = 'rid';
- $handler->display->display_options['fields']['rid']['table'] = 'relation';
- $handler->display->display_options['fields']['rid']['field'] = 'rid';
- $handler->display->display_options['fields']['rid']['relationship'] = 'relation_base_left_crm_core_user_sync';
- $handler->display->display_options['fields']['rid']['label'] = '';
- $handler->display->display_options['fields']['rid']['exclude'] = TRUE;
- $handler->display->display_options['fields']['rid']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['rid']['separator'] = '';
- /* Field: CRM Contact: Household name */
- $handler->display->display_options['fields']['contact_name']['id'] = 'contact_name';
- $handler->display->display_options['fields']['contact_name']['table'] = 'field_data_contact_name';
- $handler->display->display_options['fields']['contact_name']['field'] = 'contact_name';
- $handler->display->display_options['fields']['contact_name']['label'] = 'Contact name';
- $handler->display->display_options['fields']['contact_name']['alter']['make_link'] = TRUE;
- $handler->display->display_options['fields']['contact_name']['alter']['path'] = 'crm-core/contact/[contact_id]';
- $handler->display->display_options['fields']['contact_name']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['contact_name']['empty'] = '---';
- $handler->display->display_options['fields']['contact_name']['click_sort_column'] = 'title';
- $handler->display->display_options['fields']['contact_name']['settings'] = array(
- 'format' => 'default',
- 'markup' => 0,
- 'output' => 'default',
- 'multiple' => 'default',
- 'multiple_delimiter' => ', ',
- 'multiple_and' => 'text',
- 'multiple_delimiter_precedes_last' => 'never',
- 'multiple_el_al_min' => '3',
- 'multiple_el_al_first' => '1',
- );
- /* Field: User: Name */
- $handler->display->display_options['fields']['name']['id'] = 'name';
- $handler->display->display_options['fields']['name']['table'] = 'users';
- $handler->display->display_options['fields']['name']['field'] = 'name';
- $handler->display->display_options['fields']['name']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['fields']['name']['label'] = 'User Name';
- $handler->display->display_options['fields']['name']['exclude'] = TRUE;
- $handler->display->display_options['fields']['name']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['name']['empty'] = '---';
- $handler->display->display_options['fields']['name']['hide_empty'] = TRUE;
- /* Field: User: Uid */
- $handler->display->display_options['fields']['uid_2']['id'] = 'uid_2';
- $handler->display->display_options['fields']['uid_2']['table'] = 'users';
- $handler->display->display_options['fields']['uid_2']['field'] = 'uid';
- $handler->display->display_options['fields']['uid_2']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['fields']['uid_2']['label'] = 'User name';
- $handler->display->display_options['fields']['uid_2']['alter']['alter_text'] = TRUE;
- $handler->display->display_options['fields']['uid_2']['alter']['text'] = '[name]';
- $handler->display->display_options['fields']['uid_2']['empty'] = '---';
- $handler->display->display_options['fields']['uid_2']['empty_zero'] = TRUE;
- $handler->display->display_options['fields']['uid_2']['link_to_user'] = FALSE;
- /* Field: Global: Custom text */
- $handler->display->display_options['fields']['nothing']['id'] = 'nothing';
- $handler->display->display_options['fields']['nothing']['table'] = 'views';
- $handler->display->display_options['fields']['nothing']['field'] = 'nothing';
- $handler->display->display_options['fields']['nothing']['label'] = 'Operations';
- /* Field: Global: Custom text */
- $handler->display->display_options['fields']['nothing_1']['id'] = 'nothing_1';
- $handler->display->display_options['fields']['nothing_1']['table'] = 'views';
- $handler->display->display_options['fields']['nothing_1']['field'] = 'nothing';
- $handler->display->display_options['fields']['nothing_1']['label'] = 'Edit Link Text';
- $handler->display->display_options['fields']['nothing_1']['exclude'] = TRUE;
- $handler->display->display_options['fields']['nothing_1']['alter']['text'] = 'Edit';
- $handler->display->display_options['fields']['nothing_1']['alter']['make_link'] = TRUE;
- $handler->display->display_options['fields']['nothing_1']['alter']['path'] = 'admin/config/crm-core/user-sync/contact-to-user-management/[rid]/edit';
- $handler->display->display_options['fields']['nothing_1']['element_label_colon'] = FALSE;
- /* Field: Global: Custom text */
- $handler->display->display_options['fields']['nothing_2']['id'] = 'nothing_2';
- $handler->display->display_options['fields']['nothing_2']['table'] = 'views';
- $handler->display->display_options['fields']['nothing_2']['field'] = 'nothing';
- $handler->display->display_options['fields']['nothing_2']['label'] = 'Delete Link Text';
- $handler->display->display_options['fields']['nothing_2']['exclude'] = TRUE;
- $handler->display->display_options['fields']['nothing_2']['alter']['text'] = 'Delete';
- $handler->display->display_options['fields']['nothing_2']['alter']['make_link'] = TRUE;
- $handler->display->display_options['fields']['nothing_2']['alter']['path'] = 'admin/config/crm-core/user-sync/contact-to-user-management/[rid]/delete';
- $handler->display->display_options['fields']['nothing_2']['element_label_colon'] = FALSE;
- /* Field: Relation: Rid */
- $handler->display->display_options['fields']['rid_1']['id'] = 'rid_1';
- $handler->display->display_options['fields']['rid_1']['table'] = 'relation';
- $handler->display->display_options['fields']['rid_1']['field'] = 'rid';
- $handler->display->display_options['fields']['rid_1']['relationship'] = 'relation_base_left_crm_core_user_sync';
- $handler->display->display_options['fields']['rid_1']['label'] = 'Edit/Delete Link Controller';
- $handler->display->display_options['fields']['rid_1']['alter']['alter_text'] = TRUE;
- $handler->display->display_options['fields']['rid_1']['alter']['text'] = '[nothing_1] | [nothing_2] ';
- $handler->display->display_options['fields']['rid_1']['hide_empty'] = TRUE;
- $handler->display->display_options['fields']['rid_1']['empty_zero'] = TRUE;
- $handler->display->display_options['fields']['rid_1']['separator'] = '';
- /* Field: CRM Contact: Contact ID */
- $handler->display->display_options['fields']['contact_id_1']['id'] = 'contact_id_1';
- $handler->display->display_options['fields']['contact_id_1']['table'] = 'crm_core_contact';
- $handler->display->display_options['fields']['contact_id_1']['field'] = 'contact_id';
- $handler->display->display_options['fields']['contact_id_1']['label'] = 'Add user account link';
- $handler->display->display_options['fields']['contact_id_1']['exclude'] = TRUE;
- $handler->display->display_options['fields']['contact_id_1']['alter']['alter_text'] = TRUE;
- $handler->display->display_options['fields']['contact_id_1']['alter']['text'] = 'Add user record';
- $handler->display->display_options['fields']['contact_id_1']['alter']['make_link'] = TRUE;
- $handler->display->display_options['fields']['contact_id_1']['alter']['path'] = 'admin/config/crm-core/user-sync/contact-to-user-management/add?contact_id=[contact_id]';
- $handler->display->display_options['fields']['contact_id_1']['link_to_contact'] = 0;
- /* Field: User: Uid */
- $handler->display->display_options['fields']['uid_1']['id'] = 'uid_1';
- $handler->display->display_options['fields']['uid_1']['table'] = 'users';
- $handler->display->display_options['fields']['uid_1']['field'] = 'uid';
- $handler->display->display_options['fields']['uid_1']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['fields']['uid_1']['label'] = 'Add user account link controller';
- $handler->display->display_options['fields']['uid_1']['exclude'] = TRUE;
- $handler->display->display_options['fields']['uid_1']['alter']['alter_text'] = TRUE;
- $handler->display->display_options['fields']['uid_1']['alter']['text'] = ' ';
- $handler->display->display_options['fields']['uid_1']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['uid_1']['empty'] = '[contact_id_1]';
- $handler->display->display_options['fields']['uid_1']['link_to_user'] = FALSE;
- /* Field: Global: Custom text */
- $handler->display->display_options['fields']['nothing_3']['id'] = 'nothing_3';
- $handler->display->display_options['fields']['nothing_3']['table'] = 'views';
- $handler->display->display_options['fields']['nothing_3']['field'] = 'nothing';
- $handler->display->display_options['fields']['nothing_3']['label'] = 'Add user account trimmer';
- $handler->display->display_options['fields']['nothing_3']['alter']['text'] = '[uid_1]';
- $handler->display->display_options['fields']['nothing_3']['alter']['trim_whitespace'] = TRUE;
- $handler->display->display_options['fields']['nothing_3']['element_label_colon'] = FALSE;
- /* Field: Global: Custom text */
- $handler->display->display_options['fields']['nothing_4']['id'] = 'nothing_4';
- $handler->display->display_options['fields']['nothing_4']['table'] = 'views';
- $handler->display->display_options['fields']['nothing_4']['field'] = 'nothing';
- $handler->display->display_options['fields']['nothing_4']['label'] = '';
- $handler->display->display_options['fields']['nothing_4']['exclude'] = TRUE;
- $handler->display->display_options['fields']['nothing_4']['alter']['text'] = 'Configure the default rules';
- $handler->display->display_options['fields']['nothing_4']['alter']['make_link'] = TRUE;
- $handler->display->display_options['fields']['nothing_4']['alter']['path'] = 'admin/config/crm-core/user-sync';
- $handler->display->display_options['fields']['nothing_4']['element_label_colon'] = FALSE;
- $handler->display->display_options['fields']['nothing_4']['element_default_classes'] = FALSE;
- /* Sort criterion: CRM Contact: Household name (contact_name:given) */
- $handler->display->display_options['sorts']['contact_name_given']['id'] = 'contact_name_given';
- $handler->display->display_options['sorts']['contact_name_given']['table'] = 'field_data_contact_name';
- $handler->display->display_options['sorts']['contact_name_given']['field'] = 'contact_name_given';
- $handler->display->display_options['sorts']['contact_name_given']['exposed'] = TRUE;
- $handler->display->display_options['sorts']['contact_name_given']['expose']['label'] = 'First name';
- /* Sort criterion: CRM Contact: Household name (contact_name:family) */
- $handler->display->display_options['sorts']['contact_name_family']['id'] = 'contact_name_family';
- $handler->display->display_options['sorts']['contact_name_family']['table'] = 'field_data_contact_name';
- $handler->display->display_options['sorts']['contact_name_family']['field'] = 'contact_name_family';
- $handler->display->display_options['sorts']['contact_name_family']['exposed'] = TRUE;
- $handler->display->display_options['sorts']['contact_name_family']['expose']['label'] = 'Last name';
- /* Sort criterion: User: Name */
- $handler->display->display_options['sorts']['name']['id'] = 'name';
- $handler->display->display_options['sorts']['name']['table'] = 'users';
- $handler->display->display_options['sorts']['name']['field'] = 'name';
- $handler->display->display_options['sorts']['name']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['sorts']['name']['exposed'] = TRUE;
- $handler->display->display_options['sorts']['name']['expose']['label'] = 'User name';
- /* Filter criterion: CRM Contact: Household name */
- $handler->display->display_options['filters']['contact_name']['id'] = 'contact_name';
- $handler->display->display_options['filters']['contact_name']['table'] = 'field_data_contact_name';
- $handler->display->display_options['filters']['contact_name']['field'] = 'contact_name';
- $handler->display->display_options['filters']['contact_name']['group'] = 1;
- $handler->display->display_options['filters']['contact_name']['exposed'] = TRUE;
- $handler->display->display_options['filters']['contact_name']['expose']['operator_id'] = 'contact_name_op';
- $handler->display->display_options['filters']['contact_name']['expose']['label'] = 'Filter by contact name';
- $handler->display->display_options['filters']['contact_name']['expose']['operator'] = 'contact_name_op';
- $handler->display->display_options['filters']['contact_name']['expose']['identifier'] = 'contact_name';
- $handler->display->display_options['filters']['contact_name']['expose']['remember_roles'] = array(
- 2 => '2',
- 1 => 0,
- 3 => 0,
- );
- /* Filter criterion: User: Name */
- $handler->display->display_options['filters']['uid']['id'] = 'uid';
- $handler->display->display_options['filters']['uid']['table'] = 'users';
- $handler->display->display_options['filters']['uid']['field'] = 'uid';
- $handler->display->display_options['filters']['uid']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['filters']['uid']['value'] = '';
- $handler->display->display_options['filters']['uid']['group'] = 1;
- $handler->display->display_options['filters']['uid']['exposed'] = TRUE;
- $handler->display->display_options['filters']['uid']['expose']['operator_id'] = 'uid_op';
- $handler->display->display_options['filters']['uid']['expose']['label'] = 'Filter by user name';
- $handler->display->display_options['filters']['uid']['expose']['operator'] = 'uid_op';
- $handler->display->display_options['filters']['uid']['expose']['identifier'] = 'uid';
- $handler->display->display_options['filters']['uid']['expose']['remember_roles'] = array(
- 2 => '2',
- 1 => 0,
- 3 => 0,
- );
- /* Filter criterion: User: E-mail */
- $handler->display->display_options['filters']['mail']['id'] = 'mail';
- $handler->display->display_options['filters']['mail']['table'] = 'users';
- $handler->display->display_options['filters']['mail']['field'] = 'mail';
- $handler->display->display_options['filters']['mail']['relationship'] = 'relation_crm_core_user_sync_user';
- $handler->display->display_options['filters']['mail']['operator'] = 'contains';
- $handler->display->display_options['filters']['mail']['group'] = 1;
- $handler->display->display_options['filters']['mail']['exposed'] = TRUE;
- $handler->display->display_options['filters']['mail']['expose']['operator_id'] = 'mail_op';
- $handler->display->display_options['filters']['mail']['expose']['label'] = 'Filter by user email address';
- $handler->display->display_options['filters']['mail']['expose']['operator'] = 'mail_op';
- $handler->display->display_options['filters']['mail']['expose']['identifier'] = 'mail';
- $handler->display->display_options['filters']['mail']['expose']['remember_roles'] = array(
- 2 => '2',
- 1 => 0,
- 3 => 0,
- );
-
- /* Display: Page */
- $handler = $view->new_display('page', 'Page', 'page');
- $handler->display->display_options['defaults']['hide_admin_links'] = FALSE;
- $handler->display->display_options['path'] = 'admin/config/crm-core/user-sync/contact-to-user-management';
- $handler->display->display_options['menu']['type'] = 'tab';
- $handler->display->display_options['menu']['title'] = 'Contact to User Management';
- $handler->display->display_options['menu']['weight'] = '0';
- $handler->display->display_options['menu']['context'] = 0;
-
- $views['crm_core_contact_to_user_management'] = $view;
-
- return $views;
-}
diff --git a/modules/crm_core_user_sync/views/views_plugin_argument_default_contact_id.inc b/modules/crm_core_user_sync/views/views_plugin_argument_default_contact_id.inc
deleted file mode 100644
index b0755d5..0000000
--- a/modules/crm_core_user_sync/views/views_plugin_argument_default_contact_id.inc
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-/**
- * @file
- * Contains the user from URL argument default plugin.
- */
-
-/**
- * Default argument plugin to extract a user via menu_get_object
- */
-class views_plugin_argument_default_contact_id extends views_plugin_argument_default {
- function option_definition() {
- $options = parent::option_definition();
- $options['user'] = array('default' => '', 'bool' => TRUE, 'translatable' => FALSE);
-
- return $options;
- }
-
- function options_form(&$form, &$form_state) {
- $form['user'] = array(
- '#type' => 'checkbox',
- '#title' => t('Also look for a node and use the node author'),
- '#default_value' => $this->options['user'],
- );
- }
-
- function convert_options(&$options) {
- if (!isset($options['user']) && isset($this->argument->options['default_argument_user'])) {
- $options['user'] = $this->argument->options['default_argument_user'];
- }
- }
-
- function get_argument() {
- foreach (range(1, 3) as $i) {
- $user = menu_get_object('user', $i);
- if (!empty($user)) {
- $contact = _crm_core_user_sync_get_related_entity('user', $user->uid, 'crm_core_user_sync');
- if (!empty($contact)) {
- return $contact->contact_id;
- }
- }
- }
-
- foreach (range(1, 3) as $i) {
- $user = menu_get_object('user_uid_optional', $i);
- if (!empty($user)) {
- $contact = _crm_core_user_sync_get_related_entity('user', $user->uid, 'crm_core_user_sync');
- if (!empty($contact)) {
- return $contact->contact_id;
- }
- }
- }
-
- if (!empty($this->options['user'])) {
- foreach (range(1, 3) as $i) {
- $node = menu_get_object('node', $i);
- if (!empty($node)) {
- $contact = _crm_core_user_sync_get_related_entity('user', $node->uid, 'crm_core_user_sync');
- if (!empty($contact)) {
- return $contact->contact_id;
- }
- }
- }
- }
-
- if (arg(0) == 'user' && is_numeric(arg(1))) {
- $uid = arg(1);
- $contact = _crm_core_user_sync_get_related_entity('user', $uid, 'crm_core_user_sync');
- if (!empty($contact)) {
- return $contact->contact_id;
- }
- }
-
- if (!empty($this->options['user'])) {
- if (arg(0) == 'node' && is_numeric(arg(1))) {
- $node = node_load(arg(1));
- if ($node) {
- $contact = _crm_core_user_sync_get_related_entity('user', $node->uid, 'crm_core_user_sync');
- if (!empty($contact)) {
- return $contact->contact_id;
- }
- }
- }
- }
-
- // If the current page is a view that takes uid as an argument, return the uid.
- $views_page = views_get_page_view();
-
- if ($views_page && isset($views_page->view->argument['uid'])) {
- return $views_page->view->argument['uid']->argument;
- }
- }
-}