From 76ff40f8bbfb14f976b541e05203d427aeb8d7d8 Mon Sep 17 00:00:00 2001 From: Bachir Soussi Chiadmi Date: Tue, 17 Apr 2018 14:53:21 +0200 Subject: [PATCH] updated linkit contrib module to last beta version --- .../modules/contrib/fields/linkit/README.md | 49 ++- .../linkit.linkit_profile.default.yml | 19 + .../linkit/config/schema/linkit.schema.yml | 65 ++-- .../fields/linkit/css/linkit.admin.theme.css | 3 +- .../fields/linkit/css/linkit.autocomplete.css | 38 +- .../fields/linkit/images/throbber-active.gif | Bin 0 -> 1275 bytes .../linkit/images/throbber-inactive.png | Bin 0 -> 356 bytes .../fields/linkit/js/attribute/title.js | 21 -- .../contrib/fields/linkit/js/autocomplete.js | 116 +++++-- .../linkit/js/linkit.filter_html.admin.js | 51 +++ .../contrib/fields/linkit/js/linkit.imce.js | 52 --- .../linkit/js/plugins/linkit/linkit.png | Bin 539 -> 0 bytes .../fields/linkit/js/plugins/linkit/plugin.js | 223 ------------ .../contrib/fields/linkit/linkit.info.yml | 12 +- .../contrib/fields/linkit/linkit.install | 191 +++++++++- .../fields/linkit/linkit.libraries.yml | 15 +- .../fields/linkit/linkit.links.action.yml | 7 - .../fields/linkit/linkit.links.task.yml | 5 - .../contrib/fields/linkit/linkit.module | 200 ++++++----- .../fields/linkit/linkit.permissions.yml | 2 +- .../contrib/fields/linkit/linkit.routing.yml | 42 +-- .../contrib/fields/linkit/linkit.services.yml | 13 +- .../linkit/src/Annotation/Attribute.php | 69 ---- .../fields/linkit/src/Annotation/Matcher.php | 14 +- .../linkit/src/Annotation/Substitution.php | 28 ++ .../fields/linkit/src/AttributeBase.php | 112 ------ .../fields/linkit/src/AttributeCollection.php | 46 --- .../fields/linkit/src/AttributeInterface.php | 78 ----- .../fields/linkit/src/AttributeManager.php | 29 -- .../linkit/src/ConfigurableAttributeBase.php | 16 - .../src/ConfigurableAttributeInterface.php | 23 -- .../linkit/src/ConfigurableMatcherBase.php | 5 - .../src/ConfigurableMatcherInterface.php | 6 - .../src/Controller/AutocompleteController.php | 50 +-- .../src/Controller/LinkitController.php | 26 +- .../fields/linkit/src/Element/Linkit.php | 45 +-- .../fields/linkit/src/Entity/Profile.php | 100 +----- .../linkit/src/Form/Attribute/AddForm.php | 166 --------- .../linkit/src/Form/Attribute/DeleteForm.php | 92 ----- .../linkit/src/Form/Attribute/EditForm.php | 96 ----- .../src/Form/Attribute/OverviewForm.php | 156 --------- .../linkit/src/Form/LinkitEditorDialog.php | 207 ----------- .../linkit/src/Form/Matcher/AddForm.php | 10 - .../linkit/src/Form/Matcher/DeleteForm.php | 5 - .../linkit/src/Form/Matcher/EditForm.php | 22 +- .../linkit/src/Form/Matcher/OverviewForm.php | 19 +- .../linkit/src/Form/Profile/AddForm.php | 5 - .../linkit/src/Form/Profile/EditForm.php | 7 +- .../linkit/src/Form/Profile/FormBase.php | 15 +- .../contrib/fields/linkit/src/MatcherBase.php | 19 +- .../fields/linkit/src/MatcherCollection.php | 14 - .../fields/linkit/src/MatcherInterface.php | 23 +- .../fields/linkit/src/MatcherManager.php | 5 - .../fields/linkit/src/MatcherTokensTrait.php | 30 +- .../src/Plugin/CKEditorPlugin/Linkit.php | 123 ------- .../CKEditorPlugin/LinkitDrupalLink.php | 111 ++++++ .../Derivative/EntityMatcherDeriver.php | 35 +- .../linkit/src/Plugin/Filter/LinkitFilter.php | 156 +++++++++ .../src/Plugin/Linkit/Attribute/Accesskey.php | 38 -- .../src/Plugin/Linkit/Attribute/Clazz.php | 41 --- .../linkit/src/Plugin/Linkit/Attribute/Id.php | 38 -- .../Plugin/Linkit/Attribute/Relationship.php | 38 -- .../src/Plugin/Linkit/Attribute/Target.php | 96 ----- .../src/Plugin/Linkit/Attribute/Title.php | 82 ----- .../Linkit/Matcher/ContactFormMatcher.php | 38 ++ .../Plugin/Linkit/Matcher/EmailMatcher.php | 40 +++ .../Plugin/Linkit/Matcher/EntityMatcher.php | 328 +++++++++++++----- .../src/Plugin/Linkit/Matcher/FileMatcher.php | 103 ++++-- .../Linkit/Matcher/FrontPageMatcher.php | 40 +++ .../src/Plugin/Linkit/Matcher/NodeMatcher.php | 29 +- .../src/Plugin/Linkit/Matcher/TermMatcher.php | 14 +- .../src/Plugin/Linkit/Matcher/UserMatcher.php | 52 +-- .../Plugin/Linkit/Substitution/Canonical.php | 34 ++ .../src/Plugin/Linkit/Substitution/File.php | 39 +++ .../src/Plugin/Linkit/Substitution/Media.php | 100 ++++++ .../fields/linkit/src/ProfileInterface.php | 59 +--- .../fields/linkit/src/ProfileListBuilder.php | 25 +- .../fields/linkit/src/ResultManager.php | 74 ---- .../linkit/src/SubstitutionInterface.php | 36 ++ .../fields/linkit/src/SubstitutionManager.php | 77 ++++ .../src/SubstitutionManagerInterface.php | 28 ++ .../src/Suggestion/DescriptionSuggestion.php | 44 +++ .../src/Suggestion/EntitySuggestion.php | 81 +++++ .../src/Suggestion/SimpleSuggestion.php | 87 +++++ .../src/Suggestion/SuggestionCollection.php | 56 +++ .../SuggestionDescriptionInterface.php | 28 ++ .../src/Suggestion/SuggestionInterface.php | 64 ++++ .../fields/linkit/src/SuggestionManager.php | 63 ++++ .../linkit/src/Tests/AttributeCrudTest.php | 160 --------- .../Controllers/LinkitControllerTest.php | 83 ----- .../linkit/src/Tests/LinkitTestBase.php | 83 ----- .../linkit/src/Tests/MatcherCrudTest.php | 158 --------- .../src/Tests/Matchers/NodeMatcherTest.php | 105 ------ .../src/Tests/Matchers/UserMatcherTest.php | 114 ------ .../linkit/src/Tests/ProfileCreationTrait.php | 44 +++ .../linkit/src/Tests/ProfileCrudTest.php | 125 ------- .../src/Tests/Update/LinkitUpdateTest.php | 152 ++++++++ .../fields/linkit/src/Utility/LinkitXss.php | 7 +- .../update/editor.editor.format_1.yml | 54 +++ .../update/editor.editor.format_2.yml | 53 +++ .../update/editor.editor.format_3.yml | 25 ++ .../update/filter.format.format_1.yml | 17 + .../update/filter.format.format_2.yml | 8 + .../update/filter.format.format_3.yml | 17 + .../fixtures/update/linkit-additions.php | 73 ++++ .../linkit.linkit_profile.test_profile.yml | 47 +++ ....linkit_profile.test_profile_with_imce.yml | 24 ++ .../config/schema/linkit_test.schema.yml | 8 - .../tests/linkit_test/linkit_test.info.yml | 12 +- .../tests/linkit_test/linkit_test.module | 10 - .../Attribute/ConfigurableDummyAttribute.php | 73 ---- .../Linkit/Attribute/DummyAttribute.php | 37 -- .../Matcher/ConfigurableDummyMatcher.php | 40 +-- .../Plugin/Linkit/Matcher/DummyMatcher.php | 37 +- .../Controllers/LinkitControllerTest.php | 60 ++++ .../src/Functional/LinkitBrowserTestBase.php | 48 +++ .../tests/src/Functional/MatcherAdminTest.php | 138 ++++++++ .../tests/src/Functional/ProfileAdminTest.php | 128 +++++++ .../FunctionalJavascript/LinkitDialogTest.php | 320 +++++++++++++++++ .../LinkitFormatAdminTest.php | 59 ++++ .../src/Kernel/AssertLinkitFilterTrait.php | 83 +++++ .../tests/src/Kernel/Entity/ProfileTest.php | 32 ++ .../src/Kernel/EntityMatcherDeriverTest.php | 49 +++ .../src/Kernel/LinkitAutocompleteTest.php | 259 ++++++++++++++ .../src/Kernel/LinkitEditorLinkDialogTest.php | 243 +++++++++++++ .../src/Kernel/LinkitFilterEntityTest.php | 148 ++++++++ .../tests/src/Kernel/LinkitKernelTestBase.php | 71 ++++ .../Matchers/ContactFormMatcherTest.php | 58 ++++ .../src/Kernel/Matchers/FileMatcherTest.php | 113 ++++++ .../src/Kernel/Matchers/NodeMatcherTest.php | 160 +++++++++ .../src/Kernel}/Matchers/TermMatcherTest.php | 163 +++++---- .../src/Kernel/Matchers/UserMatcherTest.php | 138 ++++++++ .../src/Kernel/SubstitutionPluginTest.php | 181 ++++++++++ .../config/sync/editor.editor.wysiwyg.yml | 6 +- .../config/sync/filter.format.wysiwyg.yml | 10 +- .../sync/linkit.linkit_profile.collection.yml | 6 +- 136 files changed, 5138 insertions(+), 3860 deletions(-) create mode 100644 sites/all/modules/contrib/fields/linkit/config/optional/linkit.linkit_profile.default.yml create mode 100644 sites/all/modules/contrib/fields/linkit/images/throbber-active.gif create mode 100644 sites/all/modules/contrib/fields/linkit/images/throbber-inactive.png delete mode 100644 sites/all/modules/contrib/fields/linkit/js/attribute/title.js create mode 100644 sites/all/modules/contrib/fields/linkit/js/linkit.filter_html.admin.js delete mode 100644 sites/all/modules/contrib/fields/linkit/js/linkit.imce.js delete mode 100644 sites/all/modules/contrib/fields/linkit/js/plugins/linkit/linkit.png delete mode 100644 sites/all/modules/contrib/fields/linkit/js/plugins/linkit/plugin.js delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Annotation/Substitution.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/AttributeBase.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/AttributeManager.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeInterface.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/Linkit.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/LinkitDrupalLink.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Filter/LinkitFilter.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FrontPageMatcher.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Canonical.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/File.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Media.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/ResultManager.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/SubstitutionInterface.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/SubstitutionManager.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/SubstitutionManagerInterface.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/DescriptionSuggestion.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/EntitySuggestion.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/SimpleSuggestion.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionCollection.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionDescriptionInterface.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionInterface.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/SuggestionManager.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/AttributeCrudTest.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/Controllers/LinkitControllerTest.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/LinkitTestBase.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/MatcherCrudTest.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/NodeMatcherTest.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/UserMatcherTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCreationTrait.php delete mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCrudTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/src/Tests/Update/LinkitUpdateTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/editor.editor.format_1.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/editor.editor.format_2.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/editor.editor.format_3.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_1.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml create mode 100644 sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml delete mode 100644 sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php delete mode 100644 sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php rename sites/all/modules/contrib/fields/linkit/{src/Tests => tests/src/Kernel}/Matchers/TermMatcherTest.php (51%) create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php create mode 100644 sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php diff --git a/sites/all/modules/contrib/fields/linkit/README.md b/sites/all/modules/contrib/fields/linkit/README.md index 7f610ba71..687ce4b3f 100644 --- a/sites/all/modules/contrib/fields/linkit/README.md +++ b/sites/all/modules/contrib/fields/linkit/README.md @@ -1,33 +1,54 @@ Linkit =========== -Linkit provides an **enriched linking experience for internal and external -linking** with editors by using an autocomplete field. Linkit has by default -support for nodes, users, taxonomy terms, files, comments and -**basic support for all types of entities** that defines a canonical link -template. +Linkit provides an **enriched linking experience for internal and +external linking** with editors by using an autocomplete field. Linkit +has by default support for nodes, users, taxonomy terms, files, +comments and **basic support for all types of entities** that defines a +canonical link template. Installation ------------ * Normal module installation procedure. See - https://www.drupal.org/documentation/install/modules-themes/modules-8 +https://www.drupal.org/documentation/install/modules-themes/modules-8 + +* **Enable Linkit** +To enable Linkit, go to `/admin/config/content/formats` and edit the +desired text format you want to enable Linkit for. Linkit will alter +the default link plugin, so make sure that it is enabled. When the +default link plugin is enabled, you will have to select a Linkit +profile to use in the "Drupal link" tab under the toolbar configuration. + +* **Enable Linkit filter** +Linkit will insert URLs in a format like "entity:node/1". The Linkit +filter will then transform that URL into a "real" URL when rendering +the text. **Note: The Linkit filter must run before "Limit allowed HTML +tags and correct faulty HTML"**. + +* If the **Limit allowed HTML tags and correct faulty HTML** filter is +enabled, add *data-entity-type* and *data-entity-uuid* to the `` tag +in the *Allowed HTML* tags (i.e. ``). + +* (optional) **Use automatic titles with the Linkit filter** +If automatic titles is enabled in the Linkit filter settings, and +**Limit allowed HTML tags and correct faulty HTML** is enabled, add +*title* to the `` tag in the *Allowed HTML* tags (i.e. +``). Configuration ------------ -After the installation, you have to create a Linkit profile. The profile will -contain information about which plugins to use. -Profiles can be created at `/admin/config/content/linkit` +A default Linkit profile will have been installed as a step in the +module installation process. The profile will contain information about +which plugins to use. -When you have created a profile, you need to enable the Linkit plugin on the -text format you want to use. Formats are found at -`admin/config/content/formats`. +You can create additional profiles at `/admin/config/content/linkit`. Plugins examples ------------ -There are plugin implementation examples in the linkit_test module bundled with -Linkit core. +There are plugin implementation examples in the linkit_test module +bundled with Linkit core. diff --git a/sites/all/modules/contrib/fields/linkit/config/optional/linkit.linkit_profile.default.yml b/sites/all/modules/contrib/fields/linkit/config/optional/linkit.linkit_profile.default.yml new file mode 100644 index 000000000..7aa4092fa --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/config/optional/linkit.linkit_profile.default.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node +id: default +label: Default +description: 'A default Linkit profile' +matchers: + 556010a3-e317-48b3-b4ed-854c10f4b950: + uuid: 556010a3-e317-48b3-b4ed-854c10f4b950 + id: 'entity:node' + weight: 0 + settings: + metadata: 'by [node:author] | [node:created:medium]' + bundles: { } + group_by_bundle: false + include_unpublished: false + substitution_type: canonical diff --git a/sites/all/modules/contrib/fields/linkit/config/schema/linkit.schema.yml b/sites/all/modules/contrib/fields/linkit/config/schema/linkit.schema.yml index 1e63f0262..882a2f1cb 100644 --- a/sites/all/modules/contrib/fields/linkit/config/schema/linkit.schema.yml +++ b/sites/all/modules/contrib/fields/linkit/config/schema/linkit.schema.yml @@ -10,43 +10,11 @@ linkit.linkit_profile.*: type: string description: type: string - attributes: - type: sequence - sequence: - type: linkit.attribute matchers: type: sequence sequence: type: linkit.matcher -linkit.attribute: - type: mapping - mapping: - id: - type: string - settings: - type: linkit.attribute.[%parent.id] - weight: - type: integer - -linkit.attribute.*: - type: mapping - label: 'Attribute settings' - -# Plugin \Drupal\linkit\Plugin\Linkit\Attribute\Target -linkit.attribute.target: - type: linkit.attribute - mapping: - widget_type: - type: string - -# Plugin \Drupal\linkit\Plugin\Linkit\Attribute\Title -linkit.attribute.title: - type: linkit.attribute - mapping: - automatic_title: - type: boolean - linkit.matcher: type: mapping mapping: @@ -66,7 +34,7 @@ linkit.matcher.*: linkit.matcher.entity: type: mapping mapping: - result_description: + metadata: type: string bundles: type: sequence @@ -75,6 +43,8 @@ linkit.matcher.entity: nullable: true group_by_bundle: type: boolean + substitution_type: + type: string linkit.matcher.entity:*: type: linkit.matcher.entity @@ -83,6 +53,11 @@ linkit.matcher.entity:*: linkit.matcher.entity:file: type: linkit.matcher.entity mapping: + file_extensions: + type: string + file_status: + type: integer + default: 1 images: type: mapping mapping: @@ -113,19 +88,25 @@ linkit.matcher.entity:user: include_blocked: type: boolean -# Third party settings on behalf of the imce module. -linkit.linkit_profile.*.third_party.imce: - type: mapping +# Plugin \Drupal\linkit\Plugin\Filter\LinkitFilter +filter_settings.linkit: + type: filter + label: 'Linkit' mapping: - use: + title: type: boolean - scheme: - type: string + label: 'Automatically set the "title" attribute' -ckeditor.plugin.linkit: +# Plugin \Drupal\ckeditor\Plugin\CKEditorPlugin\DrupalLink +# Linkit alters the plugin to save Linkit specific information used by the +# altered plugin. +ckeditor.plugin.drupallink: type: mapping - label: 'Profile dropdown' + label: 'Drupal link' mapping: + linkit_enabled: + type: boolean + label: 'Use Linkit' linkit_profile: type: string - label: 'List of profiles' + label: 'Linkit profile' diff --git a/sites/all/modules/contrib/fields/linkit/css/linkit.admin.theme.css b/sites/all/modules/contrib/fields/linkit/css/linkit.admin.theme.css index c4afd11b9..7a668a78e 100644 --- a/sites/all/modules/contrib/fields/linkit/css/linkit.admin.theme.css +++ b/sites/all/modules/contrib/fields/linkit/css/linkit.admin.theme.css @@ -9,7 +9,6 @@ line-height: 1.2em; } -.linkit-matcher-add-form tbody td:first-child, -.linkit-attribute-add-form tbody td:first-child { +.linkit-matcher-add-form tbody td:first-child { width: 1%; } diff --git a/sites/all/modules/contrib/fields/linkit/css/linkit.autocomplete.css b/sites/all/modules/contrib/fields/linkit/css/linkit.autocomplete.css index 806e98a2e..4159a495f 100644 --- a/sites/all/modules/contrib/fields/linkit/css/linkit.autocomplete.css +++ b/sites/all/modules/contrib/fields/linkit/css/linkit.autocomplete.css @@ -3,48 +3,55 @@ * Stylesheet for the Linkit module. */ .js input.form-linkit-autocomplete { - background-image: url(/core/misc/throbber-inactive.png); + background-image: url(../images/throbber-inactive.png); background-position: 100% center; /* LTR */ background-repeat: no-repeat; } + .js[dir="rtl"] input.form-linkit-autocomplete { - background-position: 0% center; + background-position: 0 center; } + .js input.form-linkit-autocomplete.ui-autocomplete-loading { - background-image: url(/core/misc/throbber-active.gif); + background-image: url(../images/throbber-active.gif); background-position: 100% center; /* LTR */ } + .js[dir="rtl"] input.form-linkit-autocomplete.ui-autocomplete-loading { - background-position: 0% center; + background-position: 0 center; } /* Override the default jQuery UI theme */ .linkit-ui-autocomplete { - max-height: 330px; + max-height: calc((100vh - 80px)/2); overflow: auto; } -.linkit-ui-autocomplete.ui-widget { + +.linkit-ui-autocomplete.ui-widget { font-size: .9em; } -.linkit-ui-autocomplete.ui-menu .ui-menu-item { - list-style: none; +.linkit-ui-autocomplete.ui-menu .linkit-result-line-wrapper { + margin: 0; padding: 5px 7px; } -.linkit-ui-autocomplete .ui-menu-item.ui-state-focus { - margin: 0; +.linkit-ui-autocomplete.ui-menu .linkit-result-line-wrapper.ui-state-focus, +.linkit-ui-autocomplete.ui-menu .linkit-result-line-wrapper.ui-state-active { border: 0; border-bottom: 1px solid #bfbfbf; background: #0075ba; color: #fff; } -.linkit-result:not(:last-of-type) { +.linkit-result-line:not(:last-of-type) { border-bottom: 1px solid #bfbfbf; } -.linkit-result--group { +.ui-menu .linkit-result-line--group.ui-menu-divider { + margin: 0; + height: auto; + line-height: inherit; padding: 3px; background-color: #e7e7e7; border-bottom: 1px solid #bfbfbf; @@ -54,16 +61,17 @@ color: #555; } -.linkit-result--title { +.linkit-result-line--title { + display: block; font-weight: 600; } -.linkit-result--description { +.linkit-result-line--description { display: block; font-size: 0.9em; line-height: 1.3; } -.linkit-result--description img { +.linkit-result-line--description img { display: block; } diff --git a/sites/all/modules/contrib/fields/linkit/images/throbber-active.gif b/sites/all/modules/contrib/fields/linkit/images/throbber-active.gif new file mode 100644 index 0000000000000000000000000000000000000000..abf5c5d5b0e72ad28b5c8848af2a75dffad799c3 GIT binary patch literal 1275 zcmZ?wbhEHb6lCCKXc1!Isowkk`~SW7-hco8|Jw8K64l4HUVAUoa_rQj&p@%LMVCz{ zoa)~HaKX9f+3RmSfB)TW&N+_az5j^@ivPL&TtkAL9RpmA^bD9885kH8f3mQ$F~~FM z0ND&6XE3lPK2Yytd2DiWMIWcg-t|Ijl9*f$2)_L7u)CW@`H;g48EvL_ijqbu9oKWN zbXchPDqTwru-tNU`IFNDyz7OU4{hiz@$_C}BQ>+Hp|kR!*XF$ne0sJf^88H(d}S>x zyy}|Tir8%R0@~_vxaQ!Bb#D&To&V_Cy{W_dSJ$Nim)7gfs);TNOcx8L&oIqDdGVxT z(26y@q1U*Icen)#CT(N(h%@@&H|5`rg6wHYJEiBvVKv?fX#DvZJsLB+o>p}QSgl#9 zqR7x&b5Vn{Th3uq(1xCg%)M+0I<9;n*&DT<1~J8HZ@tmEXN#_>8rOxmP0!hL{93Vw zl`lA~dNO7$NjlJVK-_vl#hxE$g^aX3JN%DKwW?+5QF)x^Fjqn;BSq?`gM0Wy$Ah5; zfqTL~IH#;FSmE-9*|3hU`FitHjr|qNjkQ>?g$u|AlyEW9d%1dZzg~y!-NPRzc!f_(p09<-$(K^+yq_9UYiHJ+^&ua( z3C|728sr{8bB{bn3!7;lrFX8p?0!IC0nZ9y=Pfdtfxge$6@OltppwzjmGMxhM|aVO zx3WsR4nO#sVA-(aQsz`HMr^?XN-igkBPAE4V3`7Gtii8d QUDq)2Trtt`a76}d0HUD?6#xJL literal 0 HcmV?d00001 diff --git a/sites/all/modules/contrib/fields/linkit/images/throbber-inactive.png b/sites/all/modules/contrib/fields/linkit/images/throbber-inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..befbb9f0a1ec779fbce224f57e8cc2c87328fcb4 GIT binary patch literal 356 zcmeAS@N?(olHy`uVBq!ia0vp^f*>{r8<6y`Y?T61Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPqhqSN>d&V;JyFj6jo-U3d8t3OuR-AlPfv08qY~h1~ zoi1V9>=)YqI~k^=t=z2K7rZA^{_WX2u0|)1r$x%hd4YCjy6 zecIC5rR|x7^0G{+g!}UwuD@nAW)^Im>FA=d)FD(+DIj#qwOPgI?m88n%m4Y=CO$9Z z>b6|zGdz~hyAQ1|p4`#U0rZQ(=ICjx3_&eY*Giq(fTS86F0Wr9ECi%E9Hw zS|^UX`votxTfbSki|PGej+aKRPd2@eEj!m`r>J*~!}##N_slEy^D!)$qPK77@;N1w w&s)CCUjMqQ*zezz8&fVVcqH~|{{GL*d element that the newly created
  • element must be appended to. * @param {object} item + * The list item to append. * * @return {object} + * jQuery collection of the ul element. */ function renderItem(ul, item) { - var $line = $('
  • ').addClass('linkit-result'); - $line.append($('').html(item.title).addClass('linkit-result--title')); + var $line = $('
  • ').addClass('linkit-result-line'); + var $wrapper = $('
    ').addClass('linkit-result-line-wrapper'); + $wrapper.append($('').html(item.label).addClass('linkit-result-line--title')); - if (item.description !== null) { - $line.append($('').html(item.description).addClass('linkit-result--description')); + if (item.hasOwnProperty('description')) { + $wrapper.append($('').html(item.description).addClass('linkit-result-line--description')); } - - return $line.appendTo(ul); + return $line.append($wrapper).appendTo(ul); } /** @@ -105,7 +124,7 @@ $.each(grouped_items, function (group, items) { if (group.length) { - ul.append('
  • ' + group + '
  • '); + ul.append('
  • ' + group + '
  • '); } $.each(items, function (index, item) { @@ -114,20 +133,35 @@ }); } + function focusHandler() { + return false; + } + + function searchHandler(event) { + var options = autocomplete.options; + + return !options.isComposing; + } + /** * Attaches the autocomplete behavior to all required fields. * * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches the autocomplete behaviors. + * @prop {Drupal~behaviorDetach} detach + * Detaches the autocomplete behaviors. */ Drupal.behaviors.linkit_autocomplete = { attach: function (context) { - // Act on textfields with the "form-autocomplete" class. + // Act on textfields with the "form-linkit-autocomplete" class. var $autocomplete = $(context).find('input.form-linkit-autocomplete').once('linkit-autocomplete'); if ($autocomplete.length) { $.widget('custom.autocomplete', $.ui.autocomplete, { _create: function () { this._super(); - this.widget().menu('option', 'items', '> :not(.linkit-result--group)'); + this.widget().menu('option', 'items', '> :not(.linkit-result-line--group)'); }, _renderMenu: autocomplete.options.renderMenu, _renderItem: autocomplete.options.renderItem @@ -136,6 +170,17 @@ // Use jQuery UI Autocomplete on the textfield. $autocomplete.autocomplete(autocomplete.options); $autocomplete.autocomplete('widget').addClass('linkit-ui-autocomplete'); + + $autocomplete.click(function () { + $autocomplete.autocomplete('search', $autocomplete.val()); + }); + + $autocomplete.on('compositionstart.autocomplete', function () { + autocomplete.options.isComposing = true; + }); + $autocomplete.on('compositionend.autocomplete', function () { + autocomplete.options.isComposing = false; + }); } }, detach: function (context, settings, trigger) { @@ -154,14 +199,17 @@ cache: {}, options: { source: sourceData, + focus: focusHandler, + search: searchHandler, + select: selectHandler, renderItem: renderItem, renderMenu: renderMenu, - select: selectHandler, - minLength: 1 + minLength: 1, + isComposing: false }, ajax: { dataType: 'json' } }; -})(jQuery, Drupal, _, document); +})(jQuery, Drupal, _); diff --git a/sites/all/modules/contrib/fields/linkit/js/linkit.filter_html.admin.js b/sites/all/modules/contrib/fields/linkit/js/linkit.filter_html.admin.js new file mode 100644 index 000000000..3807f6edd --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/js/linkit.filter_html.admin.js @@ -0,0 +1,51 @@ +/** + * @file + * Send events to add or remove a tags to the filter_html allowed tags. + */ + +(function ($, Drupal, document) { + + 'use strict'; + + /** + * When enabling the linkit filter, also add linkit rules to filter_html. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches linkitFilterHtml behavior. + */ + Drupal.behaviors.linkitFilterHtml = { + attach: function (context) { + var selector = '[data-drupal-selector="edit-filters-linkit-status"]'; + var feature = editorFeature(); + $(context).find(selector).once('filters-linkit-status').each(function () { + $(this).on('click', function () { + var eventName = $(this).is(':checked') ? 'drupalEditorFeatureAdded' : 'drupalEditorFeatureRemoved'; + $(document).trigger(eventName, feature); + }); + }); + } + }; + + /** + * Returns a editor feature. + * + * @return {Drupal.EditorFeature} + * A editor feature with linkit specific tags and attributes. + */ + function editorFeature() { + var linkitFeature = new Drupal.EditorFeature('linkit'); + var rule = new Drupal.EditorFeatureHTMLRule(); + // Tags. + rule.required.tags = ['a']; + rule.allowed.tags = ['a']; + // Attributes. + rule.required.attributes = ['data-entity-substitution', 'data-entity-type', 'data-entity-uuid', 'title']; + rule.allowed.attributes = ['data-entity-substitution', 'data-entity-type', 'data-entity-uuid', 'title']; + + linkitFeature.addHTMLRule(rule); + return linkitFeature; + } + +})(jQuery, Drupal, document); diff --git a/sites/all/modules/contrib/fields/linkit/js/linkit.imce.js b/sites/all/modules/contrib/fields/linkit/js/linkit.imce.js deleted file mode 100644 index 3682483de..000000000 --- a/sites/all/modules/contrib/fields/linkit/js/linkit.imce.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file - * IMCE integration for Linkit. - */ - -(function ($, Drupal, drupalSettings) { - - 'use strict'; - - /** - * @namespace - * - * Need to be in the global namespace, otherwise the IMCE window will not show - * the 'select' button in the toolbar. - */ - var linkitImce = window.linkitImce = {}; - - /** - * Drupal behavior to handle imce linkit integration. - */ - Drupal.behaviors.linkitImce = { - attach: function (context, settings) { - var $link = $(context).find('.linkit-imce-open').once('linkit-imce-open'); - if ($link.length) { - $link.bind('click', function (event) { - event.preventDefault(); - window.open($(this).attr('href'), '', 'width=760,height=560,resizable=1'); - }); - } - } - }; - - /** - * Handler for imce sendto operation. - */ - linkitImce.sendto = function (file, win) { - var imce = win.imce; - var items = imce.getSelection(); - - if (imce.countSelection() > 1) { - imce.setMessage(Drupal.t('You can only select one file.')); - return; - } - var path = imce.getConf('root_url') + '/' + imce.getItemPath(items[0]); - $('[data-drupal-selector="edit-attributes-href"]').val(path); - win.close(); - }; - - -})(jQuery, Drupal, drupalSettings); - - diff --git a/sites/all/modules/contrib/fields/linkit/js/plugins/linkit/linkit.png b/sites/all/modules/contrib/fields/linkit/js/plugins/linkit/linkit.png deleted file mode 100644 index 90fc72ee76c345a5187705319d0eb10cd07f11ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmV+$0_6RPP)h2PKWK(;=FKji~5VX@U}NzjWKMNu9s7RyN{lR2h2C>o7sz~&jKpBvSoQ3Uwa zd?8PkSC&aI7$mYR6Svz<91aI@xm*$EpxtioB@ziCm&>{Jo<7Eu!JH_H7pYY0G876$ zAZG!9N~IEVI-N`ymKzp;>Ih&TP&Yb&SfU670;~tdyK=cq;GqxZp#R)oJJ0iXpw82K z_{<*%X0!Qz=&vFppG+oi`)BwY{SX=XA97Ft*2Q!>edYCfAE<4*(=+gqLHPqYnhYoa dKE8KW`~_Z;Ri 0) { - var value = returnValues.attributes[attrName]; - linkElement.data('cke-saved-' + attrName, value); - linkElement.setAttribute(attrName, value); - } - // Delete the property if set to an empty string. - else { - linkElement.removeAttribute(attrName); - } - } - } - } - - // Save snapshot for undo support. - editor.fire('saveSnapshot'); - }; - // Drupal.t() will not work inside CKEditor plugins because CKEditor - // loads the JavaScript file instead of Drupal. Pull translated - // strings from the plugin settings that are translated server-side. - var dialogSettings = { - title: linkElement ? editor.config.linkit_dialogTitleAdd : editor.config.linkit_dialogTitleEdit, - dialogClass: 'editor-linkit-dialog' - }; - - // Open the dialog for the edit form. - Drupal.ckeditor.openDialog(editor, Drupal.url('linkit/dialog/linkit/' + editor.config.drupal.format), existingValues, saveCallback, dialogSettings); - } - }); - - // CTRL + L. - editor.setKeystroke(CKEDITOR.CTRL + 76, 'linkit'); - - // Add buttons. - if (editor.ui.addButton) { - editor.ui.addButton('Linkit', { - label: Drupal.t('Link'), - command: 'linkit', - icon: this.path + '/linkit.png' - }); - } - - editor.on('doubleclick', function (evt) { - var element = getSelectedLink(editor) || evt.data.element; - - if (!element.isReadOnly()) { - if (element.is('a')) { - editor.getSelection().selectElement(element); - editor.getCommand('linkit').exec(); - } - } - }); - - // If the "menu" plugin is loaded, register the menu items. - if (editor.addMenuItems) { - editor.addMenuItems({ - linkit: { - label: Drupal.t('Edit Link'), - command: 'linkit', - group: 'link', - order: 1 - } - }); - } - - // If the "contextmenu" plugin is loaded, register the listeners. - if (editor.contextMenu) { - editor.contextMenu.addListener(function (element, selection) { - if (!element || element.isReadOnly()) { - return null; - } - var anchor = getSelectedLink(editor); - if (!anchor) { - return null; - } - - var menu = {}; - if (anchor.getAttribute('href') && anchor.getChildCount()) { - menu = { - linkit: CKEDITOR.TRISTATE_OFF - }; - } - return menu; - }); - } - } - }); - - /** - * Get the surrounding link element of current selection. - * - * The following selection will all return the link element. - * - * @example - *
    li^nk - * [link] - * text[link] - * li[nk] - * [li]nk] - * [li]nk - * - * @param {CKEDITOR.editor} editor - * The CKEditor editor object - * - * @return {?HTMLElement} - * The selected link element, or null. - * - */ - function getSelectedLink(editor) { - var selection = editor.getSelection(); - var selectedElement = selection.getSelectedElement(); - if (selectedElement && selectedElement.is('a')) { - return selectedElement; - } - - var range = selection.getRanges(true)[0]; - - if (range) { - range.shrink(CKEDITOR.SHRINK_TEXT); - return editor.elementPath(range.getCommonAncestor()).contains('a', 1); - } - return null; - } - -})(jQuery, Drupal, drupalSettings, CKEDITOR); diff --git a/sites/all/modules/contrib/fields/linkit/linkit.info.yml b/sites/all/modules/contrib/fields/linkit/linkit.info.yml index 0a1f31ca7..8fb636780 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.info.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.info.yml @@ -1,12 +1,14 @@ name: Linkit -description: Linkit -package: Custom type: module +description: 'Provides an easy interface for internal and external linking with wysiwyg editors.' +package: User interface # core: 8.x configure: entity.linkit_profile.collection +test_dependencies: + - imce -# Information added by Drupal.org packaging script on 2017-03-21 -version: '8.x-4.3' +# Information added by Drupal.org packaging script on 2018-03-08 +version: '8.x-5.0-beta7' core: '8.x' project: 'linkit' -datestamp: 1490127367 +datestamp: 1520552594 diff --git a/sites/all/modules/contrib/fields/linkit/linkit.install b/sites/all/modules/contrib/fields/linkit/linkit.install index 0f3bacf74..bf4dc35be 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.install +++ b/sites/all/modules/contrib/fields/linkit/linkit.install @@ -2,5 +2,194 @@ /** * @file - * Installation functions for Linkit module. + * Contains install and update functions for Linkit. */ + +/** + * Implements hook_uninstall(). + */ +function linkit_uninstall() { + $config_factory = \Drupal::configFactory(); + + // Remove the image styles that Linkit has installed. + $config_factory->getEditable('image.style.linkit_result_thumbnail')->delete(); +} + +/** + * Updates Linkit from 4 to 5. + * + * Removes linkit profile attributes. + * Replaces the linkit ckeditor plugin with drupallink. + * Enables the linkit filter on text formats where linkit is used. + * Adds 'data-entity-type' and 'data-entity-uuid' attributes to the tag + * if filter_html is activated. + */ +function linkit_update_8500() { + $config_factory = \Drupal::configFactory(); + + // Iterate on all profile configuration entities. + foreach ($config_factory->listAll('linkit.linkit_profile.') as $id) { + $profile = $config_factory->getEditable($id); + // Remove all attributes. + $profile->clear('attributes')->save(TRUE); + } + + // An array that will be filled with text format ids that we should enable the + // new linkit_filter for. + $linkit_enabled_formats = []; + + // Iterate on all editor configuration entities. + foreach ($config_factory->listAll('editor.editor.') as $id) { + $editor_config = $config_factory->getEditable($id); + + // Save the old settings. + $old_linkit_settings = $editor_config->get('settings.plugins.linkit'); + + $drupal_link_in_use = FALSE; + $old_linkit_button_path = NULL; + + // If the editor has old linkit settings, perform update tasks. + if (!is_null($old_linkit_settings)) { + // Remove the old linkit settings. + $editor_config->clear('settings.plugins.linkit'); + $editor_config->save(TRUE); + + // Add the format id that the editor is using. + $linkit_enabled_formats[] = $editor_config->get('format'); + + // Remove the old linkit plugin from the toolbar, and check if DrupalLink + // is present in the toolbar as linkit now extends this plugin. + $toolbar_rows = $editor_config->get('settings.toolbar.rows'); + foreach ($toolbar_rows as $row_index => $row) { + foreach ($row as $button_group_index => $button_group) { + foreach ($button_group['items'] as $item__name) { + if ($item__name === 'Linkit') { + $old_linkit_button_path = 'settings.toolbar.rows.' . $row_index . '.' . $button_group_index . '.items'; + } + + if ($item__name === 'DrupalLink') { + $drupal_link_in_use = TRUE; + } + } + } + } + + if ($old_linkit_button_path) { + $buttons = $editor_config->get($old_linkit_button_path); + $index = array_search('Linkit', $buttons); + // If the DrupalLink plugin is not present in the toolbar, lets add it + // in the same button group as the old linkit plugin was in. + if (!$drupal_link_in_use) { + $buttons[$index] = 'DrupalLink'; + } + else { + unset($buttons[$index]); + } + $editor_config->set($old_linkit_button_path, array_values($buttons)); + $editor_config->save(TRUE); + } + + // Set the linkit settings to the DrupalLink. + $drupal_link_settings = [ + 'linkit_enabled' => TRUE, + 'linkit_profile' => $old_linkit_settings['linkit_profile'], + ]; + $editor_config->set('settings.plugins.drupallink', $drupal_link_settings); + $editor_config->save(TRUE); + } + } + + // Enable the linkit_filter for all formats that is used with linkit. + foreach ($linkit_enabled_formats as $filter_id) { + $config = $config_factory->getEditable('filter.format.' . $filter_id); + $filter_html_weight = $config->get('filters.filter_html.weight'); + + $linkit_filter = [ + 'id' => 'linkit', + 'provider' => 'linkit', + 'status' => TRUE, + 'weight' => $filter_html_weight ? ($filter_html_weight - 1) : -15, + 'settings' => [ + 'title' => FALSE, + ], + ]; + $config->set('filters.linkit', $linkit_filter); + + $allowed_html = $config->get('filters.filter_html.settings.allowed_html'); + if (!empty($allowed_html)) { + preg_match_all('/<([\w]+)[^>]*>/', $allowed_html, $out); + $current_mapping = array_combine($out[1], $out[0]); + + if (isset($current_mapping['a'])) { + $allowed_html = str_replace($current_mapping['a'], str_replace('>', ' data-entity-type data-entity-uuid>', $current_mapping['a']), $allowed_html); + } + else { + $allowed_html .= ' '; + } + $config->set('filters.filter_html.settings.allowed_html', $allowed_html); + } + + $config->save(TRUE); + } +} + +/** + * Prepare anchor attributes for substitution plugins. + */ +function linkit_update_8501() { + $config_factory = \Drupal::configFactory(); + + // Update all filter formats that allow the data-entity-uuid attribute to also + // allow the data-entity-substitution attribute. + foreach ($config_factory->listAll('filter.format.') as $id) { + $filter = $config_factory->getEditable($id); + if ($allowed_html = $filter->get('filters.filter_html.settings.allowed_html')) { + $allowed_html = str_replace('data-entity-uuid', 'data-entity-uuid data-entity-substitution', $allowed_html); + $filter->set('filters.filter_html.settings.allowed_html', $allowed_html); + $filter->save(TRUE); + } + } + + // Update all "file" matchers to the "file" substitution plugin, to maintain + // existing behavior out of the box. + $config_factory = \Drupal::configFactory(); + foreach ($config_factory->listAll('linkit.linkit_profile.') as $id) { + $profile = $config_factory->getEditable($id); + foreach ($profile->get('matchers') as $key => $matcher) { + $settings = $profile->get('matchers.' . $key . '.settings'); + $settings['substitution_type'] = $matcher['id'] === 'entity:file' ? 'file' : 'canonical'; + $profile->set('matchers.' . $key . '.settings', $settings); + } + $profile->save(TRUE); + } +} + +/** + * Rename profile property 'result_description' to 'metadata'. + */ +function linkit_update_8502() { + $config_factory = \Drupal::configFactory(); + foreach ($config_factory->listAll('linkit.linkit_profile.') as $id) { + $profile = $config_factory->getEditable($id); + + foreach ($profile->get('matchers') as $key => $matcher) { + $old_value = $profile->get('matchers.' . $key . '.settings.result_description'); + $profile->set('matchers.' . $key . '.settings.metadata', $old_value); + $profile->clear('matchers.' . $key . '.settings.result_description'); + } + + $profile->save(TRUE); + } +} + +/** + * Remove imce integration settings. + */ +function linkit_update_8503() { + $config_factory = \Drupal::configFactory(); + foreach ($config_factory->listAll('linkit.linkit_profile.') as $id) { + $profile = $config_factory->getEditable($id); + $profile->clear('third_party_settings.imce'); + $profile->save(TRUE); + } +} diff --git a/sites/all/modules/contrib/fields/linkit/linkit.libraries.yml b/sites/all/modules/contrib/fields/linkit/linkit.libraries.yml index ad835e567..6f3bce370 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.libraries.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.libraries.yml @@ -26,18 +26,7 @@ linkit.autocomplete: - core/jquery.ui.autocomplete - core/underscore -linkit.attribute.title: +linkit.filter_html.admin: version: VERSION js: - js/attribute/title.js: {} - dependencies: - - linkit/linkit.base - - linkit/linkit.autocomplete - -linkit.imce: - version: VERSION - js: - js/linkit.imce.js: {} - dependencies: - - core/jquery.once - - linkit/linkit.base + js/linkit.filter_html.admin.js: {} diff --git a/sites/all/modules/contrib/fields/linkit/linkit.links.action.yml b/sites/all/modules/contrib/fields/linkit/linkit.links.action.yml index b29f51f6c..8b5c1fa56 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.links.action.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.links.action.yml @@ -9,10 +9,3 @@ linkit.matcher.add: title: 'Add matcher' appears_on: - linkit.matchers - -linkit.attribute.add: - route_name: linkit.attribute.add - title: 'Add attribute' - appears_on: - - linkit.attributes - diff --git a/sites/all/modules/contrib/fields/linkit/linkit.links.task.yml b/sites/all/modules/contrib/fields/linkit/linkit.links.task.yml index 671a9a503..39dde9353 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.links.task.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.links.task.yml @@ -8,8 +8,3 @@ linkit.matchers: title: 'Manage matchers' base_route: entity.linkit_profile.edit_form weight: 5 -linkit.attributes: - route_name: linkit.attributes - title: 'Manage attributes' - base_route: entity.linkit_profile.edit_form - weight: 10 diff --git a/sites/all/modules/contrib/fields/linkit/linkit.module b/sites/all/modules/contrib/fields/linkit/linkit.module index e7326997a..affeaebf4 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.module +++ b/sites/all/modules/contrib/fields/linkit/linkit.module @@ -2,108 +2,152 @@ /** * @file - * + * Linkit hook implementations. */ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\Core\Url; -use Drupal\linkit\ProfileInterface; /** * Implements hook_help(). */ function linkit_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { - case 'entity.linkit_profile.attributes': - return '

    ' . t('Attributes are HTML attributes that will be attached to the insert plugin.') . '

    '; - break; + case 'help.page.linkit': + $output = ''; + $output .= '

    ' . t('About') . '

    '; + $output .= '

    ' . t('The Linkit module provides an easy interface for internal and external linking with wysiwyg editors by using an autocomplete field.') . '

    '; + $output .= '

    ' . t('Uses') . '

    '; + $output .= '
    '; + $output .= '
    ' . t('Managing Linkit profiles') . '
    '; + $output .= '
    ' . t('You can create and edit Linkit profiles on the Linkit profile page. You can create a Linkit profile by clicking "Add profile".', [':profiles' => Url::fromRoute('entity.linkit_profile.collection')->toString(), ':add_profile' => Url::fromRoute('entity.linkit_profile.add_form')->toString()]) . '
    '; + $output .= '
    '; + return $output; + + case 'entity.linkit_profile.collection': + $output = '

    ' . t('Linkit profiles define how Linkit will operate on fields that have Linkit attached.') . '

    '; + $output .= '

    ' . t('The most common way to use Linkit is to enable Linkit on the Drupal Link plugin and associate a Linkit profile to it on a Text format.') . '

    '; + return $output; + + case 'linkit.matchers': + $output = '

    ' . t('Matchers defines how different data can be queried and displayed in the autocomplete suggestion list. Multiple matchers of the same type can be used at the same time to granulate the suggestions. The order of the added matchers defines in which order the suggestions will be presented.') . '

    '; + return $output; } } +/** + * Implements hook_ckeditor_plugin_info_alter(). + */ +function linkit_ckeditor_plugin_info_alter(array &$plugins) { + if (isset($plugins['drupallink'])) { + $plugins['drupallink']['class'] = "Drupal\\linkit\\Plugin\\CKEditorPlugin\\LinkitDrupalLink"; + } +} /** - * Implements hook_form_BASE_FORM_ID_alter() for linkit_profile_form on behalf - * of the 'imce' module. - * - * Adds IMCE settings to the form. - * - * @see imce_form_linkit_profile_form_builder() + * Implements hook_form_FORM_ID_alter(). */ -function imce_form_linkit_profile_form_alter(&$form, FormStateInterface $form_state) { - /** @var \Drupal\Linkit\ProfileInterface $linkit_profile */ - $linkit_profile = $form_state->getFormObject()->getEntity(); +function linkit_form_editor_link_dialog_alter(&$form, FormStateInterface $form_state, $form_id) { + // Alter only the form with ID 'editor_link_dialog'. + if ($form_id !== 'editor_link_dialog') { + return; + } - $form['imce'] = array( - '#type' => 'details', - '#title' => t('IMCE integration'), - '#group' => 'additional_settings', - ); + /** @var Drupal\filter\Entity\FilterFormat $filter_format */ + $filter_format = $form_state->getBuildInfo()['args'][0]; - $form['imce']['imce_use'] = array( - '#type' => 'checkbox', - '#title' => t('Enable IMCE File Browser in the editor dialog.'), - '#default_value' => $linkit_profile->getThirdPartySetting('imce', 'use', FALSE), - ); + /** @var \Drupal\Core\Entity\EntityStorageInterface $editorStorage */ + $editorStorage = Drupal::service('entity.manager')->getStorage('editor'); - $scheme_options = \Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::READ_VISIBLE); - $form['imce']['imce_scheme'] = array( - '#type' => 'radios', - '#title' => t('Scheme'), - '#options' => $scheme_options, - '#default_value' => $linkit_profile->getThirdPartySetting('imce', 'scheme', 'public'), - '#states' => [ - 'visible' => [ - ':input[name="imce_use"]' => ['checked' => TRUE], - ], + /** @var \Drupal\editor\EditorInterface $editor */ + $editor = $editorStorage->load($filter_format->id()); + $plugin_settings = $editor->getSettings()['plugins']['drupallink']; + + // Do not alter the form if Linkit is not enabled for this text format. + if (!isset($plugin_settings['linkit_enabled']) || (isset($plugin_settings['linkit_enabled']) && !$plugin_settings['linkit_enabled'])) { + return; + } + + $linkit_profile_id = $editor->getSettings()['plugins']['drupallink']['linkit_profile']; + + if (isset($form_state->getUserInput()['editor_object'])) { + $input = $form_state->getUserInput()['editor_object']; + $form_state->set('link_element', $input); + $form_state->setCached(TRUE); + } + else { + // Retrieve the link element's attributes from form state. + $input = $form_state->get('link_element') ?: []; + } + + $form['href_dirty_check'] = [ + '#type' => 'hidden', + '#default_value' => isset($input['href']) ? $input['href'] : '', + ]; + + $form['attributes']['href'] = array_merge($form['attributes']['href'], [ + '#type' => 'linkit', + '#description' => t('Start typing to find content.'), + '#autocomplete_route_name' => 'linkit.autocomplete', + '#autocomplete_route_parameters' => [ + 'linkit_profile_id' => $linkit_profile_id, ], - ); + "#weight" => -10, + '#default_value' => isset($input['href']) ? $input['href'] : '', + ]); - $form['#entity_builders'][] = 'imce_form_linkit_profile_form_builder'; -} + $fields = [ + 'data-entity-type', + 'data-entity-uuid', + 'data-entity-substitution', + ]; -/** - * Entity builder for the linkit profile form with imce options. - * - * @see imce_form_linkit_profile_form_alter(). - */ -function imce_form_linkit_profile_form_builder($entity_type, ProfileInterface $linkit_profile, &$form, FormStateInterface $form_state) { - $linkit_profile->setThirdPartySetting('imce', 'use', $form_state->getValue('imce_use')); - $linkit_profile->setThirdPartySetting('imce', 'scheme', $form_state->getValue('imce_scheme')); -} + $form['attributes']["#weight"] = -100; -/** - * Implements hook_form_BASE_FORM_ID_alter() for linkit_editor_dialog_form on - * behalf of the 'imce' module. - * - * Adds a button to open the imce file browser if it is enabled. - */ -function imce_form_linkit_editor_dialog_form_alter(&$form, FormStateInterface $form_state) { - /** @var \Drupal\Linkit\ProfileInterface $linkit_profile */ - $linkit_profile = $form_state->getFormObject()->getLinkitProfile(); - - if($linkit_profile->getThirdPartySetting('imce', 'use', FALSE)) { - $form['imce-link'] = [ - '#type' => 'link', - '#title' => t('Open IMCE file browser'), - '#url' => Url::fromRoute('imce.page', [ - 'scheme' => $linkit_profile->getThirdPartySetting('imce', 'scheme', 'public'), - ]), - '#options' => array( - 'query' => array( - 'sendto' => 'linkitImce.sendto', - ), - ), - '#attributes' => [ - 'class' => ['linkit-imce-open'], - ], - '#attached' => [ - 'library' => [ - 'linkit/linkit.imce' - ], - ], - '#weight' => 1, + foreach ($fields as $field_name) { + $form['attributes'][$field_name] = [ + '#title' => $field_name, + '#type' => 'hidden', + '#default_value' => isset($input[$field_name]) ? $input[$field_name] : '', ]; } + + // Add #submit callback that handles the data-* attributes. + array_unshift($form['#submit'], 'linkit_form_editor_link_dialog_submit'); +} + +/** + * Handles the data-* attributes and href replacement when appropriate. + */ +function linkit_form_editor_link_dialog_submit(array &$form, FormStateInterface $form_state) { + $link_element = $form_state->get('link_element'); + + $href = $form_state->getValue(['attributes', 'href']); + $href_dirty_check = $form_state->getValue(['href_dirty_check']); + + if ($href !== $href_dirty_check) { + $form_state->unsetValue(['attributes', 'data-entity-type']); + $form_state->unsetValue(['attributes', 'data-entity-uuid']); + $form_state->unsetValue(['attributes', 'data-entity-substitution']); + } + + $fields = [ + 'href', + 'data-entity-type', + 'data-entity-uuid', + 'data-entity-substitution', + ]; + + foreach ($fields as $field_name) { + $value = $form_state->getValue(['attributes', $field_name]); + if (empty($value)) { + if (!empty($link_element)) { + $form_state->setValue(['attributes', $field_name], ''); + } + else { + $form_state->unsetValue(['attributes', $field_name]); + } + } + } } diff --git a/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml b/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml index e56ef4f4a..830dcded9 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.permissions.yml @@ -1,2 +1,2 @@ administer linkit profiles: - title: 'Administer linkit profiles' \ No newline at end of file + title: 'Administer linkit profiles' diff --git a/sites/all/modules/contrib/fields/linkit/linkit.routing.yml b/sites/all/modules/contrib/fields/linkit/linkit.routing.yml index 035952c0a..6a0d68d19 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.routing.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.routing.yml @@ -29,37 +29,6 @@ entity.linkit_profile.delete_form: requirements: _permission: 'administer linkit profiles' -linkit.attributes: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes' - defaults: - _form: '\Drupal\linkit\Form\Attribute\OverviewForm' - _title: 'Manage attributes' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.add: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/add' - defaults: - _form: '\Drupal\linkit\Form\Attribute\AddForm' - _title: 'Add attribute' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.delete: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/{plugin_instance_id}/delete' - defaults: - _form: '\Drupal\linkit\Form\Attribute\DeleteForm' - requirements: - _permission: 'administer linkit profiles' - -linkit.attribute.edit: - path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes/{plugin_instance_id}' - defaults: - _form: '\Drupal\linkit\Form\Attribute\EditForm' - _title_callback: 'Drupal\linkit\Controller\LinkitController::attributeTitle' - requirements: - _permission: 'administer linkit profiles' - linkit.matchers: path: '/admin/config/content/linkit/manage/{linkit_profile}/matchers' defaults: @@ -91,21 +60,12 @@ linkit.matcher.edit: requirements: _permission: 'administer linkit profiles' -linkit.linkit_dialog: - path: '/linkit/dialog/linkit/{filter_format}' - defaults: - _form: '\Drupal\linkit\Form\LinkitEditorDialog' - _title: 'Add link' - requirements: - _entity_access: 'filter_format.use' - options: - _theme: ajax_base_page - linkit.autocomplete: path: '/linkit/autocomplete/{linkit_profile_id}' defaults: _controller: '\Drupal\linkit\Controller\AutocompleteController::autocomplete' requirements: + # Access is handled by the matchers. _access: 'TRUE' options: _theme: ajax_base_page diff --git a/sites/all/modules/contrib/fields/linkit/linkit.services.yml b/sites/all/modules/contrib/fields/linkit/linkit.services.yml index 1deeb8679..e18ca32d2 100644 --- a/sites/all/modules/contrib/fields/linkit/linkit.services.yml +++ b/sites/all/modules/contrib/fields/linkit/linkit.services.yml @@ -1,11 +1,10 @@ services: - plugin.manager.linkit.attribute: - class: Drupal\linkit\AttributeManager - parent: default_plugin_manager - plugin.manager.linkit.matcher: class: Drupal\linkit\MatcherManager parent: default_plugin_manager - - linkit.result_manager: - class: Drupal\linkit\ResultManager + plugin.manager.linkit.substitution: + class: Drupal\linkit\SubstitutionManager + arguments: ['@entity_type.manager'] + parent: default_plugin_manager + linkit.suggestion_manager: + class: Drupal\linkit\SuggestionManager diff --git a/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php b/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php deleted file mode 100644 index d22b34bcd..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Annotation/Attribute.php +++ /dev/null @@ -1,69 +0,0 @@ -setConfiguration($configuration); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration() { - return [ - 'id' => $this->getPluginId(), - 'weight' => $this->weight, - 'settings' => $this->configuration, - ]; - } - - /** - * {@inheritdoc} - */ - public function setConfiguration(array $configuration) { - $configuration += [ - 'weight' => '0', - 'settings' => [], - ]; - $this->configuration = $configuration['settings'] + $this->defaultConfiguration(); - $this->weight = $configuration['weight']; - return $this; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return []; - } - - /** - * {@inheritdoc} - */ - public function calculateDependencies() { - return []; - } - - /** - * {@inheritdoc} - */ - public function getLabel() { - return $this->pluginDefinition['label']; - } - - /** - * {@inheritdoc} - */ - public function getHtmlName() { - return $this->pluginDefinition['html_name']; - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return $this->pluginDefinition['description']; - } - - /** - * {@inheritdoc} - */ - public function getWeight() { - return $this->weight; - } - - /** - * {@inheritdoc} - */ - public function setWeight($weight) { - $this->weight = $weight; - return $this; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php b/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php deleted file mode 100644 index 3b4d88b40..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeCollection.php +++ /dev/null @@ -1,46 +0,0 @@ -get($aID)->getWeight(); - $b_weight = $this->get($bID)->getWeight(); - if ($a_weight == $b_weight) { - return strnatcasecmp($this->get($aID)->getLabel(), $this->get($bID)->getLabel()); - } - - return ($a_weight < $b_weight) ? -1 : 1; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php b/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php deleted file mode 100644 index d3e865ba6..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeInterface.php +++ /dev/null @@ -1,78 +0,0 @@ -<a> tag. - * - * @return string - * The attribute html name. - */ - public function getHtmlName(); - - /** - * Returns the weight of the attribute. - * - * @return int|string - * Either the integer weight of the attribute or an empty string. - */ - public function getWeight(); - - /** - * Sets the weight for this attribute. - * - * @param int $weight - * The weight for this attribute. - * - * @return $this - */ - public function setWeight($weight); - - /** - * The form element structure for this attribute to be used in the dialog. - * - * @param mixed $default_value - * The default value for the element. Used when editing an attribute in the - * dialog. - * - * @return array - * The form element. - */ - public function buildFormElement($default_value); - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php b/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php deleted file mode 100644 index 99d5a3b9f..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/AttributeManager.php +++ /dev/null @@ -1,29 +0,0 @@ -alterInfo('linkit_attribute'); - $this->setCacheBackend($cache_backend, 'linkit_attributes'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php b/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php deleted file mode 100644 index 14ba4415c..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/ConfigurableAttributeBase.php +++ /dev/null @@ -1,16 +0,0 @@ -linkitProfileStorage = $linkit_profile_storage; - $this->resultManager = $resultManager; + $this->suggestionManager = $suggestionManager; } /** @@ -57,7 +55,7 @@ class AutocompleteController implements ContainerInjectionInterface { public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager')->getStorage('linkit_profile'), - $container->get('linkit.result_manager') + $container->get('linkit.suggestion_manager') ); } @@ -67,23 +65,31 @@ class AutocompleteController implements ContainerInjectionInterface { * Like other autocomplete functions, this function inspects the 'q' query * parameter for the string to use to search for suggestions. * - * @param Request $request + * @param \Symfony\Component\HttpFoundation\Request $request * The request. - * @param $linkit_profile_id + * @param string $linkit_profile_id * The linkit profile id. - * @return JsonResponse + * + * @return \Symfony\Component\HttpFoundation\JsonResponse * A JSON response containing the autocomplete suggestions. */ public function autocomplete(Request $request, $linkit_profile_id) { $this->linkitProfile = $this->linkitProfileStorage->load($linkit_profile_id); - $string = Unicode::strtolower($request->query->get('q')); + $string = $request->query->get('q'); - $matches = $this->resultManager->getResults($this->linkitProfile, $string); + $suggestionCollection = $this->suggestionManager->getSuggestions($this->linkitProfile, Unicode::strtolower($string)); - $json_object = new \stdClass(); - $json_object->matches = $matches; + /* + * If there are no suggestions from the matcher plugins, we have to add a + * special suggestion that have the same path as the given string so users + * can select it and use it anyway. This is a common use case with external + * links. + */ + if (!count($suggestionCollection->getSuggestions()) && !empty($string)) { + $suggestionCollection = $this->suggestionManager->addUnscathedSuggestion($suggestionCollection, $string); + } - return new JsonResponse($json_object); + return new JsonResponse($suggestionCollection); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php b/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php index d23e7d336..fdefd47ae 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php +++ b/sites/all/modules/contrib/fields/linkit/src/Controller/LinkitController.php @@ -1,10 +1,5 @@ t('Edit %label profile', array('%label' => $linkit_profile->label())); + return $this->t('Edit %label profile', ['%label' => $linkit_profile->label()]); } /** @@ -42,24 +37,7 @@ class LinkitController extends ControllerBase { public function matcherTitle(ProfileInterface $linkit_profile, $plugin_instance_id) { /** @var \Drupal\linkit\MatcherInterface $matcher */ $matcher = $linkit_profile->getMatcher($plugin_instance_id); - return $this->t('Edit %label matcher', array('%label' => $matcher->getLabel())); - } - - /** - * Route title callback. - * - * @param \Drupal\linkit\ProfileInterface $linkit_profile - * The profile. - * @param string $plugin_instance_id - * The plugin instance id. - * - * @return string - * The title for the attribute edit form. - */ - public function attributeTitle(ProfileInterface $linkit_profile, $plugin_instance_id) { - /** @var \Drupal\linkit\AttributeInterface $attribute */ - $attribute = $linkit_profile->getAttribute($plugin_instance_id); - return $this->t('Edit %label attribute', array('%label' => $attribute->getLabel())); + return $this->t('Edit %label matcher', ['%label' => $matcher->getLabel()]); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php b/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php index 25e9a0f4f..5e533c514 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php +++ b/sites/all/modules/contrib/fields/linkit/src/Element/Linkit.php @@ -1,15 +1,9 @@ TRUE, '#size' => 60, - '#process' => array( - array($class, 'processLinkitAutocomplete'), - array($class, 'processGroup'), - ), - '#pre_render' => array( - array($class, 'preRenderLinkitElement'), - array($class, 'preRenderGroup'), - ), + '#process' => [ + [$class, 'processLinkitAutocomplete'], + [$class, 'processGroup'], + ], + '#pre_render' => [ + [$class, 'preRenderLinkitElement'], + [$class, 'preRenderGroup'], + ], '#theme' => 'input__textfield', - '#theme_wrappers' => array('form_element'), - ); + '#theme_wrappers' => ['form_element'], + ]; } /** @@ -63,7 +57,7 @@ class Linkit extends FormElement { $access = FALSE; if (!empty($element['#autocomplete_route_name'])) { - $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : array(); + $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : []; $url = Url::fromRoute($element['#autocomplete_route_name'], $parameters)->toString(TRUE); /** @var \Drupal\Core\Access\AccessManagerInterface $access_manager */ $access_manager = \Drupal::service('access_manager'); @@ -88,21 +82,10 @@ class Linkit extends FormElement { } /** - * Prepares a #type 'linkit' render element for input.html.twig. - * - * @param array $element - * An associative array containing the properties of the element. - * Properties used: #title, #value, #description, #size, #attributes. - * - * @return array - * The $element with prepared variables ready for input.html.twig. + * {@inheritdoc} */ public static function preRenderLinkitElement($element) { - $element['#attributes']['type'] = 'text'; - Element::setAttributes($element, array('id', 'name', 'value', 'size')); - static::setAttributes($element, array('form-text')); - - return $element; + return Textfield::preRenderTextfield($element); } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php b/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php index 785ff6365..651242f83 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php +++ b/sites/all/modules/contrib/fields/linkit/src/Entity/Profile.php @@ -1,15 +1,9 @@ getAttributes()->get($attribute_id); - } - - /** - * {@inheritdoc} - */ - public function getAttributes() { - if (!$this->attributeCollection) { - $this->attributeCollection = new AttributeCollection($this->getAttributeManager(), $this->attributes); - $this->attributeCollection->sort(); - } - return $this->attributeCollection; - } - - /** - * {@inheritdoc} - */ - public function addAttribute(array $configuration) { - $this->getAttributes()->addInstanceId($configuration['id'], $configuration); - return $configuration['id']; - } - - /** - * {@inheritdoc} - */ - public function removeAttribute($attribute_id) { - unset($this->attributes[$attribute_id]); - $this->getAttributes()->removeInstanceId($attribute_id); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAttributeConfig($attribute_id, array $configuration) { - $this->attributes[$attribute_id] = $configuration; - $this->getAttributes()->setInstanceConfiguration($attribute_id, $configuration); - return $this; - } - /** * {@inheritdoc} */ @@ -186,7 +113,7 @@ class Profile extends ConfigEntityBase implements ProfileInterface, EntityWithPl */ public function getMatchers() { if (!$this->matcherCollection) { - $this->matcherCollection = new MatcherCollection($this->getMatcherManager(), $this->matchers); + $this->matcherCollection = new MatcherCollection(\Drupal::service('plugin.manager.linkit.matcher'), $this->matchers); $this->matcherCollection->sort(); } return $this->matcherCollection; @@ -223,30 +150,9 @@ class Profile extends ConfigEntityBase implements ProfileInterface, EntityWithPl * {@inheritdoc} */ public function getPluginCollections() { - return array( - 'attributes' => $this->getAttributes(), + return [ 'matchers' => $this->getMatchers(), - ); - } - - /** - * Returns the attribute manager. - * - * @return \Drupal\Component\Plugin\PluginManagerInterface - * The attribute manager. - */ - protected function getAttributeManager() { - return \Drupal::service('plugin.manager.linkit.attribute'); - } - - /** - * Returns the matcher manager. - * - * @return \Drupal\Component\Plugin\PluginManagerInterface - * The matcher manager. - */ - protected function getMatcherManager() { - return \Drupal::service('plugin.manager.linkit.matcher'); + ]; } } diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php deleted file mode 100644 index 059ef512e..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/AddForm.php +++ /dev/null @@ -1,166 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.linkit.attribute') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return "linkit_attribute_add_form"; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL) { - $this->linkitProfile = $linkit_profile; - - $form['#attached']['library'][] = 'linkit/linkit.admin'; - $header = [ - 'label' => $this->t('Attributes'), - 'description' => $this->t('Description'), - ]; - - $form['plugin'] = [ - '#type' => 'tableselect', - '#header' => $header, - '#options' => $this->buildRows(), - '#empty' => $this->t('No attributes available.'), - '#multiple' => FALSE, - ]; - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save and continue'), - '#submit' => ['::submitForm'], - '#tableselect' => TRUE, - '#button_type' => 'primary', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - if (empty($form_state->getValue('plugin'))) { - $form_state->setErrorByName('plugin', $this->t('No attribute selected.')); - } - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $form_state->cleanValues(); - - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance($form_state->getValue('plugin')); - $plugin_id = $this->linkitProfile->addAttribute($plugin->getConfiguration()); - $this->linkitProfile->save(); - - $this->logger('linkit')->notice('Added %label attribute to the @profile profile.', [ - '%label' => $this->linkitProfile->getAttribute($plugin_id)->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - - $is_configurable = $plugin instanceof ConfigurableAttributeInterface; - if ($is_configurable) { - $form_state->setRedirect('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $plugin_id, - ]); - } - else { - drupal_set_message($this->t('Added %label attribute.', ['%label' => $plugin->getLabel()])); - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - } - - /** - * Builds the table rows. - * - * Only attributes that is not already applied to the profile are shown. - * - * @return array - * An array of table rows. - */ - private function buildRows() { - $rows = []; - - $applied_plugins = $this->linkitProfile->getAttributes()->getConfiguration(); - $all_plugins = $this->manager->getDefinitions(); - uasort($all_plugins, function ($a, $b) { - return strnatcasecmp($a['label'], $b['label']); - }); - foreach (array_diff_key($all_plugins, $applied_plugins) as $definition) { - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance($definition['id']); - - $row = [ - 'label' => (string) $plugin->getLabel(), - 'description' => (string) $plugin->getDescription(), - ]; - - $rows[$plugin->getPluginId()] = $row; - } - - return $rows; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php deleted file mode 100644 index d31e44b01..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/DeleteForm.php +++ /dev/null @@ -1,92 +0,0 @@ -t('Are you sure you want to delete the @plugin attribute from the %profile profile?', ['%profile' => $this->linkitProfile->label(), '@plugin' => $this->linkitAttribute->getLabel()]); - } - - /** - * {@inheritdoc} - */ - public function getCancelUrl() { - return Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'linkit_attribute_delete_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL, $plugin_instance_id = NULL) { - $this->linkitProfile = $linkit_profile; - - if (!$this->linkitProfile->getAttributes()->has($plugin_instance_id)) { - throw new NotFoundHttpException(); - } - - $this->linkitAttribute = $this->linkitProfile->getAttribute($plugin_instance_id); - return parent::buildForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - if ($this->linkitProfile->getAttributes()->has($this->linkitAttribute->getPluginId())) { - $this->linkitProfile->removeAttribute($this->linkitAttribute->getPluginId()); - $this->linkitProfile->save(); - - drupal_set_message($this->t('The attribute %label has been deleted.', ['%label' => $this->linkitAttribute->getLabel()])); - $this->logger('linkit')->notice('The attribute %label has been deleted in the @profile profile.', [ - '%label' => $this->linkitAttribute->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - } - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php deleted file mode 100644 index 0b76601fb..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/EditForm.php +++ /dev/null @@ -1,96 +0,0 @@ -linkitProfile = $linkit_profile; - $this->linkitAttribute = $this->linkitProfile->getAttribute($plugin_instance_id); - $form['data'] = [ - '#tree' => true, - ]; - - $form['data'] += $this->linkitAttribute->buildConfigurationForm($form, $form_state); - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => $this->t('Save changes'), - '#submit' => array('::submitForm'), - '#button_type' => 'primary', - ); - $form['actions']['delete'] = array( - '#type' => 'link', - '#title' => $this->t('Delete'), - '#url' => Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $this->linkitAttribute->getPluginId(), - ]), - '#attributes' => [ - 'class' => ['button', 'button--danger'], - ], - ); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $form_state->cleanValues(); - $plugin_data = (new FormState())->setValues($form_state->getValue('data')); - $this->linkitAttribute->submitConfigurationForm($form, $plugin_data); - $this->linkitProfile->save(); - - drupal_set_message($this->t('Saved %label configuration.', array('%label' => $this->linkitAttribute->getLabel()))); - $this->logger('linkit')->notice('The attribute %label has been updated in the @profile profile.', [ - '%label' => $this->linkitAttribute->getLabel(), - '@profile' => $this->linkitProfile->label(), - ]); - - $form_state->setRedirect('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ]); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php deleted file mode 100644 index 267dd61d5..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Attribute/OverviewForm.php +++ /dev/null @@ -1,156 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.linkit.attribute') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return "linkit_attribute_overview_form"; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, ProfileInterface $linkit_profile = NULL) { - $this->linkitProfile = $linkit_profile; - - $form['plugins'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Attribute'), - $this->t('Description'), - $this->t('Weight'), - $this->t('Operations'), - ], - '#empty' => $this->t('No attributes added.'), - '#tabledrag' => [ - [ - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'plugin-order-weight', - ], - ], - ]; - - foreach ($this->linkitProfile->getAttributes() as $plugin) { - $key = $plugin->getPluginId(); - - $form['plugins'][$key]['#attributes']['class'][] = 'draggable'; - $form['plugins'][$key]['#weight'] = $plugin->getWeight(); - - $form['plugins'][$key]['label'] = [ - '#plain_text' => (string) $plugin->getLabel(), - ]; - - $form['plugins'][$key]['description'] = [ - '#plain_text' => (string) $plugin->getDescription(), - ]; - - $form['plugins'][$key]['weight'] = [ - '#type' => 'weight', - '#title' => t('Weight for @title', ['@title' => (string) $plugin->getLabel()]), - '#title_display' => 'invisible', - '#default_value' => $plugin->getWeight(), - '#attributes' => ['class' => ['plugin-order-weight']], - ]; - - $form['plugins'][$key]['operations'] = [ - '#type' => 'operations', - '#links' => [], - ]; - - $is_configurable = $plugin instanceof ConfigurableAttributeInterface; - if ($is_configurable) { - $form['plugins'][$key]['operations']['#links']['edit'] = [ - 'title' => t('Edit'), - 'url' => Url::fromRoute('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $key, - ]), - ]; - } - - $form['plugins'][$key]['operations']['#links']['delete'] = [ - 'title' => t('Delete'), - 'url' => Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $key, - ]), - ]; - } - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save'), - '#button_type' => 'primary', - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - foreach ($form_state->getValue('plugins') as $id => $plugin_data) { - if ($this->linkitProfile->getAttributes()->has($id)) { - $this->linkitProfile->getAttribute($id)->setWeight($plugin_data['weight']); - } - } - $this->linkitProfile->save(); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php b/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php deleted file mode 100644 index 8f3b8f571..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Form/LinkitEditorDialog.php +++ /dev/null @@ -1,207 +0,0 @@ -editorStorage = $editor_storage; - $this->linkitProfileStorage = $linkit_profile_storage; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.manager')->getStorage('editor'), - $container->get('entity.manager')->getStorage('linkit_profile') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'linkit_editor_dialog_form'; - } - - /** - * {@inheritdoc} - * - * @param \Drupal\filter\Entity\FilterFormat $filter_format - * The filter format for which this dialog corresponds. - */ - public function buildForm(array $form, FormStateInterface $form_state, FilterFormat $filter_format = NULL) { - // The default values are set directly from \Drupal::request()->request, - // provided by the editor plugin opening the dialog. - $user_input = $form_state->getUserInput(); - $input = isset($user_input['editor_object']) ? $user_input['editor_object'] : []; - - /** @var \Drupal\editor\EditorInterface $editor */ - $editor = $this->editorStorage->load($filter_format->id()); - $linkit_profile_id = $editor->getSettings()['plugins']['linkit']['linkit_profile']; - $this->linkitProfile = $this->linkitProfileStorage->load($linkit_profile_id); - - $form['#tree'] = TRUE; - $form['#attached']['library'][] = 'editor/drupal.editor.dialog'; - $form['#prefix'] = '
    '; - $form['#suffix'] = '
    '; - - // Everything under the "attributes" key is merged directly into the - // generated link tag's attributes. - $form['attributes']['href'] = [ - '#title' => $this->t('Link'), - '#type' => 'linkit', - '#default_value' => isset($input['href']) ? $input['href'] : '', - '#description' => $this->t('Start typing to find content or paste a URL.'), - '#autocomplete_route_name' => 'linkit.autocomplete', - '#autocomplete_route_parameters' => [ - 'linkit_profile_id' => $linkit_profile_id - ], - '#weight' => 0, - ]; - - $this->addAttributes($form, $form_state, $this->linkitProfile->getAttributes(), $input); - - $form['actions'] = [ - '#type' => 'actions', - ]; - - $form['actions']['save_modal'] = [ - '#type' => 'submit', - '#value' => $this->t('Save'), - '#submit' => [], - '#ajax' => [ - 'callback' => '::submitForm', - 'event' => 'click', - ], - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $attributes = array_filter($form_state->getValue('attributes')); - $form_state->setValue('attributes', $attributes); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $response = new AjaxResponse(); - - if ($form_state->getErrors()) { - unset($form['#prefix'], $form['#suffix']); - $form['status_messages'] = [ - '#type' => 'status_messages', - '#weight' => -10, - ]; - $response->addCommand(new HtmlCommand('#linkit-editor-dialog-form', $form)); - } - else { - $response->addCommand(new EditorDialogSave($form_state->getValues())); - $response->addCommand(new CloseModalDialogCommand()); - } - - return $response; - } - - /** - * Adds the attributes enabled on the current profile. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * @param AttributeCollection $attributes - * A collection of attributes for the current profile. - * @param array $input - * An array with the attribute values from the editor. - */ - private function addAttributes(array &$form, FormStateInterface &$form_state, AttributeCollection $attributes, array $input) { - if ($attributes->count()) { - $form['linkit_attributes'] = [ - '#type' => 'container', - '#title' => $this->t('Attributes'), - '#weight' => '10', - ]; - - /** @var \Drupal\linkit\AttributeInterface $plugin */ - foreach ($attributes as $plugin) { - $plugin_name = $plugin->getHtmlName(); - - $default_value = isset($input[$plugin_name]) ? $input[$plugin_name] : ''; - $form['linkit_attributes'][$plugin_name] = $plugin->buildFormElement($default_value); - $form['linkit_attributes'][$plugin_name] += [ - '#parents' => [ - 'attributes', $plugin_name, - ], - ]; - } - } - } - - /** - * Gets the linkit profile entity. - * - * @return \Drupal\linkit\ProfileInterface - * The current linkit profile used by this form. - */ - public function getLinkitProfile() { - return $this->linkitProfile; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/AddForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/AddForm.php index 0acad7329..fdc80f077 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/AddForm.php +++ b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/AddForm.php @@ -1,10 +1,5 @@ 'primary', ]; - $options = []; - foreach ($this->manager->getDefinitions() as $id => $plugin) { - $options[$id] = $plugin['label']; - } - return $form; } diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/DeleteForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/DeleteForm.php index bff47370f..e09b038e0 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/DeleteForm.php +++ b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/DeleteForm.php @@ -1,10 +1,5 @@ linkitMatcher->buildConfigurationForm($form, $form_state); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save changes'), - '#submit' => array('::submitForm'), + '#submit' => ['::submitForm'], '#button_type' => 'primary', - ); - $form['actions']['delete'] = array( + ]; + $form['actions']['delete'] = [ '#type' => 'link', '#title' => $this->t('Delete'), '#url' => Url::fromRoute('linkit.matcher.delete', [ @@ -65,7 +60,7 @@ class EditForm extends FormBase { '#attributes' => [ 'class' => ['button', 'button--danger'], ], - ); + ]; return $form; } @@ -79,7 +74,7 @@ class EditForm extends FormBase { $this->linkitMatcher->submitConfigurationForm($form, $plugin_data); $this->linkitProfile->save(); - drupal_set_message($this->t('Saved %label configuration.', array('%label' => $this->linkitMatcher->getLabel()))); + drupal_set_message($this->t('Saved %label configuration.', ['%label' => $this->linkitMatcher->getLabel()])); $this->logger('linkit')->notice('The matcher %label has been updated in the @profile profile.', [ '%label' => $this->linkitMatcher->getLabel(), '@profile' => $this->linkitProfile->label(), @@ -89,4 +84,5 @@ class EditForm extends FormBase { 'linkit_profile' => $this->linkitProfile->id(), ]); } + } diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/OverviewForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/OverviewForm.php index 1bffe2d7f..33cb0e3d3 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/OverviewForm.php +++ b/sites/all/modules/contrib/fields/linkit/src/Form/Matcher/OverviewForm.php @@ -1,10 +1,5 @@ 'table', '#header' => [ [ - 'data' => $this->t('Matcher'), - 'colspan' => 2 + 'data' => $this->t('Matchers'), + 'colspan' => 2, ], $this->t('Weight'), $this->t('Operations'), @@ -109,7 +104,7 @@ class OverviewForm extends FormBase { $form['plugins'][$key]['weight'] = [ '#type' => 'weight', - '#title' => t('Weight for @title', ['@title' => (string) $plugin->getLabel()]), + '#title' => $this->t('Weight for @title', ['@title' => (string) $plugin->getLabel()]), '#title_display' => 'invisible', '#default_value' => $plugin->getWeight(), '#attributes' => ['class' => ['plugin-order-weight']], @@ -123,18 +118,18 @@ class OverviewForm extends FormBase { $is_configurable = $plugin instanceof ConfigurableMatcherInterface; if ($is_configurable) { $form['plugins'][$key]['operations']['#links']['edit'] = [ - 'title' => t('Edit'), + 'title' => $this->t('Edit'), 'url' => Url::fromRoute('linkit.matcher.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), + 'linkit_profile' => $this->linkitProfile->id(), 'plugin_instance_id' => $key, ]), ]; } $form['plugins'][$key]['operations']['#links']['delete'] = [ - 'title' => t('Delete'), + 'title' => $this->t('Delete'), 'url' => Url::fromRoute('linkit.matcher.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), + 'linkit_profile' => $this->linkitProfile->id(), 'plugin_instance_id' => $key, ]), ]; diff --git a/sites/all/modules/contrib/fields/linkit/src/Form/Profile/AddForm.php b/sites/all/modules/contrib/fields/linkit/src/Form/Profile/AddForm.php index b43d69c81..10d810581 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Form/Profile/AddForm.php +++ b/sites/all/modules/contrib/fields/linkit/src/Form/Profile/AddForm.php @@ -1,10 +1,5 @@ 'machine_name', '#default_value' => $this->entity->id(), '#machine_name' => [ - 'exists' => ['\Drupal\linkit\Entity\Profile', 'load'] + 'exists' => ['\Drupal\linkit\Entity\Profile', 'load'], ], '#disabled' => !$this->entity->isNew(), ]; @@ -51,10 +46,10 @@ abstract class FormBase extends EntityForm { '#description' => $this->t('The text will be displayed on the profile collection page.'), ]; - $form['additional_settings'] = array( + $form['additional_settings'] = [ '#type' => 'vertical_tabs', '#weight' => 99, - ); + ]; return parent::form($form, $form_state); } @@ -69,7 +64,7 @@ abstract class FormBase extends EntityForm { $linkit_profile->set('label', trim($linkit_profile->label())); $status = $linkit_profile->save(); - $edit_link = $this->entity->link($this->t('Edit')); + $edit_link = $this->entity->toLink($this->t('Edit'), 'edit-form')->toString(); switch ($status) { case SAVED_NEW: drupal_set_message($this->t('Created new profile %label.', ['%label' => $linkit_profile->label()])); @@ -82,7 +77,7 @@ abstract class FormBase extends EntityForm { case SAVED_UPDATED: drupal_set_message($this->t('Updated profile %label.', ['%label' => $linkit_profile->label()])); $this->logger('linkit')->notice('Updated profile %label.', ['%label' => $linkit_profile->label(), 'link' => $edit_link]); - $form_state->setRedirectUrl($linkit_profile->urlInfo('edit-form')); + $form_state->setRedirectUrl($linkit_profile->toUrl('edit-form')); break; } } diff --git a/sites/all/modules/contrib/fields/linkit/src/MatcherBase.php b/sites/all/modules/contrib/fields/linkit/src/MatcherBase.php index 6932e2b71..1176e084f 100644 --- a/sites/all/modules/contrib/fields/linkit/src/MatcherBase.php +++ b/sites/all/modules/contrib/fields/linkit/src/MatcherBase.php @@ -1,14 +1,10 @@ setConfiguration($configuration); } + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition + ); + } + /** * {@inheritdoc} */ @@ -58,7 +65,7 @@ abstract class MatcherBase extends PluginBase implements MatcherInterface, Conta * {@inheritdoc} */ public function getSummary() { - return array(); + return []; } /** diff --git a/sites/all/modules/contrib/fields/linkit/src/MatcherCollection.php b/sites/all/modules/contrib/fields/linkit/src/MatcherCollection.php index b7124c2f3..c397bc338 100644 --- a/sites/all/modules/contrib/fields/linkit/src/MatcherCollection.php +++ b/sites/all/modules/contrib/fields/linkit/src/MatcherCollection.php @@ -1,10 +1,5 @@ moduleExists('token')) { // Add the token tree UI. - $form['token_tree'] = array( + $form['metadata']['token_tree'] = [ '#theme' => 'token_tree_link', '#token_types' => $types, '#dialog' => TRUE, - '#weight' => -90, - ); + '#weight' => 10, + ]; } else { - $token_items = array(); + $token_items = []; foreach ($this->getAvailableTokens($types) as $type => $tokens) { foreach ($tokens as $name => $info) { $token_description = !empty($info['description']) ? $info['description'] : ''; @@ -40,16 +35,16 @@ trait MatcherTokensTrait { } if (count($token_items)) { - $form['tokens'] = array( + $form['metadata']['tokens'] = [ '#type' => 'details', '#title' => t('Available tokens'), - '#weight' => -90, - ); + '#weight' => 10, + ]; - $form['tokens']['list'] = array( + $form['metadata']['tokens']['list'] = [ '#theme' => 'item_list', '#items' => $token_items, - ); + ]; } } } @@ -59,10 +54,11 @@ trait MatcherTokensTrait { * * @param array $types * An array of token types to use. + * * @return array * An array with available tokens */ - public function getAvailableTokens(array $types = array()) { + public function getAvailableTokens(array $types = []) { $info = \Drupal::token()->getInfo(); $available = array_intersect_key($info['tokens'], array_flip($types)); return $available; diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/Linkit.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/Linkit.php deleted file mode 100644 index 54056a525..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/Linkit.php +++ /dev/null @@ -1,123 +0,0 @@ -linkitProfileStorage = $linkit_profile_storage; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('entity.manager')->getStorage('linkit_profile') - ); - } - - /** - * {@inheritdoc} - */ - public function getFile() { - return drupal_get_path('module', 'linkit') . '/js/plugins/linkit/plugin.js'; - } - - /** - * {@inheritdoc} - */ - public function getConfig(Editor $editor) { - return array( - 'linkit_dialogTitleAdd' => t('Add link'), - 'linkit_dialogTitleEdit' => t('Edit link'), - ); - } - - /** - * {@inheritdoc} - */ - public function getButtons() { - return array( - 'Linkit' => array( - 'label' => t('Linkit'), - 'image' => drupal_get_path('module', 'linkit') . '/js/plugins/linkit/linkit.png', - ), - ); - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { - $settings = $editor->getSettings(); - - $all_profiles = $this->linkitProfileStorage->loadMultiple(); - - $options = array(); - foreach ($all_profiles as $profile) { - $options[$profile->id()] = $profile->label(); - } - - $form['linkit_profile'] = array( - '#type' => 'select', - '#title' => t('Select a linkit profile'), - '#options' => $options, - '#default_value' => isset($settings['plugins']['linkit']) ? $settings['plugins']['linkit'] : '', - '#empty_option' => $this->t('- Select profile -'), - '#description' => $this->t('Select the linkit profile you wish to use with this text format.'), - '#element_validate' => array( - array($this, 'validateLinkitProfileSelection'), - ), - ); - - return $form; - } - - /** - * #element_validate handler for the "linkit_profile" element in settingsForm(). - */ - public function validateLinkitProfileSelection(array $element, FormStateInterface $form_state) { - $toolbar_buttons = $form_state->getValue(array('editor', 'settings', 'toolbar', 'button_groups')); - if (strpos($toolbar_buttons, '"Linkit"') !== FALSE && empty($element['#value'])) { - $form_state->setError($element, t('Please select the linkit profile you wish to use.')); - } - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/LinkitDrupalLink.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/LinkitDrupalLink.php new file mode 100644 index 000000000..048a03f34 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/CKEditorPlugin/LinkitDrupalLink.php @@ -0,0 +1,111 @@ +linkitProfileStorage = $linkit_profile_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity.manager')->getStorage('linkit_profile') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { + $settings = $editor->getSettings(); + + $all_profiles = $this->linkitProfileStorage->loadMultiple(); + + $options = []; + foreach ($all_profiles as $profile) { + $options[$profile->id()] = $profile->label(); + } + + $form['linkit_enabled'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Linkit enabled'), + '#default_value' => isset($settings['plugins']['drupallink']['linkit_enabled']) ? $settings['plugins']['drupallink']['linkit_enabled'] : '', + '#description' => $this->t('Enable Linkit for this text format.'), + ]; + + $form['linkit_profile'] = [ + '#type' => 'select', + '#title' => $this->t('Linkit profile'), + '#options' => $options, + '#default_value' => isset($settings['plugins']['drupallink']['linkit_profile']) ? $settings['plugins']['drupallink']['linkit_profile'] : '', + '#empty_option' => $this->t('- Select -'), + '#description' => $this->t('Select the Linkit profile you wish to use with this text format.'), + '#states' => [ + 'invisible' => [ + 'input[data-drupal-selector="edit-editor-settings-plugins-drupallink-linkit-enabled"]' => ['checked' => FALSE], + ], + ], + '#element_validate' => [ + [$this, 'validateLinkitProfileSelection'], + ], + ]; + + return $form; + } + + /** + * Linkit profile select validation. + * + * #element_validate callback for the "linkit_profile" element. + * + * @param array $element + * An associative array containing the properties and children of the + * generic form element. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form for the form this element belongs to. + * + * @see \Drupal\Core\Render\Element\FormElement::processPattern() + */ + public function validateLinkitProfileSelection(array $element, FormStateInterface $form_state) { + $values = $form_state->getValue([ + 'editor', + 'settings', + 'plugins', + 'drupallink', + ]); + $enabled = isset($values['linkit_enabled']) && $values['linkit_enabled'] === 1; + if ($enabled && empty(trim($values['linkit_profile']))) { + $form_state->setError($element, $this->t('Please select the Linkit profile you wish to use.')); + } + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Derivative/EntityMatcherDeriver.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Derivative/EntityMatcherDeriver.php index b5fcf5020..a51e12928 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Derivative/EntityMatcherDeriver.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Derivative/EntityMatcherDeriver.php @@ -1,39 +1,35 @@ entityManager = $entity_manager; + public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->entityTypeManager = $entity_type_manager; } /** @@ -41,7 +37,7 @@ class EntityMatcherDeriver extends DeriverBase implements ContainerDeriverInterf */ public static function create(ContainerInterface $container, $base_plugin_id) { return new static( - $container->get('entity.manager') + $container->get('entity_type.manager') ); } @@ -49,10 +45,13 @@ class EntityMatcherDeriver extends DeriverBase implements ContainerDeriverInterf * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { - foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) { - $has_canonical = $entity_type->hasLinkTemplate('canonical'); + foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) { + $canonical = $entity_type->getLinkTemplate('canonical'); + $edit_form = $entity_type->getLinkTemplate('edit-form'); - if ($has_canonical) { + // Only entities that has a distinct canonical URI that is not the same + // as the edit-form URI will be derived. + if ($entity_type instanceof ContentEntityTypeInterface && $canonical && ($canonical !== $edit_form)) { $this->derivatives[$entity_type_id] = $base_plugin_definition; $this->derivatives[$entity_type_id]['id'] = $base_plugin_definition['id'] . ':' . $entity_type_id; $this->derivatives[$entity_type_id]['label'] = $entity_type->getLabel(); diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Filter/LinkitFilter.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Filter/LinkitFilter.php new file mode 100644 index 000000000..11f3e0512 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Filter/LinkitFilter.php @@ -0,0 +1,156 @@ +entityRepository = $entity_repository; + $this->substitutionManager = $substitution_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity.repository'), + $container->get('plugin.manager.linkit.substitution') + ); + } + + /** + * {@inheritdoc} + */ + public function process($text, $langcode) { + $result = new FilterProcessResult($text); + + if (strpos($text, 'data-entity-type') !== FALSE && strpos($text, 'data-entity-uuid') !== FALSE) { + $dom = Html::load($text); + $xpath = new \DOMXPath($dom); + + foreach ($xpath->query('//a[@data-entity-type and @data-entity-uuid]') as $element) { + /** @var \DOMElement $element */ + try { + // Load the appropriate translation of the linked entity. + $entity_type = $element->getAttribute('data-entity-type'); + $uuid = $element->getAttribute('data-entity-uuid'); + + // Make the substitution optional, for backwards compatibility, + // maintaining the previous hard-coded direct file link assumptions, + // for content created before the substitution feature. + if (!$substitution_type = $element->getAttribute('data-entity-substitution')) { + $substitution_type = $entity_type === 'file' ? 'file' : SubstitutionManagerInterface::DEFAULT_SUBSTITUTION; + } + + $entity = $this->entityRepository->loadEntityByUuid($entity_type, $uuid); + if ($entity) { + + $entity = $this->entityRepository->getTranslationFromContext($entity, $langcode); + + /** @var \Drupal\Core\GeneratedUrl $url */ + $url = $this->substitutionManager + ->createInstance($substitution_type) + ->getUrl($entity); + + $element->setAttribute('href', $url->getGeneratedUrl()); + $access = $entity->access('view', NULL, TRUE); + + // Set the appropriate title attribute. + if ($this->settings['title'] && !$access->isForbidden() && !$element->getAttribute('title')) { + $element->setAttribute('title', $entity->label()); + } + + // The processed text now depends on: + $result + // - the linked entity access for the current user. + ->addCacheableDependency($access) + // - the generated URL (which has undergone path & route + // processing) + ->addCacheableDependency($url) + // - the linked entity (whose URL and title may change) + ->addCacheableDependency($entity); + } + } + catch (\Exception $e) { + watchdog_exception('linkit_filter', $e); + } + } + + $result->setProcessedText(Html::serialize($dom)); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $form['title'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Automatically set the title attribute to that of the (translated) referenced content'), + '#default_value' => $this->settings['title'], + '#attached' => [ + 'library' => ['linkit/linkit.filter_html.admin'], + ], + ]; + return $form; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php deleted file mode 100644 index e0a609f1b..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Accesskey.php +++ /dev/null @@ -1,38 +0,0 @@ - 'textfield', - '#title' => t('Accesskey'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - '#placeholder' => t('The "accesskey" attribute value'), - ]; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php deleted file mode 100644 index 03787e7b4..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Clazz.php +++ /dev/null @@ -1,41 +0,0 @@ - 'textfield', -// '#title' => t('Class'), -// '#maxlength' => 255, -// '#size' => 40, -// ]; -// } -// -//} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php deleted file mode 100644 index 817b1ba09..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Id.php +++ /dev/null @@ -1,38 +0,0 @@ - 'textfield', - '#title' => t('Id'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - '#placeholder' => t('The "id" attribute value'), - ]; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php deleted file mode 100644 index 0c3286767..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Relationship.php +++ /dev/null @@ -1,38 +0,0 @@ - 'textfield', - '#title' => t('Relationship'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - '#placeholder' => t('The "rel" attribute value'), - ]; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php deleted file mode 100644 index ce4833757..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Target.php +++ /dev/null @@ -1,96 +0,0 @@ -configuration['widget_type']) { - case self::SELECT_LIST: - return [ - '#type' => 'select', - '#title' => t('Target'), - '#options' => [ - '' => '', - '_blank' => t('New window (_blank)'), - '_top' => t('Top window (_top)'), - '_self' => t('Same window (_self)'), - '_parent' => t('Parent window (_parent)') - ], - '#default_value' => $default_value, - ]; - case self::SIMPLE_CHECKBOX: - return [ - '#type' => 'checkbox', - '#title' => t('Open in new window'), - '#default_value' => $default_value, - '#return_value' => '_blank', - ]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return parent::defaultConfiguration() + [ - 'widget_type' => self::SIMPLE_CHECKBOX, - ]; - } - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form['widget_type'] = [ - '#type' => 'radios', - '#title' => $this->t('Widget type'), - '#default_value' => $this->configuration['widget_type'], - '#options' => [ - self::SELECT_LIST => $this->t('Selectlist with predefined targets.'), - self::SIMPLE_CHECKBOX => $this->t('Simple checkbox to allow links to be opened in a new browser window or tab.'), - ], - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { - } - - /** - * {@inheritdoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['widget_type'] = $form_state->getValue('widget_type'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php deleted file mode 100644 index 6cd8f3e4b..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Attribute/Title.php +++ /dev/null @@ -1,82 +0,0 @@ - 'textfield', - '#title' => t('Title'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - '#placeholder' => t('The "title" attribute value'), - ]; - - if ($this->configuration['automatic_title']) { - $element['#attached']['library'][] = 'linkit/linkit.attribute.title'; - $element['#placeholder'] = t('The "title" attribute value (auto populated)'); - } - - return $element; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return parent::defaultConfiguration() + [ - 'automatic_title' => FALSE, - ]; - } - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form['automatic_title'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Automatically populate title'), - '#default_value' => $this->configuration['automatic_title'], - '#description' => $this->t('Automatically populate the title attribute with the title from the match selection.'), - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { - } - - /** - * {@inheritdoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['automatic_title'] = $form_state->getValue('automatic_title'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php new file mode 100644 index 000000000..e9326b933 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/ContactFormMatcher.php @@ -0,0 +1,38 @@ + ['contact'], + ]; + } + + /** + * {@inheritdoc} + */ + protected function buildEntityQuery($search_string) { + $query = parent::buildEntityQuery($search_string); + + // Remove the personal contact form from the suggestion list. + $query->condition('id', 'personal', '<>'); + + return $query; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php new file mode 100644 index 000000000..c9513d94d --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EmailMatcher.php @@ -0,0 +1,40 @@ +setLabel($this->t('E-mail @email', ['@email' => $string])) + ->setPath('mailto:' . Html::escape($string)) + ->setGroup($this->t('E-mail')) + ->setDescription($this->t('Opens your mail client ready to e-mail @email', ['@email' => $string])); + + $suggestions->addSuggestion($suggestion); + } + return $suggestions; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php index 33838206a..a8a85c8f3 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/EntityMatcher.php @@ -1,24 +1,31 @@ database = $database; - $this->entityManager = $entity_manager; + $this->entityTypeManager = $entity_type_manager; + $this->entityTypeBundleInfo = $entity_type_bundle_info; + $this->entityRepository = $entity_repository; $this->moduleHandler = $module_handler; $this->currentUser = $current_user; - $this->target_type = $plugin_definition['target_entity']; + $this->targetType = $plugin_definition['target_entity']; + $this->substitutionManager = $substitution_manager; } /** @@ -89,9 +120,12 @@ class EntityMatcher extends ConfigurableMatcherBase { $plugin_id, $plugin_definition, $container->get('database'), - $container->get('entity.manager'), + $container->get('entity_type.manager'), + $container->get('entity_type.bundle.info'), + $container->get('entity.repository'), $container->get('module_handler'), - $container->get('current_user') + $container->get('current_user'), + $container->get('plugin.manager.linkit.substitution') ); } @@ -100,12 +134,12 @@ class EntityMatcher extends ConfigurableMatcherBase { */ public function getSummary() { $summery = parent::getSummary(); - $entity_type = $this->entityManager->getDefinition($this->target_type); + $entity_type = $this->entityTypeManager->getDefinition($this->targetType); - $result_description = $this->configuration['result_description']; - if (!empty($result_description)) { - $summery[] = $this->t('Result description: @result_description', [ - '@result_description' => $result_description + $metadata = $this->configuration['metadata']; + if (!empty($metadata)) { + $summery[] = $this->t('Metadata: @metadata', [ + '@metadata' => $metadata, ]); } @@ -114,7 +148,7 @@ class EntityMatcher extends ConfigurableMatcherBase { $bundles = []; if ($has_bundle_filter) { - $bundles_info = $this->entityManager->getBundleInfo($this->target_type); + $bundles_info = $this->entityTypeBundleInfo->getBundleInfo($this->targetType); foreach ($this->configuration['bundles'] as $bundle) { $bundles[] = $bundles_info[$bundle]['label']; } @@ -136,55 +170,93 @@ class EntityMatcher extends ConfigurableMatcherBase { * {@inheritdoc} */ public function defaultConfiguration() { - return parent::defaultConfiguration() + [ - 'result_description' => '', + return [ + 'metadata' => '', 'bundles' => [], 'group_by_bundle' => FALSE, - ]; + 'substitution_type' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, + ] + parent::defaultConfiguration(); } /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $entity_type = $this->entityManager->getDefinition($this->target_type); - $form['result_description'] = [ - '#title' => $this->t('Result description'), - '#type' => 'textfield', - '#default_value' => $this->configuration['result_description'], - '#size' => 120, - '#maxlength' => 255, + $entity_type = $this->entityTypeManager->getDefinition($this->targetType); + + $form['metadata'] = [ + '#type' => 'details', + '#title' => $this->t('Suggestion metadata'), + '#open' => TRUE, '#weight' => -100, ]; - $this->insertTokenList($form, [$this->target_type]); + $form['metadata']['metadata'] = [ + '#title' => $this->t('Metadata'), + '#type' => 'textfield', + '#default_value' => $this->configuration['metadata'], + '#description' => $this->t('Metadata is shown together with each suggestion in the suggestion list.'), + '#size' => 120, + '#maxlength' => 255, + '#weight' => 0, + ]; + + $this->insertTokenList($form, [$this->targetType]); // Filter the possible bundles to use if the entity has bundles. if ($entity_type->hasKey('bundle')) { $bundle_options = []; - foreach ($this->entityManager->getBundleInfo($this->target_type) as $bundle_name => $bundle_info) { + foreach ($this->entityTypeBundleInfo->getBundleInfo($this->targetType) as $bundle_name => $bundle_info) { $bundle_options[$bundle_name] = $bundle_info['label']; } - $form['bundles'] = [ - '#type' => 'checkboxes', - '#title' => $this->t('Restrict to the selected bundles'), - '#options' => $bundle_options, - '#default_value' => $this->configuration['bundles'], - '#description' => $this->t('If none of the checkboxes is checked, allow all bundles.'), - '#element_validate' => [[get_class($this), 'elementValidateFilter']], - '#weight' => -50, + $form['bundle_restrictions'] = [ + '#type' => 'details', + '#title' => $this->t('Bundle restrictions'), + '#open' => TRUE, + '#weight' => -90, ]; - // Group the results by bundle. - $form['group_by_bundle'] = [ + $form['bundle_restrictions']['bundles'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Restrict suggestions to the selected bundles'), + '#options' => $bundle_options, + '#default_value' => $this->configuration['bundles'], + '#description' => $this->t('If none of the checkboxes is checked, all bundles are allowed.'), + '#element_validate' => [[get_class($this), 'elementValidateFilter']], + ]; + + $form['bundle_grouping'] = [ + '#type' => 'details', + '#title' => $this->t('Bundle grouping'), + '#open' => TRUE, + ]; + + // Group the suggestions by bundle. + $form['bundle_grouping']['group_by_bundle'] = [ '#type' => 'checkbox', '#title' => $this->t('Group by bundle'), '#default_value' => $this->configuration['group_by_bundle'], - '#weight' => -50, + '#description' => $this->t('Group suggestions by their bundle.'), ]; } + $substitution_options = $this->substitutionManager->getApplicablePluginsOptionList($this->targetType); + $form['substitution'] = [ + '#type' => 'details', + '#title' => $this->t('URL substitution'), + '#open' => TRUE, + '#weight' => 100, + '#access' => count($substitution_options) !== 1, + ]; + $form['substitution']['substitution_type'] = [ + '#title' => $this->t('Substitution Type'), + '#type' => 'select', + '#default_value' => $this->configuration['substitution_type'], + '#options' => $substitution_options, + '#description' => $this->t('Configure how the selected entity should be transformed into a URL for insertion.'), + ]; + return $form; } @@ -198,9 +270,10 @@ class EntityMatcher extends ConfigurableMatcherBase { * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['result_description'] = $form_state->getValue('result_description'); + $this->configuration['metadata'] = $form_state->getValue('metadata'); $this->configuration['bundles'] = $form_state->getValue('bundles'); $this->configuration['group_by_bundle'] = $form_state->getValue('group_by_bundle'); + $this->configuration['substitution_type'] = $form_state->getValue('substitution_type'); } /** @@ -214,55 +287,64 @@ class EntityMatcher extends ConfigurableMatcherBase { /** * {@inheritdoc} */ - public function getMatches($string) { + public function execute($string) { + $suggestions = new SuggestionCollection(); $query = $this->buildEntityQuery($string); - $result = $query->execute(); + $query_result = $query->execute(); + $url_results = $this->findEntityIdByUrl($string); + $result = array_merge($query_result, $url_results); + // If no results, return an empty suggestion collection. if (empty($result)) { - return []; + return $suggestions; } - $matches = []; - $entities = $this->entityManager->getStorage($this->target_type)->loadMultiple($result); + $entities = $this->entityTypeManager->getStorage($this->targetType)->loadMultiple($result); - foreach ($entities as $entity_id => $entity) { + foreach ($entities as $entity) { // Check the access against the defined entity access handler. /** @var \Drupal\Core\Access\AccessResultInterface $access */ $access = $entity->access('view', $this->currentUser, TRUE); + if (!$access->isAllowed()) { continue; } - $matches[] = [ - 'title' => $this->buildLabel($entity), - 'description' => $this->buildDescription($entity), - 'path' => $this->buildPath($entity), - 'group' => $this->buildGroup($entity), - ]; + $entity = $this->entityRepository->getTranslationFromContext($entity); + $suggestion = $this->createSuggestion($entity); + $suggestions->addSuggestion($suggestion); } - return $matches; + return $suggestions; } /** * Builds an EntityQuery to get entities. * - * @param $match + * @param string $search_string * Text to match the label against. * * @return \Drupal\Core\Entity\Query\QueryInterface * The EntityQuery object with the basic conditions and sorting applied to * it. */ - protected function buildEntityQuery($match) { - $match = $this->database->escapeLike($match); + protected function buildEntityQuery($search_string) { + $search_string = $this->database->escapeLike($search_string); - $entity_type = $this->entityManager->getDefinition($this->target_type); - $query = $this->entityManager->getStorage($this->target_type)->getQuery(); + $entity_type = $this->entityTypeManager->getDefinition($this->targetType); + $query = $this->entityTypeManager->getStorage($this->targetType)->getQuery(); $label_key = $entity_type->getKey('label'); if ($label_key) { - $query->condition($label_key, '%' . $match . '%', 'LIKE'); + // For configuration entities, the condition needs to be CONTAINS as + // the matcher does not support LIKE. + if ($entity_type instanceof ConfigEntityTypeInterface) { + $query->condition($label_key, $search_string, 'CONTAINS'); + } + else { + $query->condition($label_key, '%' . $search_string . '%', 'LIKE'); + } + $query->sort($label_key, 'ASC'); } @@ -271,19 +353,51 @@ class EntityMatcher extends ConfigurableMatcherBase { $query->condition($bundle_key, $this->configuration['bundles'], 'IN'); } - // Add tags to let other modules alter the query. - $query->addTag('linkit_entity_autocomplete'); - $query->addTag('linkit_entity_' . $this->target_type . '_autocomplete'); - - // Add access tag for the query. - $query->addTag('entity_access'); - $query->addTag($this->target_type . '_access'); + $this->addQueryTags($query); return $query; } /** - * Builds the label string used in the match array. + * Adds query tags to the query. + * + * @param \Drupal\Core\Entity\Query\QueryInterface $query + * A query to add tags to. + */ + protected function addQueryTags(QueryInterface $query) { + // Add tags to let other modules alter the query. + $query->addTag('linkit_entity_autocomplete'); + $query->addTag('linkit_entity_' . $this->targetType . '_autocomplete'); + + // Add access tag for the query. + $query->addTag('entity_access'); + $query->addTag($this->targetType . '_access'); + } + + /** + * Creates a suggestion. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The matched entity. + * + * @return \Drupal\linkit\Suggestion\EntitySuggestion + * A suggestion object with populated entity data. + */ + protected function createSuggestion(EntityInterface $entity) { + $suggestion = new EntitySuggestion(); + $suggestion->setLabel($this->buildLabel($entity)) + ->setGroup($this->buildGroup($entity)) + ->setDescription($this->buildDescription($entity)) + ->setEntityUuid($entity->uuid()) + ->setEntityTypeId($entity->getEntityTypeId()) + ->setSubstitutionId($this->configuration['substitution_type']) + ->setPath($this->buildPath($entity)); + + return $suggestion; + } + + /** + * Builds the label string used in the suggestion. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. @@ -291,39 +405,26 @@ class EntityMatcher extends ConfigurableMatcherBase { * @return string * The label for this entity. */ - protected function buildLabel($entity) { + protected function buildLabel(EntityInterface $entity) { return Html::escape($entity->label()); } /** - * Builds the description string used in the match array. + * Builds the metadata string used in the suggestion. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. * * @return string - * The description for this entity. + * The metadata for this entity. */ - protected function buildDescription($entity) { - $description = \Drupal::token()->replace($this->configuration['result_description'], [$this->target_type => $entity], []); + protected function buildDescription(EntityInterface $entity) { + $description = \Drupal::token()->replace($this->configuration['metadata'], [$this->targetType => $entity], ['clear' => TRUE]); return LinkitXss::descriptionFilter($description); } /** - * Builds the path string used in the match array. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The matched entity. - * - * @return string - * The URL for this entity. - */ - protected function buildPath($entity) { - return $entity->toUrl()->toString(); - } - - /** - * Builds the group string used in the match array. + * Builds the group string used in the suggestion. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. @@ -331,13 +432,13 @@ class EntityMatcher extends ConfigurableMatcherBase { * @return string * The match group for this entity. */ - protected function buildGroup($entity) { + protected function buildGroup(EntityInterface $entity) { $group = $entity->getEntityType()->getLabel(); // If the entities by this entity should be grouped by bundle, get the // name and append it to the group. if ($this->configuration['group_by_bundle']) { - $bundles = $this->entityManager->getBundleInfo($entity->getEntityTypeId()); + $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId()); $bundle_label = $bundles[$entity->bundle()]['label']; $group .= ' - ' . $bundle_label; } @@ -345,4 +446,43 @@ class EntityMatcher extends ConfigurableMatcherBase { return $group; } + /** + * Builds the path string used in the suggestion. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The matched entity. + * + * @return string + * The path for this entity. + */ + protected function buildPath(EntityInterface $entity) { + return $entity->toUrl('canonical', ['path_processing' => FALSE])->toString(); + } + + /** + * Finds entity id from the given input. + * + * @param string $user_input + * The string to url parse. + * + * @return array + * An array with an entity id if the input can be parsed as an internal url + * and a match is found, otherwise an empty array. + */ + protected function findEntityIdByUrl($user_input) { + $result = []; + + try { + $params = Url::fromUserInput($user_input)->getRouteParameters(); + if (key($params) === $this->targetType) { + $result = [end($params)]; + } + } + catch (Exception $e) { + // Do nothing. + } + + return $result; + } + } diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php index cb39ccfe6..28252a2fd 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FileMatcher.php @@ -1,21 +1,19 @@ t('Show image dimensions: @show_image_dimensions', [ + if (!empty($this->configuration['file_extensions'])) { + $summary[] = $this->t('Limit matches to the following file extensions: @file_extensions', [ + '@file_extensions' => str_replace(' ', ', ', $this->configuration['file_extensions']), + ]); + } + + $summary[] = $this->t('Show image dimensions: @show_image_dimensions', [ '@show_image_dimensions' => $this->configuration['images']['show_dimensions'] ? $this->t('Yes') : $this->t('No'), ]); - $summery[] = $this->t('Show image thumbnail: @show_image_thumbnail', [ + $summary[] = $this->t('Show image thumbnail: @show_image_thumbnail', [ '@show_image_thumbnail' => $this->configuration['images']['show_thumbnail'] ? $this->t('Yes') : $this->t('No'), ]); if ($this->moduleHandler->moduleExists('image') && $this->configuration['images']['show_thumbnail']) { $image_style = ImageStyle::load($this->configuration['images']['thumbnail_image_style']); - if (!is_null($image_style)) { - $summery[] = $this->t('Thumbnail style: @thumbnail_style', [ - '@thumbnail_style' => $image_style->label(), + if (!is_null($image_style)) { + $summary[] = $this->t('Thumbnail style: @thumbnail_style', [ + '@thumbnail_style' => $image_style->label(), ]); } } - return $summery; + return $summary; } /** * {@inheritdoc} */ public function defaultConfiguration() { - return parent::defaultConfiguration() + [ + return [ + 'file_extensions' => '', + 'file_status' => FILE_STATUS_PERMANENT, 'images' => [ 'show_dimensions' => FALSE, 'show_thumbnail' => FALSE, 'thumbnail_image_style' => 'linkit_result_thumbnail', ], - ]; + 'substitution_type' => 'file', + ] + parent::defaultConfiguration(); } /** @@ -82,28 +89,46 @@ class FileMatcher extends EntityMatcher { public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); - $form['images'] = array( + $form['extensions'] = [ '#type' => 'details', - '#title' => t('Image file settings'), - '#description' => t('Extra settings for image files in the result.'), + '#title' => $this->t('File extensions'), + '#open' => TRUE, + '#weight' => -100, + ]; + + $file_extensions = str_replace(' ', ', ', $this->configuration['file_extensions']); + $form['extensions']['file_extensions'] = [ + '#type' => 'textfield', + '#title' => $this->t('Allowed file extensions'), + '#default_value' => $file_extensions, + '#description' => $this->t('Separate extensions with a space or comma and do not include the leading dot.'), + '#element_validate' => [['\Drupal\file\Plugin\Field\FieldType\FileItem', 'validateExtensions']], + '#maxlength' => 256, + ]; + + $form['images'] = [ + '#type' => 'details', + '#title' => $this->t('Image file settings'), + '#description' => $this->t('Extra settings for image files in the result.'), + '#open' => TRUE, '#tree' => TRUE, - ); + ]; $form['images']['show_dimensions'] = [ - '#title' => t('Show pixel dimensions'), + '#title' => $this->t('Show pixel dimensions'), '#type' => 'checkbox', '#default_value' => $this->configuration['images']['show_dimensions'], ]; if ($this->moduleHandler->moduleExists('image')) { $form['images']['show_thumbnail'] = [ - '#title' => t('Show thumbnail'), + '#title' => $this->t('Show thumbnail'), '#type' => 'checkbox', '#default_value' => $this->configuration['images']['show_thumbnail'], ]; $form['images']['thumbnail_image_style'] = [ - '#title' => t('Thumbnail image style'), + '#title' => $this->t('Thumbnail image style'), '#type' => 'select', '#default_value' => $this->configuration['images']['thumbnail_image_style'], '#options' => image_style_options(FALSE), @@ -124,6 +149,8 @@ class FileMatcher extends EntityMatcher { public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { parent::submitConfigurationForm($form, $form_state); + $this->configuration['file_extensions'] = $form_state->getValue('file_extensions'); + $values = $form_state->getValue('images'); if (!$values['show_thumbnail']) { $values['thumbnail_image_style'] = NULL; @@ -135,9 +162,19 @@ class FileMatcher extends EntityMatcher { /** * {@inheritdoc} */ - protected function buildEntityQuery($match) { - $query = parent::buildEntityQuery($match); - $query->condition('status', FILE_STATUS_PERMANENT); + protected function buildEntityQuery($search_string) { + $query = parent::buildEntityQuery($search_string); + + $query->condition('status', $this->configuration['file_status']); + + if (!empty($this->configuration['file_extensions'])) { + $file_extensions = explode(' ', $this->configuration['file_extensions']); + $group = $query->orConditionGroup(); + foreach ($file_extensions as $file_extension) { + $group->condition('filename', '%\.' . $this->database->escapeLike($file_extension), 'LIKE'); + } + $query->condition($group); + } return $query; } @@ -145,8 +182,8 @@ class FileMatcher extends EntityMatcher { /** * {@inheritdoc} */ - protected function buildDescription($entity) { - $description_array = array(); + protected function buildDescription(EntityInterface $entity) { + $description_array = []; $description_array[] = parent::buildDescription($entity); @@ -161,29 +198,27 @@ class FileMatcher extends EntityMatcher { } if ($this->configuration['images']['show_thumbnail'] && $this->moduleHandler->moduleExists('image')) { - $image_element = array( + $image_element = [ '#weight' => -10, '#theme' => 'image_style', '#style_name' => $this->configuration['images']['thumbnail_image_style'], '#uri' => $entity->getFileUri(), - ); + ]; $description_array[] = (string) \Drupal::service('renderer')->render($image_element); } } - $description = implode('
    ' , $description_array); + $description = implode('
    ', $description_array); return LinkitXss::descriptionFilter($description); } /** * {@inheritdoc} - * - * The file entity still uses url() even though it's deprecated in the - * entity interface. */ - protected function buildPath($entity) { + protected function buildPath(EntityInterface $entity) { /** @var \Drupal\file\FileInterface $entity */ return file_url_transform_relative(file_create_url($entity->getFileUri())); } + } diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FrontPageMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FrontPageMatcher.php new file mode 100644 index 000000000..dd3ca15ea --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/FrontPageMatcher.php @@ -0,0 +1,40 @@ +setLabel($this->t('Front page')) + ->setPath(Url::fromRoute('')->toString()) + ->setGroup($this->t('System')) + ->setDescription($this->t('The front page for this site.')); + + $suggestions->addSuggestion($suggestion); + } + + return $suggestions; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/NodeMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/NodeMatcher.php index 4beb6f2a5..3a1424cc8 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/NodeMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/NodeMatcher.php @@ -1,19 +1,16 @@ FALSE, - ]; + ] + parent::defaultConfiguration(); } /** @@ -56,11 +53,17 @@ class NodeMatcher extends EntityMatcher { public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); - $form['include_unpublished'] = [ - '#title' => t('Include unpublished nodes'), + $form['unpublished_nodes'] = [ + '#type' => 'details', + '#title' => $this->t('Unpublished nodes'), + '#open' => TRUE, + ]; + + $form['unpublished_nodes']['include_unpublished'] = [ + '#title' => $this->t('Include unpublished nodes'), '#type' => 'checkbox', '#default_value' => $this->configuration['include_unpublished'], - '#description' => t('In order to see unpublished nodes, the requesting user must also have permissions to do so.'), + '#description' => $this->t('In order to see unpublished nodes, users must also have permissions to do so.'), ]; return $form; @@ -78,8 +81,8 @@ class NodeMatcher extends EntityMatcher { /** * {@inheritdoc} */ - protected function buildEntityQuery($match) { - $query = parent::buildEntityQuery($match); + protected function buildEntityQuery($search_string) { + $query = parent::buildEntityQuery($search_string); $no_access = !$this->currentUser->hasPermission('bypass node access') && !count($this->moduleHandler->getImplementations('node_grants')); if ($this->configuration['include_unpublished'] !== TRUE || $no_access) { diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/TermMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/TermMatcher.php index 513b1dccc..fcab6bea9 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/TermMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/TermMatcher.php @@ -1,20 +1,18 @@ replace($this->configuration['result_description'], ['term' => $entity], []); + protected function buildDescription(EntityInterface $entity) { + $description = \Drupal::token()->replace($this->configuration['metadata'], ['term' => $entity], []); return LinkitXss::descriptionFilter($description); } diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/UserMatcher.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/UserMatcher.php index 94a462a93..b1f707e68 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/UserMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Matcher/UserMatcher.php @@ -1,19 +1,17 @@ [], 'include_blocked' => FALSE, - ]; + ] + parent::defaultConfiguration(); } - /** * {@inheritdoc} */ @@ -63,20 +60,33 @@ class UserMatcher extends EntityMatcher { public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form = parent::buildConfigurationForm($form, $form_state); - $form['roles'] = array( + $form['role_restrictions'] = [ + '#type' => 'details', + '#title' => $this->t('Role restrictions'), + '#open' => TRUE, + '#weight' => -90, + ]; + + $form['role_restrictions']['roles'] = [ '#type' => 'checkboxes', '#title' => $this->t('Restrict to the selected roles'), - '#options' => array_diff_key(user_role_names(TRUE), array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID)), - '#default_value' => $this->configuration['roles'], - '#description' => $this->t('If none of the checkboxes is checked, allow all roles.'), + '#options' => array_diff_key(user_role_names(TRUE), [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]), + '#default_value' => $this->configuration['roles'], + '#description' => $this->t('If none of the checkboxes is checked, all roles are allowed.'), '#element_validate' => [[get_class($this), 'elementValidateFilter']], - ); + ]; - $form['include_blocked'] = [ - '#title' => t('Include blocked user'), + $form['blocked_users'] = [ + '#type' => 'details', + '#title' => $this->t('Blocked users'), + '#open' => TRUE, + ]; + + $form['blocked_users']['include_blocked'] = [ + '#title' => $this->t('Include blocked user'), '#type' => 'checkbox', '#default_value' => $this->configuration['include_blocked'], - '#description' => t('In order to see blocked users, the requesting user must also have permissions to do so.'), + '#description' => $this->t('In order to see blocked users, users must have permissions to do so.'), ]; return $form; @@ -95,12 +105,12 @@ class UserMatcher extends EntityMatcher { /** * {@inheritdoc} */ - protected function buildEntityQuery($match) { - $query = parent::buildEntityQuery($match); + protected function buildEntityQuery($search_string) { + $query = parent::buildEntityQuery($search_string); - $match = $this->database->escapeLike($match); + $search_string = $this->database->escapeLike($search_string); // The user entity don't specify a label key so we have to do it instead. - $query->condition('name', '%' . $match . '%', 'LIKE'); + $query->condition('name', '%' . $search_string . '%', 'LIKE'); // Filter by role. if (!empty($this->configuration['roles'])) { diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Canonical.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Canonical.php new file mode 100644 index 000000000..deff8928a --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Canonical.php @@ -0,0 +1,34 @@ +toUrl('canonical')->toString(TRUE); + } + + /** + * {@inheritdoc} + */ + public static function isApplicable(EntityTypeInterface $entity_type) { + return $entity_type->hasLinkTemplate('canonical'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/File.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/File.php new file mode 100644 index 000000000..854cf2129 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/File.php @@ -0,0 +1,39 @@ +setGeneratedUrl(file_create_url($entity->getFileUri())); + $url->addCacheableDependency($entity); + return $url; + } + + /** + * {@inheritdoc} + */ + public static function isApplicable(EntityTypeInterface $entity_type) { + return $entity_type->isSubclassOf('Drupal\file\FileInterface'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Media.php b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Media.php new file mode 100644 index 000000000..ddc1bf295 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Plugin/Linkit/Substitution/Media.php @@ -0,0 +1,100 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * Get the URL associated with a given entity. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to get a URL for. + * + * @return \Drupal\Core\GeneratedUrl + * A url to replace. + */ + public function getUrl(EntityInterface $entity) { + $url = new GeneratedUrl(); + + /** @var \Drupal\media\MediaTypeInterface $media_type */ + $media_type = $entity->get('bundle')->entity; + // Default to the canonical URL if the bundle doesn't have a source field. + if (empty($media_type->getSource()->getConfiguration()['source_field'])) { + return $entity->toUrl('canonical')->toString(TRUE); + } + + $source_field = $media_type->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $entity->{$source_field}->entity; + $url->setGeneratedUrl(file_create_url($file->getFileUri())); + $url->addCacheableDependency($entity); + return $url; + } + + /** + * Checks if this substitution plugin is applicable for the given entity type. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * An entity type object. + * + * @return bool + * If the plugin is applicable. + */ + public static function isApplicable(EntityTypeInterface $entity_type) { + return $entity_type->entityClassImplements('Drupal\media\MediaInterface'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/ProfileInterface.php b/sites/all/modules/contrib/fields/linkit/src/ProfileInterface.php index fae8275fe..de8c5da84 100644 --- a/sites/all/modules/contrib/fields/linkit/src/ProfileInterface.php +++ b/sites/all/modules/contrib/fields/linkit/src/ProfileInterface.php @@ -1,10 +1,5 @@ t('Description'), - 'class' => [RESPONSIVE_PRIORITY_MEDIUM], - ]; + $header['title'] = t('Profile'); + $header['description'] = [ + 'data' => t('Description'), + 'class' => [RESPONSIVE_PRIORITY_MEDIUM], + ]; return $header + parent::buildHeader(); } @@ -55,15 +50,7 @@ class ProfileListBuilder extends ConfigEntityListBuilder { 'title' => t('Manage matchers'), 'weight' => 10, 'url' => Url::fromRoute('linkit.matchers', [ - 'linkit_profile' => $entity->id() - ]), - ]; - - $operations['attributes'] = [ - 'title' => t('Manage attributes'), - 'weight' => 20, - 'url' => Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $entity->id() + 'linkit_profile' => $entity->id(), ]), ]; diff --git a/sites/all/modules/contrib/fields/linkit/src/ResultManager.php b/sites/all/modules/contrib/fields/linkit/src/ResultManager.php deleted file mode 100644 index bd4274454..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/ResultManager.php +++ /dev/null @@ -1,74 +0,0 @@ - t('No results'), - ]]; - } - - // Special for link to front page. - if (strpos($search_string, 'front') !== FALSE) { - $matches[] = [ - 'title' => t('Front page'), - 'description' => 'The front page for this site.', - 'path' => Url::fromRoute('')->toString(), - 'group' => t('System'), - ]; - } - - foreach ($linkitProfile->getMatchers() as $plugin) { - $matches = array_merge($matches, $plugin->getMatches($search_string)); - } - - // Check for an e-mail address then return an e-mail match and create a - // mail-to link if appropriate. - if (filter_var($search_string, FILTER_VALIDATE_EMAIL)) { - $matches[] = [ - 'title' => t('E-mail @email', ['@email' => $search_string]), - 'description' => t('Opens your mail client ready to e-mail @email', ['@email' => $search_string]), - 'path' => 'mailto:' . Html::escape($search_string), - 'group' => t('E-mail'), - ]; - } - - // If there is still no matches, return a "no results" array. - if (empty($matches)) { - return [[ - 'title' => t('No results'), - ]]; - } - - return $matches; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/SubstitutionInterface.php b/sites/all/modules/contrib/fields/linkit/src/SubstitutionInterface.php new file mode 100644 index 000000000..c39ec5a9f --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/SubstitutionInterface.php @@ -0,0 +1,36 @@ +alterInfo('linkit_substitution'); + $this->setCacheBackend($cache_backend, 'linkit_substitution'); + + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public function getApplicablePluginsOptionList($entity_type_id) { + $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); + $options = []; + foreach ($this->filterPlugins($this->getDefinitions(), $entity_type) as $id => $definition) { + $options[$id] = $definition['label']; + } + return $options; + } + + /** + * Filter the list of plugins by their applicability. + * + * @param array $definitions + * An array of plugin definitions. + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type to get applicable plugins for. + * + * @return array + * The definitions appropriate for the given entity type. + * + * @see SubstitutionInterface::isApplicable() + */ + protected function filterPlugins(array $definitions, EntityTypeInterface $entity_type) { + return array_filter($definitions, function ($definition) use ($entity_type) { + /** @var \Drupal\linkit\SubstitutionInterface $class */ + $class = $definition['class']; + return $class::isApplicable($entity_type); + }); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/SubstitutionManagerInterface.php b/sites/all/modules/contrib/fields/linkit/src/SubstitutionManagerInterface.php new file mode 100644 index 000000000..7f64aba41 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/SubstitutionManagerInterface.php @@ -0,0 +1,28 @@ +description; + } + + /** + * {@inheritdoc} + */ + public function setDescription($description) { + $this->description = $description; + return $this; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() { + + return parent::jsonSerialize() + [ + 'description' => $this->getDescription(), + ]; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Suggestion/EntitySuggestion.php b/sites/all/modules/contrib/fields/linkit/src/Suggestion/EntitySuggestion.php new file mode 100644 index 000000000..772db110f --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Suggestion/EntitySuggestion.php @@ -0,0 +1,81 @@ +entityUuid = $entity_uuid; + return $this; + } + + /** + * Sets the entity type id. + * + * @param string $entity_type_id + * The entity type id. + * + * @return $this + */ + public function setEntityTypeId($entity_type_id) { + $this->entityTypeId = $entity_type_id; + return $this; + } + + /** + * Sets the substitution id. + * + * @param string $substitution_id + * The substitution id. + * + * @return $this + */ + public function setSubstitutionId($substitution_id) { + $this->substitutionId = $substitution_id; + return $this; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() { + return parent::jsonSerialize() + [ + 'entity_uuid' => $this->entityUuid, + 'entity_type_id' => $this->entityTypeId, + 'substitution_id' => $this->substitutionId, + ]; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Suggestion/SimpleSuggestion.php b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SimpleSuggestion.php new file mode 100644 index 000000000..49063906d --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SimpleSuggestion.php @@ -0,0 +1,87 @@ +label; + } + + /** + * {@inheritdoc} + */ + public function setLabel($label) { + $this->label = $label; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getPath() { + return $this->path; + } + + /** + * {@inheritdoc} + */ + public function setPath($path) { + $this->path = $path; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getGroup() { + return $this->group; + } + + /** + * {@inheritdoc} + */ + public function setGroup($group) { + $this->group = $group; + return $this; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() { + return [ + 'label' => $this->getLabel(), + 'path' => $this->getPath(), + 'group' => $this->getGroup(), + ]; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionCollection.php b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionCollection.php new file mode 100644 index 000000000..de20548a3 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionCollection.php @@ -0,0 +1,56 @@ +suggestions; + } + + /** + * Adds a suggestion to this collection. + * + * @param \Drupal\linkit\Suggestion\SuggestionInterface $suggestion + * The suggestion to add to the collection. + */ + public function addSuggestion(SuggestionInterface $suggestion) { + $this->suggestions[] = $suggestion; + } + + /** + * Adds a collection of suggestions to the this collection. + * + * @param \Drupal\linkit\Suggestion\SuggestionCollection $suggestionCollection + * A collection of suggestions. + */ + public function addSuggestions(SuggestionCollection $suggestionCollection) { + $this->suggestions = array_merge($this->suggestions, $suggestionCollection->getSuggestions()); + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() { + return [ + 'suggestions' => $this->suggestions, + ]; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionDescriptionInterface.php b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionDescriptionInterface.php new file mode 100644 index 000000000..fc95c1189 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Suggestion/SuggestionDescriptionInterface.php @@ -0,0 +1,28 @@ +getMatchers() as $plugin) { + $suggestions->addSuggestions($plugin->execute($search_string)); + } + + return $suggestions; + } + + /** + * Adds an unscathed suggestion to the given suggestion collection. + * + * @param \Drupal\linkit\Suggestion\SuggestionCollection $suggestionCollection + * A suggestion collection to add the unscathed suggestion to. + * @param string $search_string + * The string ro use in the matchers. + * + * @return \Drupal\linkit\Suggestion\SuggestionCollection + * A suggestion collection. + */ + public function addUnscathedSuggestion(SuggestionCollection $suggestionCollection, $search_string) { + $suggestion = new DescriptionSuggestion(); + $suggestion->setLabel(Html::escape($search_string)) + ->setGroup($this->t('No results')) + ->setDescription($this->t('Linkit could not find any suggestions. This URL will be used as is.')) + ->setPath($search_string); + $suggestionCollection->addSuggestion($suggestion); + return $suggestionCollection; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/AttributeCrudTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/AttributeCrudTest.php deleted file mode 100644 index 5132ff5fb..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/AttributeCrudTest.php +++ /dev/null @@ -1,160 +0,0 @@ -manager = $this->container->get('plugin.manager.linkit.attribute'); - - $this->linkitProfile = $this->createProfile(); - $this->drupalLogin($this->adminUser); - } - - /** - * Test the overview page. - */ - function testOverview() { - $this->drupalGet(Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - $this->assertText(t('No attributes added.')); - - $this->assertLinkByHref(Url::fromRoute('linkit.attribute.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])->toString()); - } - - /** - * Test adding an attribute to a profile. - */ - function testAdd() { - $this->drupalGet(Url::fromRoute('linkit.attribute.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertEqual(count($this->manager->getDefinitions()), count($this->xpath('//input[@type="radio"]')), 'All attributes are available.'); - - $edit = array(); - $edit['plugin'] = 'dummy_attribute'; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - - $this->assertUrl(Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertEqual(1, count($this->xpath('//table/tbody/tr')), 'Attribute added.'); - $this->assertNoText(t('No attributes added.')); - } - - /** - * Test adding a configurable attribute to a profile. - */ - function testAddConfigurable() { - $this->drupalGet(Url::fromRoute('linkit.attribute.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertEqual(count($this->manager->getDefinitions()), count($this->xpath('//input[@type="radio"]')), 'All attributes are available.'); - - $edit = array(); - $edit['plugin'] = 'configurable_dummy_attribute'; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - - $this->assertUrl(Url::fromRoute('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => 'configurable_dummy_attribute', - ])); - - $this->drupalGet(Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertEqual(1, count($this->xpath('//table/tbody/tr')), 'Attribute added.'); - $this->assertNoText(t('No attributes added.')); - - $plugin_url = Url::fromRoute('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => 'configurable_dummy_attribute', - ]); - - $this->assertLinkByHref($plugin_url->toString()); - } - - /** - * Test delete an attribute from a profile. - */ - function testDelete() { - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance('dummy_attribute'); - - $this->linkitProfile->addAttribute($plugin->getConfiguration()); - $this->linkitProfile->save(); - - // Try delete an attribute that is not attached to the profile. - $this->drupalGet(Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => 'doesntexists' - ])); - $this->assertResponse('404'); - - // Go to the delete page, but press cancel. - $this->drupalGet(Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $plugin->getPluginId(), - ])); - $this->clickLink(t('Cancel')); - $this->assertUrl(Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - // Delete the attribute from the profile. - $this->drupalGet(Url::fromRoute('linkit.attribute.delete', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => 'dummy_attribute', - ])); - - $this->drupalPostForm(NULL, [], t('Confirm')); - $this->assertRaw(t('The attribute %plugin has been deleted.', ['%plugin' => $plugin->getLabel()])); - $this->assertUrl(Url::fromRoute('linkit.attributes', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - $this->assertText(t('No attributes added.')); - - /** @var \Drupal\linkit\Entity\Profile $updated_profile */ - $updated_profile = Profile::load($this->linkitProfile->id()); - $this->assertFalse($updated_profile->getAttributes()->has($plugin->getPluginId()), 'The attribute is deleted from the profile'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Controllers/LinkitControllerTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/Controllers/LinkitControllerTest.php deleted file mode 100644 index f7acbe8fc..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/Controllers/LinkitControllerTest.php +++ /dev/null @@ -1,83 +0,0 @@ -linkitProfile = $this->createProfile(); - - $this->drupalLogin($this->adminUser); - } - - /** - * Tests the profile route title callback. - */ - function testProfileTitle() { - $this->drupalGet(Url::fromRoute('entity.linkit_profile.edit_form', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertText('Edit ' . $this->linkitProfile->label() . ' profile'); - } - - /** - * Tests the matcher route title callback. - */ - function testMatcherTitle() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->container->get('plugin.manager.linkit.matcher')->createInstance('configurable_dummy_matcher'); - $matcher_uuid = $this->linkitProfile->addMatcher($plugin->getConfiguration()); - $this->linkitProfile->save(); - - $this->drupalGet(Url::fromRoute('linkit.matcher.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $matcher_uuid, - ])); - - $this->assertText('Edit ' . $plugin->getLabel() . ' matcher'); - } - - /** - * Tests the attribute route title callback. - */ - function testAttributeTitle() { - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->container->get('plugin.manager.linkit.attribute')->createInstance('configurable_dummy_attribute'); - $this->linkitProfile->addAttribute($plugin->getConfiguration()); - $this->linkitProfile->save(); - - $this->drupalGet(Url::fromRoute('linkit.attribute.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $plugin->getPluginId(), - ])); - $this->assertText('Edit ' . $plugin->getLabel() . ' attribute'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/LinkitTestBase.php b/sites/all/modules/contrib/fields/linkit/src/Tests/LinkitTestBase.php deleted file mode 100644 index 196dece20..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/LinkitTestBase.php +++ /dev/null @@ -1,83 +0,0 @@ -adminUser = $this->drupalCreateUser(['administer linkit profiles']); - $this->baseUser = $this->drupalCreateUser(); - - $this->drupalPlaceBlock('page_title_block', ['region' => 'content']); - $this->drupalPlaceBlock('local_tasks_block', ['region' => 'content']); - $this->drupalPlaceBlock('local_actions_block', ['region' => 'content']); - $this->drupalPlaceBlock('system_messages_block', ['region' => 'highlighted']); - } - - /** - * Creates a profile based on default settings. - * - * @param array $settings - * (optional) An associative array of settings for the profile, as used in - * entity_create(). Override the defaults by specifying the key and value - * in the array - * - * The following defaults are provided: - * - label: Random string. - * - * @return \Drupal\linkit\ProfileInterface - * The created profile entity. - */ - protected function createProfile(array $settings = []) { - // Populate defaults array. - $settings += [ - 'id' => Unicode::strtolower($this->randomMachineName()), - 'label' => $this->randomMachineName(), - ]; - - $profile = Profile::create($settings); - $profile->save(); - - return $profile; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/MatcherCrudTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/MatcherCrudTest.php deleted file mode 100644 index 528c378b2..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/MatcherCrudTest.php +++ /dev/null @@ -1,158 +0,0 @@ -manager = $this->container->get('plugin.manager.linkit.matcher'); - - $this->linkitProfile = $this->createProfile(); - $this->drupalLogin($this->adminUser); - } - - /** - * Test the overview page. - */ - function testOverview() { - $this->drupalGet(Url::fromRoute('linkit.matchers', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - $this->assertText(t('No matchers added.')); - - $this->assertLinkByHref(Url::fromRoute('linkit.matcher.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])->toString()); - } - - /** - * Test adding a matcher to a profile. - */ - function testAdd() { - $this->drupalGet(Url::fromRoute('linkit.matcher.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $edit = array(); - $edit['plugin'] = 'dummy_matcher'; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - - // Load the saved profile. - $this->linkitProfile = Profile::load($this->linkitProfile->id()); - - $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds(); - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->linkitProfile->getMatcher(current($matcher_ids)); - - $this->assertRaw(t('Added %label matcher.', ['%label' => $plugin->getLabel()])); - $this->assertNoText(t('No matchers added.')); - } - - /** - * Test adding a configurable attribute to a profile. - */ - function testAddConfigurable() { - $this->drupalGet(Url::fromRoute('linkit.matcher.add', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $edit = array(); - $edit['plugin'] = 'configurable_dummy_matcher'; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - - // Load the saved profile. - $this->linkitProfile = Profile::load($this->linkitProfile->id()); - - $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds(); - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->linkitProfile->getMatcher(current($matcher_ids)); - - $this->assertUrl(Url::fromRoute('linkit.matcher.edit', [ - 'linkit_profile' => $this->linkitProfile->id(), - 'plugin_instance_id' => $plugin->getUuid(), - ])); - - $this->drupalGet(Url::fromRoute('linkit.matchers', [ - 'linkit_profile' => $this->linkitProfile->id(), - ])); - - $this->assertNoText(t('No matchers added.')); - } - - /** - * Test delete a matcher from a profile. - */ - function testDelete() { - /** @var \Drupal\linkit\AttributeInterface $plugin */ - $plugin = $this->manager->createInstance('dummy_matcher'); - - $profile = $this->createProfile(); - $plugin_uuid = $profile->addMatcher($plugin->getConfiguration()); - $profile->save(); - - // Try delete a matcher that is not attached to the profile. - $this->drupalGet(Url::fromRoute('linkit.matcher.delete', [ - 'linkit_profile' => $profile->id(), - 'plugin_instance_id' => 'doesntexists' - ])); - $this->assertResponse('404'); - - // Go to the delete page, but press cancel. - $this->drupalGet(Url::fromRoute('linkit.matcher.delete', [ - 'linkit_profile' => $profile->id(), - 'plugin_instance_id' => $plugin_uuid, - ])); - $this->clickLink(t('Cancel')); - $this->assertUrl(Url::fromRoute('linkit.matchers', [ - 'linkit_profile' => $profile->id(), - ])); - - // Delete the matcher from the profile. - $this->drupalGet(Url::fromRoute('linkit.matcher.delete', [ - 'linkit_profile' => $profile->id(), - 'plugin_instance_id' => $plugin_uuid, - ])); - - $this->drupalPostForm(NULL, [], t('Confirm')); - $this->assertRaw(t('The matcher %plugin has been deleted.', ['%plugin' => $plugin->getLabel()])); - $this->assertUrl(Url::fromRoute('linkit.matchers', [ - 'linkit_profile' => $profile->id(), - ])); - $this->assertText(t('No matchers added.')); - - /** @var \Drupal\linkit\Entity\Profile $updated_profile */ - $updated_profile = Profile::load($profile->id()); - $this->assertFalse($updated_profile->getMatchers()->has($plugin_uuid), 'The user matcher is deleted from the profile'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/NodeMatcherTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/NodeMatcherTest.php deleted file mode 100644 index 9db476232..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/NodeMatcherTest.php +++ /dev/null @@ -1,105 +0,0 @@ -drupalLogin($this->adminUser); - $this->manager = $this->container->get('plugin.manager.linkit.matcher'); - - $type1 = $this->drupalCreateContentType(['type' => 'test1', 'name' => 'Test1']); - $type2 = $this->drupalCreateContentType(['type' => 'test2', 'name' => 'Test2']); - - // Nodes with type 1. - $this->drupalCreateNode(['title' => 'Lorem Ipsum 1', 'type' => $type1->id()]); - $this->drupalCreateNode(['title' => 'Lorem Ipsum 2', 'type' => $type1->id()]); - - // Nodes with type 1. - $this->drupalCreateNode(['title' => 'Lorem Ipsum 3', 'type' => $type2->id()]); - - // Unpublished node. - $this->drupalCreateNode(['title' => 'Lorem unpublishd', 'type' => $type1->id(), 'status' => FALSE]); - } - - /** - * Tests node matcher. - */ - function testNodeMatcherWidthDefaultConfiguration() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:node', []); - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(3, count($matches), 'Correct number of matches'); - } - - /** - * Tests node matcher with bundle filer. - */ - function testNodeMatcherWidthBundleFiler() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:node', [ - 'settings' => [ - 'bundles' => [ - 'test1' => 'test1' - ], - ], - ]); - - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(2, count($matches), 'Correct number of matches'); - } - - /** - * Tests node matcher with include unpublished setting activated. - */ - function testNodeMatcherWidthIncludeUnpublished() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:node', [ - 'settings' => [ - 'include_unpublished' => TRUE, - ], - ]); - - // Test without permissions to see unpublished nodes. - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(3, count($matches), 'Correct number of matches'); - - $account = $this->drupalCreateUser(['bypass node access']); - $this->drupalLogin($account); - - // Test with permissions to see unpublished nodes. - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(4, count($matches), 'Correct number of matches'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/UserMatcherTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/UserMatcherTest.php deleted file mode 100644 index 6150a1119..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/UserMatcherTest.php +++ /dev/null @@ -1,114 +0,0 @@ -drupalLogin($this->drupalCreateUser(['access user profiles'])); - $this->manager = $this->container->get('plugin.manager.linkit.matcher'); - - $custom_role = $this->drupalCreateRole(array(), 'custom_role', 'custom_role'); - $custom_role_admin = $this->drupalCreateRole(array(), 'custom_role_admin', 'custom_role_admin'); - - $this->drupalCreateUser([], 'lorem'); - $this->drupalCreateUser([], 'foo'); - - $account = $this->drupalCreateUser([], 'ipsumlorem'); - $account->addRole($custom_role); - $account->save(); - - $account = $this->drupalCreateUser([], 'lorem_custom_role'); - $account->addRole($custom_role); - $account->save(); - - $account = $this->drupalCreateUser([], 'lorem_custom_role_admin'); - $account->addRole($custom_role_admin); - $account->save(); - - $account = $this->drupalCreateUser([], 'blocked_lorem'); - $account->block(); - $account->save(); - } - - /** - * Tests user matcher. - */ - function testUserMatcherWidthDefaultConfiguration() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:user', []); - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(4, count($matches), 'Correct number of matches'); - } - - /** - * Tests user matcher with role filer. - */ - function testUserMatcherWidthRoleFiler() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:user', [ - 'settings' => [ - 'roles' => [ - 'custom_role' => 'custom_role' - ], - ], - ]); - - $matches = $plugin->getMatches('Lorem'); - $this->assertEqual(2, count($matches), 'Correct number of matches'); - } - - /** - * Tests user matcher with include blocked setting activated. - */ - function testUserMatcherWidthIncludeBlocked() { - /** @var \Drupal\linkit\MatcherInterface $plugin */ - $plugin = $this->manager->createInstance('entity:user', [ - 'settings' => [ - 'include_blocked' => TRUE, - ], - ]); - - // Test without permissions to see blocked users. - $matches = $plugin->getMatches('blocked'); - $this->assertEqual(0, count($matches), 'Correct number of matches'); - - $account = $this->drupalCreateUser(['administer users']); - $this->drupalLogin($account); - - // Test with permissions to see blocked users. - $matches = $plugin->getMatches('blocked'); - $this->assertEqual(1, count($matches), 'Correct number of matches'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCreationTrait.php b/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCreationTrait.php new file mode 100644 index 000000000..e662aaf14 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCreationTrait.php @@ -0,0 +1,44 @@ + Unicode::strtolower($this->randomMachineName()), + 'label' => $this->randomMachineName(), + ]; + + $profile = Profile::create($settings); + $profile->save(); + + $profile = Profile::load($profile->id()); + + return $profile; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCrudTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCrudTest.php deleted file mode 100644 index 93af4e9ce..000000000 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/ProfileCrudTest.php +++ /dev/null @@ -1,125 +0,0 @@ -drupalLogin($this->adminUser); - } - - /** - * Test the overview page. - */ - function testOverview() { - // Verify that the profile collection page is not accessible for regular - // users. - $this->drupalLogin($this->baseUser); - $this->drupalGet(Url::fromRoute('entity.linkit_profile.collection')); - $this->assertResponse(403); - $this->drupalLogout(); - - // Verify that the profile collection page is accessible for regular users. - $this->drupalLogin($this->adminUser); - - $profiles = []; - $profiles[] = $this->createProfile(); - $profiles[] = $this->createProfile(); - - $this->drupalGet(Url::fromRoute('entity.linkit_profile.collection')); - $this->assertResponse(200); - - // Assert that the 'Add profile' action exists. - $this->assertLinkByHref(Url::fromRoute('entity.linkit_profile.add_form')->toString()); - - /** @var \Drupal\linkit\ProfileInterface $profile */ - foreach ($profiles as $profile) { - $this->assertLinkByHref('admin/config/content/linkit/manage/' . $profile->id()); - $this->assertLinkByHref('admin/config/content/linkit/manage/' . $profile->id() . '/delete'); - } - } - - /** - * Creates profile. - */ - function testProfileCreation() { - $this->drupalGet(Url::fromRoute('entity.linkit_profile.add_form')); - $this->drupalGet('admin/config/content/linkit/add'); - $this->assertResponse(200); - - // Create a profile. - $edit = []; - $edit['label'] = Unicode::strtolower($this->randomMachineName()); - $edit['id'] = Unicode::strtolower($this->randomMachineName()); - $edit['description'] = $this->randomMachineName(16); - $this->drupalPostForm(NULL, $edit, t('Save and manage matchers')); - - $this->assertRaw(t('Created new profile %label.', ['%label' => $edit['label']])); - - $this->drupalGet(Url::fromRoute('entity.linkit_profile.collection')); - $this->assertText($edit['label'], 'Profile exists in the profile collection.'); - } - - /** - * Updates a profile. - */ - function testProfileUpdate() { - $profile = $this->createProfile(); - $this->drupalGet(Url::fromRoute('entity.linkit_profile.edit_form', [ - 'linkit_profile' => $profile->id(), - ])); - $this->assertResponse(200); - - $id_field = $this->xpath('.//input[not(@disabled) and @name="id"]'); - - $this->assertTrue(empty($id_field), 'Machine name field is disabled.'); - $this->assertLinkByHref(Url::fromRoute('entity.linkit_profile.edit_form', [ - 'linkit_profile' => $profile->id(), - ])->toString()); - $this->assertLinkByHref('admin/config/content/linkit/manage/' . $profile->id() . '/delete'); - - $edit = []; - $edit['label'] = $this->randomMachineName(); - $edit['description'] = $this->randomMachineName(16); - $this->drupalPostForm(NULL, $edit, t('Update profile')); - - $this->assertRaw(t('Updated profile %label.', ['%label' => $edit['label']])); - - $this->drupalGet(Url::fromRoute('entity.linkit_profile.collection')); - $this->assertText($edit['label'], 'Updated profile exists in the profile collection.'); - } - - /** - * Delete a profile. - */ - function testProfileDelete() { - /** @var \Drupal\linkit\ProfileInterface $profile */ - $profile = $this->createProfile(); - $this->drupalGet(Url::fromRoute('entity.linkit_profile.delete_form', [ - 'linkit_profile' => $profile->id(), - ])); - $this->drupalPostForm(NULL, [], t('Delete')); - - $this->assertRaw(t('The linkit profile %label has been deleted.', ['%label' => $profile->label()])); - $this->drupalGet(Url::fromRoute('entity.linkit_profile.collection')); - $this->assertNoText($profile->label(), 'Deleted profile does not exists in the profile collection.'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Update/LinkitUpdateTest.php b/sites/all/modules/contrib/fields/linkit/src/Tests/Update/LinkitUpdateTest.php new file mode 100644 index 000000000..38de523e4 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/src/Tests/Update/LinkitUpdateTest.php @@ -0,0 +1,152 @@ +configFactory = $this->container->get('config.factory'); + } + + /** + * Set database dump files to be used. + */ + protected function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../tests/fixtures/update/drupal-8.linkit-enabled.standard.php.gz', + __DIR__ . '/../../../tests/fixtures/update/linkit-additions.php', + ]; + } + + /** + * Tests linkit_update_8500(). + * + * @see linkit_update_8500() + */ + public function testLinkitUpdate8500() { + $editor = $this->configFactory->get('editor.editor.format_1'); + $this->assertTrue($editor->get('settings.plugins.linkit'), 'We got old linkit settings in the editor configuration.'); + $format_1_linkit_profile = $editor->get('settings.plugins.linkit.linkit_profile'); + + $editor = $this->configFactory->get('editor.editor.format_2'); + $this->assertTrue($editor->get('settings.plugins.linkit'), 'We got old linkit settings in the editor configuration.'); + $format_2_linkit_profile = $editor->get('settings.plugins.linkit.linkit_profile'); + + $editor = $this->configFactory->get('editor.editor.format_3'); + $this->assertTrue($editor->get('settings.plugins.linkit'), 'We got old linkit settings in the editor configuration.'); + $format_3_linkit_profile = $editor->get('settings.plugins.linkit.linkit_profile'); + + $this->runUpdates(); + + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile'); + $this->assertEqual(NULL, $test_profile->get('attributes'), 'Attributes are deleted from the profile.'); + + $editor = $this->configFactory->get('editor.editor.format_1'); + $this->assertNull($editor->get('settings.plugins.linkit'), 'Old linkit settings in the editor configuration is removed.'); + $this->assertEqual($editor->get('settings.toolbar.rows.0.1.items.0'), 'DrupalLink', 'Drupal link plugin is in the toolbar.'); + $this->assertNotEqual($editor->get('settings.toolbar.rows.0.1.items.1'), 'Linkit', 'Linkit plugin is removed from the toolbar.'); + $this->assertTrue($editor->get('settings.plugins.drupallink.linkit_enabled'), 'Drupal link plugin has linkit enabled.'); + $this->assertEqual($editor->get('settings.plugins.drupallink.linkit_profile'), $format_1_linkit_profile, 'Drupal link plugin uses the same profile as the old linkit plugin.'); + + $editor = $this->configFactory->get('editor.editor.format_2'); + $this->assertNull($editor->get('settings.plugins.linkit'), 'Old linkit settings in the editor configuration is removed.'); + $this->assertEqual($editor->get('settings.toolbar.rows.0.1.items.0'), 'DrupalLink', 'Drupal link plugin is in the toolbar.'); + $this->assertTrue($editor->get('settings.plugins.drupallink.linkit_enabled'), 'Drupal link plugin has linkit enabled.'); + $this->assertEqual($editor->get('settings.plugins.drupallink.linkit_profile'), $format_2_linkit_profile, 'Drupal link plugin uses the same profile as the old linkit plugin.'); + + $editor = $this->configFactory->get('editor.editor.format_3'); + $this->assertNull($editor->get('settings.plugins.linkit'), 'Old linkit settings in the editor configuration is removed.'); + $this->assertEqual($editor->get('settings.toolbar.rows.0.0.items.0'), 'DrupalLink', 'Drupal link plugin is in the toolbar.'); + $this->assertTrue($editor->get('settings.plugins.drupallink.linkit_enabled'), 'Drupal link plugin has linkit enabled.'); + $this->assertEqual($editor->get('settings.plugins.drupallink.linkit_profile'), $format_3_linkit_profile, 'Drupal link plugin uses the same profile as the old linkit plugin.'); + + $format = $this->configFactory->get('filter.format.format_1'); + $this->assertNotNull($format->get('filters.linkit'), 'Linkit filter is enabled.'); + $this->assertTrue($format->get('filters.linkit.weight') < $format->get('filters.filter_html.weight'), 'Linkit filter is running before filter_html.'); + + $format = $this->configFactory->get('filter.format.format_2'); + $this->assertNotNull($format->get('filters.linkit'), 'Linkit filter is enabled.'); + + $format = $this->configFactory->get('filter.format.format_3'); + $this->assertNotNull($format->get('filters.linkit'), 'Linkit filter is enabled.'); + + $htmlRestrictions = FilterFormat::load('format_1')->getHtmlRestrictions(); + $this->assertTrue(array_key_exists("data-entity-type", $htmlRestrictions['allowed']['a'])); + $this->assertTrue(array_key_exists("data-entity-uuid", $htmlRestrictions['allowed']['a'])); + + $htmlRestrictions = FilterFormat::load('format_3')->getHtmlRestrictions(); + $this->assertTrue(array_key_exists("data-entity-type", $htmlRestrictions['allowed']['a'])); + $this->assertTrue(array_key_exists("data-entity-uuid", $htmlRestrictions['allowed']['a'])); + } + + /** + * Tests linkit_update_8501(). + * + * @see linkit_update_8501() + */ + public function testLinkitUpdate8501() { + $this->runUpdates(); + + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile'); + $this->assertEqual('canonical', $test_profile->get('matchers.fc48c807-2a9c-44eb-b86b-7e134c1aa252.settings.substitution_type'), 'Content matcher has a substitution type of canonical.'); + $this->assertEqual('file', $test_profile->get('matchers.b8d6d672-6377-493f-b492-3cc69511cf17.settings.substitution_type'), 'File matcher has a substitution type of file.'); + + $htmlRestrictions = FilterFormat::load('format_1')->getHtmlRestrictions(); + $this->assertTrue(array_key_exists("data-entity-type", $htmlRestrictions['allowed']['a'])); + $this->assertTrue(array_key_exists("data-entity-uuid", $htmlRestrictions['allowed']['a'])); + $this->assertTrue(array_key_exists("data-entity-substitution", $htmlRestrictions['allowed']['a'])); + } + + /** + * Tests linkit_update_8502(). + * + * @see linkit_update_8502() + */ + public function testLinkitUpdate8502() { + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile'); + $this->assertNotNull($test_profile->get('matchers.fc48c807-2a9c-44eb-b86b-7e134c1aa252.settings.result_description'), 'Profile have result_description'); + + $this->runUpdates(); + + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile'); + $this->assertNull($test_profile->get('matchers.fc48c807-2a9c-44eb-b86b-7e134c1aa252.settings.result_description'), 'Profile does not have result_description'); + $this->assertNotNull($test_profile->get('matchers.fc48c807-2a9c-44eb-b86b-7e134c1aa252.settings.metadata'), 'Profile have metadata'); + } + + /** + * Tests linkit_update_8503(). + * + * @see linkit_update_8503() + */ + public function testLinkitUpdate8503() { + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile_imce'); + $this->assertNotNull($test_profile->get('third_party_settings.imce.use'), 'Profile have imce use'); + $this->assertNotNull($test_profile->get('third_party_settings.imce.scheme'), 'Profile have imce scheme'); + + $this->runUpdates(); + + $test_profile = $this->configFactory->get('linkit.linkit_profile.test_profile_imce'); + $this->assertNull($test_profile->get('third_party_settings.imce.use'), 'Profile does not have imce use'); + $this->assertNull($test_profile->get('third_party_settings.imce.scheme'), 'Profile does not have imce scheme'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Utility/LinkitXss.php b/sites/all/modules/contrib/fields/linkit/src/Utility/LinkitXss.php index 1c8b5c890..101adff21 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Utility/LinkitXss.php +++ b/sites/all/modules/contrib/fields/linkit/src/Utility/LinkitXss.php @@ -1,10 +1,5 @@
      1. ' + filter_html_help: true + filter_html_nofollow: false diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml new file mode 100644 index 000000000..1bd9a2b6f --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_2.yml @@ -0,0 +1,8 @@ +uuid: 69cd7d6b-3c80-4f49-9631-7fbd7b011d5d +langcode: en +status: true +dependencies: { } +name: 'Format 2' +format: format_2 +weight: 0 +filters: { } diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml new file mode 100644 index 000000000..eb14f97a5 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/filter.format.format_3.yml @@ -0,0 +1,17 @@ +uuid: ff6b71a0-5051-4857-a0a8-28a670b7317d +langcode: en +status: true +dependencies: { } +name: 'Format 3' +format: format_3 +weight: 0 +filters: + filter_html: + id: filter_html + provider: filter + status: true + weight: -10 + settings: + allowed_html: '
          1. ' + filter_html_help: true + filter_html_nofollow: false diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php new file mode 100644 index 000000000..07a60f148 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit-additions.php @@ -0,0 +1,73 @@ +insert('config') + ->fields([ + 'collection', + 'name', + 'data', + ]) + ->values([ + 'collection' => '', + 'name' => 'linkit.linkit_profile.' . $config['id'], + 'data' => serialize($config), + ]) + ->execute(); +} + +// Configuration for text formats. +$configs = []; +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_1.yml')); +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_2.yml')); +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/filter.format.format_3.yml')); +foreach ($configs as $config) { + $connection->insert('config') + ->fields([ + 'collection', + 'name', + 'data', + ]) + ->values([ + 'collection' => '', + 'name' => 'filter.format.' . $config['format'], + 'data' => serialize($config), + ]) + ->execute(); +} + +// Configuration for editors. +$configs = []; +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_1.yml')); +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_2.yml')); +$configs[] = Yaml::decode(file_get_contents(__DIR__ . '/editor.editor.format_3.yml')); +foreach ($configs as $config) { + $connection->insert('config') + ->fields([ + 'collection', + 'name', + 'data', + ]) + ->values([ + 'collection' => '', + 'name' => 'editor.editor.' . $config['format'], + 'data' => serialize($config), + ]) + ->execute(); +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml new file mode 100644 index 000000000..bee4523d0 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile.yml @@ -0,0 +1,47 @@ +uuid: e91c2255-2146-46fb-af58-1b391113c352 +langcode: en +status: true +dependencies: + module: + - file + - node +id: test_profile +label: 'Test profile' +description: 'This is a test profile' +attributes: + target: + id: target + weight: 0 + settings: + widget_type: simple_checkbox + title: + id: title + weight: 0 + settings: + automatic_title: false + accesskey: + id: accesskey + weight: 0 + settings: { } +matchers: + fc48c807-2a9c-44eb-b86b-7e134c1aa252: + uuid: fc48c807-2a9c-44eb-b86b-7e134c1aa252 + id: 'entity:node' + weight: 0 + settings: + result_description: 'by [node:author] | [node:created:medium]' + bundles: { } + group_by_bundle: false + include_unpublished: false + b8d6d672-6377-493f-b492-3cc69511cf17: + uuid: b8d6d672-6377-493f-b492-3cc69511cf17 + id: 'entity:file' + weight: 0 + settings: + result_description: '[file:path] [file:url]' + bundles: null + group_by_bundle: null + images: + show_dimensions: false + show_thumbnail: false + thumbnail_image_style: null diff --git a/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml new file mode 100644 index 000000000..c906d2f8c --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/fixtures/update/linkit.linkit_profile.test_profile_with_imce.yml @@ -0,0 +1,24 @@ +uuid: 3cfc827f-07ff-456e-86db-a831e3770a03 +langcode: en +status: true +dependencies: + module: + - imce + - node +third_party_settings: + imce: + use: 1 + scheme: public +id: test_profile_imce +label: 'Test profile imce' +description: 'This is a test profile with imce settings' +matchers: + 556010a3-e317-48b3-b4ed-854c10f4b950: + uuid: 556010a3-e317-48b3-b4ed-854c10f4b950 + id: 'entity:node' + weight: 0 + settings: + result_description: 'by [node:author] | [node:created:medium]' + bundles: { } + group_by_bundle: false + include_unpublished: false diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml index 2e78ae55c..ce29e8fcd 100644 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml +++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/config/schema/linkit_test.schema.yml @@ -1,13 +1,5 @@ # Schema for the configuration files of the Linkit test module. - -# Plugin \Drupal\linkit_test\Plugin\Linkit\Attribute\ConfigurableDummyAttribute -linkit.attribute.configurable_dummy_attribute: - type: linkit.attribute - mapping: - dummy_setting: - type: boolean - # Plugin \Drupal\linkit_test\Plugin\Linkit\Matcher\ConfigurableDummyMatcher linkit.matcher.configurable_dummy_matcher: type: linkit.matcher diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml index 0262e996d..d3ba29c9e 100644 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml +++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.info.yml @@ -5,12 +5,12 @@ type: module # version: VERSION # core: 8.x dependencies: - - linkit - - field - - text + - linkit:linkit + - drupal:field + - drupal:text -# Information added by Drupal.org packaging script on 2017-03-21 -version: '8.x-4.3' +# Information added by Drupal.org packaging script on 2018-03-08 +version: '8.x-5.0-beta7' core: '8.x' project: 'linkit' -datestamp: 1490127367 +datestamp: 1520552594 diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module index 178e46d98..e2b2c055f 100644 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module +++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/linkit_test.module @@ -4,13 +4,3 @@ * @file * Support module for Linkit testing. */ - - -/** - * Implements hook_linkit_attribute_alter(). - */ -function linkit_test_linkit_attribute_alter(&$linkit_attribute_info) { - if (isset($linkit_attribute_info['dummyattribute'])) { - $linkit_attribute_info['dummyattribute']['description'] = t('Altered dummy description'); - } -} diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php deleted file mode 100644 index 7dde958bf..000000000 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/ConfigurableDummyAttribute.php +++ /dev/null @@ -1,73 +0,0 @@ - 'textfield', - '#title' => t('DummyAttribute'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - ]; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return parent::defaultConfiguration() + [ - 'dummy_setting' => FALSE, - ]; - } - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form['dummy_setting'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Dummy setting'), - '#default_value' => $this->configuration['dummy_setting'], - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { - } - - /** - * {@inheritdoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['dummy_setting'] = $form_state->getValue('dummy_setting'); - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php deleted file mode 100644 index 82581674c..000000000 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Attribute/DummyAttribute.php +++ /dev/null @@ -1,37 +0,0 @@ - 'textfield', - '#title' => t('DummyAttribute'), - '#default_value' => $default_value, - '#maxlength' => 255, - '#size' => 40, - ]; - } - -} diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php index 8bcc60b16..d190997ad 100644 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/ConfigurableDummyMatcher.php @@ -1,18 +1,15 @@ 'Configurable Dummy Matcher title', - 'description' => 'Configurable Dummy Matcher description', - 'path' => 'http://example.com', - 'group' => 'Configurable Dummy Matcher', - ]; + public function execute($string) { + $suggestions = new SuggestionCollection(); + $suggestion = new DescriptionSuggestion(); + $suggestion->setLabel('Configurable Dummy Matcher title') + ->setPath('http://example.com') + ->setGroup('Configurable Dummy Matcher') + ->setDescription('Configurable Dummy Matcher description'); - return $matches; + $suggestions->addSuggestion($suggestion); + + return $suggestions; } } diff --git a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php index 242e7145c..8a7386067 100644 --- a/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php +++ b/sites/all/modules/contrib/fields/linkit/tests/linkit_test/src/Plugin/Linkit/Matcher/DummyMatcher.php @@ -1,17 +1,14 @@ setLabel('Dummy Matcher title') + ->setPath('http://example.com') + ->setGroup('Dummy Matcher'); - /** - * {@inheritdoc} - */ - public function getMatches($string) { - $matches[] = [ - 'title' => 'DummyMatcher title', - 'description' => 'DummyMatcher description', - 'path' => 'http://example.com', - 'group' => 'DummyMatcher', - ]; + $suggestions->addSuggestion($suggestion); - return $matches; + return $suggestions; } } diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php new file mode 100644 index 000000000..e931e85ee --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/Controllers/LinkitControllerTest.php @@ -0,0 +1,60 @@ +linkitProfile = $this->createProfile(); + } + + /** + * Tests the profile route title callback. + */ + public function testProfileTitle() { + $this->drupalLogin($this->adminUser); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id()); + + $this->assertSession()->pageTextContains('Edit ' . $this->linkitProfile->label() . ' profile'); + } + + /** + * Tests the matcher route title callback. + */ + public function testMatcherTitle() { + $this->drupalLogin($this->adminUser); + + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->container->get('plugin.manager.linkit.matcher')->createInstance('configurable_dummy_matcher'); + $matcher_uuid = $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $matcher_uuid); + + $this->assertSession()->pageTextContains('Edit ' . $plugin->getLabel() . ' matcher'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php new file mode 100644 index 000000000..dc661fd0a --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/LinkitBrowserTestBase.php @@ -0,0 +1,48 @@ +placeBlock('page_title_block'); + $this->placeBlock('local_tasks_block'); + $this->placeBlock('local_actions_block'); + $this->placeBlock('system_messages_block'); + + $this->adminUser = $this->drupalCreateUser(['administer linkit profiles']); + $this->webUser = $this->drupalCreateUser(); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php new file mode 100644 index 000000000..2cf52ec1d --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/MatcherAdminTest.php @@ -0,0 +1,138 @@ +manager = $this->container->get('plugin.manager.linkit.matcher'); + + $this->linkitProfile = $this->createProfile(); + } + + /** + * Test the overview page. + */ + public function testOverview() { + $this->drupalLogin($this->adminUser); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers'); + $this->assertSession()->pageTextContains(t('No matchers added.')); + + // Make sure the 'Add matcher' action link is present. + $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add'); + } + + /** + * Test adding a matcher to a profile. + */ + public function testAdd() { + $this->drupalLogin($this->adminUser); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add'); + + // Create matcher. + $edit = []; + $edit['plugin'] = 'dummy_matcher'; + $this->submitForm($edit, t('Save and continue')); + + // Reload the profile. + $this->linkitProfile = Profile::load($this->linkitProfile->id()); + + $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds(); + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->linkitProfile->getMatcher(current($matcher_ids)); + + $this->assertSession()->responseContains(t('Added %label matcher.', ['%label' => $plugin->getLabel()])); + $this->assertSession()->pageTextNotContains(t('No matchers added.')); + } + + /** + * Test adding a configurable attribute to a profile. + */ + public function testAddConfigurable() { + $this->drupalLogin($this->adminUser); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/add'); + + // Create configurable matcher. + $edit = []; + $edit['plugin'] = 'configurable_dummy_matcher'; + $this->submitForm($edit, t('Save and continue')); + + // Reload the profile. + $this->linkitProfile = Profile::load($this->linkitProfile->id()); + + $matcher_ids = $this->linkitProfile->getMatchers()->getInstanceIds(); + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->linkitProfile->getMatcher(current($matcher_ids)); + + $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin->getUuid()); + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers'); + + $this->assertSession()->pageTextNotContains(t('No matchers added.')); + } + + /** + * Test delete a matcher from a profile. + */ + public function testDelete() { + $this->drupalLogin($this->adminUser); + + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('dummy_matcher'); + + $plugin_uuid = $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + // Try delete a matcher that is not attached to the profile. + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/doesntexists/delete'); + $this->assertSession()->statusCodeEquals('404'); + + // Go to the delete page, but press cancel. + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin_uuid . '/delete'); + $this->clickLink(t('Cancel')); + $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers'); + + // Delete the matcher from the profile. + $this->drupalGet('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers/' . $plugin_uuid . '/delete'); + + $this->submitForm([], t('Confirm')); + $this->assertSession()->responseContains(t('The matcher %plugin has been deleted.', ['%plugin' => $plugin->getLabel()])); + $this->assertSession()->addressEquals('/admin/config/content/linkit/manage/' . $this->linkitProfile->id() . '/matchers'); + $this->assertSession()->pageTextContains(t('No matchers added.')); + + /** @var \Drupal\linkit\Entity\Profile $updated_profile */ + $updated_profile = Profile::load($this->linkitProfile->id()); + $this->assertFalse($updated_profile->getMatchers()->has($plugin_uuid), 'The user matcher is deleted from the profile'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php new file mode 100644 index 000000000..3b840b9ab --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Functional/ProfileAdminTest.php @@ -0,0 +1,128 @@ +drupalLogin($this->webUser); + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->statusCodeEquals(403); + $this->drupalLogout(); + + // Login as an admin user and make sure the collection page is accessible. + $this->drupalLogin($this->adminUser); + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->statusCodeEquals(200); + + // Make sure the 'Add profile' action link is present. + $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/add'); + + // Create multiple profiles. + $profiles = []; + $profiles[] = $this->createProfile(); + $profiles[] = $this->createProfile(); + + // Refresh the page. + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->statusCodeEquals(200); + + // Make sure that there is an edit and a delete operation link for all + // profiles. + foreach ($profiles as $profile) { + $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id()); + $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id() . '/delete'); + } + } + + /** + * Creates profile. + */ + public function testProfileCreation() { + $this->drupalLogin($this->adminUser); + + // Make sure the profile add page is accessible. + $this->drupalGet('/admin/config/content/linkit/add'); + $this->assertSession()->statusCodeEquals(200); + + // Create a profile. + $edit = []; + $edit['label'] = Unicode::strtolower($this->randomMachineName()); + $edit['id'] = Unicode::strtolower($this->randomMachineName()); + $edit['description'] = $this->randomMachineName(16); + $this->submitForm($edit, t('Save and manage matchers')); + + // Make sure that the new profile was saved properly. + $this->assertSession()->responseContains(t('Created new profile %label.', ['%label' => $edit['label']])); + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->pageTextContains($edit['label']); + } + + /** + * Updates a profile. + */ + public function testProfileUpdate() { + $this->drupalLogin($this->adminUser); + + // Create a profile. + $profile = $this->createProfile(); + + // Make sure the profile edit page is accessible. + $this->drupalGet('/admin/config/content/linkit/manage/' . $profile->id()); + $this->assertSession()->statusCodeEquals(200); + + // Make sure the machine name field is disabled and that we have certain + // elements presented. + $this->assertSession()->elementNotExists('xpath', '//input[not(@disabled) and @name="id"]'); + $this->assertSession()->buttonExists('Update profile'); + $this->assertSession()->linkByHrefExists('/admin/config/content/linkit/manage/' . $profile->id() . '/delete'); + + // Update the profile. + $edit = []; + $edit['label'] = $this->randomMachineName(); + $edit['description'] = $this->randomMachineName(16); + $this->submitForm($edit, t('Update profile')); + + // Make sure that the profile was updated properly. + $this->assertSession()->responseContains(t('Updated profile %label.', ['%label' => $edit['label']])); + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->pageTextContains($edit['label']); + } + + /** + * Delete a profile. + */ + public function testProfileDelete() { + $this->drupalLogin($this->adminUser); + + // Create a profile. + $profile = $this->createProfile(); + + $this->drupalGet('/admin/config/content/linkit/manage/' . $profile->id() . '/delete'); + $this->assertSession()->statusCodeEquals(200); + + // Delete the profile. + $this->submitForm([], t('Delete')); + + // Make sure that the profile was deleted properly. + $this->assertSession()->responseContains(t('The linkit profile %label has been deleted.', ['%label' => $profile->label()])); + $this->drupalGet('/admin/config/content/linkit'); + $this->assertSession()->responseNotContains($profile->label()); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php new file mode 100644 index 000000000..dfad7ab74 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitDialogTest.php @@ -0,0 +1,320 @@ +container->get('plugin.manager.linkit.matcher'); + /** @var \Drupal\linkit\MatcherInterface $plugin */ + + $this->linkitProfile = $this->createProfile(); + $plugin = $matcherManager->createInstance('entity:entity_test_mul'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + // Create text format, associate CKEditor. + $llama_format = FilterFormat::create([ + 'format' => 'llama', + 'name' => 'Llama', + 'weight' => 0, + 'filters' => [], + ]); + $llama_format->save(); + $editor = Editor::create([ + 'format' => 'llama', + 'editor' => 'ckeditor', + ]); + $editor->save(); + + // Create "CKEditor" text editor plugin instance. + $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor'); + + // Create a node type for testing. + NodeType::create(['type' => 'page', 'name' => 'page'])->save(); + + // Create a body field instance for the 'page' node type. + FieldConfig::create([ + 'field_storage' => FieldStorageConfig::loadByName('node', 'body'), + 'bundle' => 'page', + 'label' => 'Body', + 'settings' => ['display_summary' => TRUE], + 'required' => TRUE, + ])->save(); + + // Assign widget settings for the 'default' form mode. + EntityFormDisplay::create([ + 'targetEntityType' => 'node', + 'bundle' => 'page', + 'mode' => 'default', + 'status' => TRUE, + ])->setComponent('body', ['type' => 'text_textarea_with_summary'])->save(); + + // Customize the configuration. + $this->container->get('plugin.manager.editor')->clearCachedDefinitions(); + + $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor'); + $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions(); + $settings = $editor->getSettings(); + $settings['plugins']['drupallink']['linkit_enabled'] = TRUE; + $settings['plugins']['drupallink']['linkit_profile'] = $this->linkitProfile->id(); + $editor->setSettings($settings); + $editor->save(); + + $account = $this->drupalCreateUser([ + 'administer nodes', + 'create page content', + 'edit own page content', + 'use text format llama', + 'view test entity', + ]); + + $this->drupalLogin($account); + } + + /** + * Test the link dialog. + */ + public function testLinkDialog() { + $session = $this->getSession(); + $web_assert = $this->assertSession(); + $page = $session->getPage(); + + // Adds additional languages. + $langcodes = ['sv', 'da', 'fi']; + foreach ($langcodes as $langcode) { + ConfigurableLanguage::createFromLangcode($langcode)->save(); + } + + // Create a test entity. + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + $entity = EntityTestMul::create(['name' => 'Foo']); + $entity->save(); + + // Go to node creation page. + $this->drupalGet('node/add/page'); + + // Wait until the editor has been loaded. + $ckeditor_loaded = $this->getSession()->wait(5000, "jQuery('.cke_contents').length > 0"); + $this->assertTrue($ckeditor_loaded, 'The editor has been loaded.'); + + // Click on the drupallink plugin. + $page->find('css', 'a.cke_button__drupallink')->click(); + + // Wait for the form to load. + $web_assert->assertWaitOnAjaxRequest(); + + // Find the href field. + $href_field = $page->findField('attributes[href]'); + + // Make sure the href field is an autocomplete field. + $href_field->hasAttribute('data-autocomplete-path'); + $href_field->hasClass('form-linkit-autocomplete'); + $href_field->hasClass('ui-autocomplete-input'); + + // Make sure all fields are empty. + $this->assertEmpty($href_field->getValue(), 'Href field is empty.'); + $this->assertEmptyWithJs('attributes[data-entity-type]'); + $this->assertEmptyWithJs('attributes[data-entity-uuid]'); + $this->assertEmptyWithJs('attributes[data-entity-substitution]'); + $this->assertEmptyWithJs('href_dirty_check'); + + // Make sure the autocomplete result container is hidden. + $autocomplete_container = $page->find('css', 'ul.linkit-ui-autocomplete'); + $this->assertFalse($autocomplete_container->isVisible()); + + // Trigger a keydown event to active a autocomplete search. + $href_field->keyDown('f'); + + // Wait for the results to load. + $this->getSession()->wait(5000, "jQuery('.linkit-result-line.ui-menu-item').length > 0"); + + // Make sure the autocomplete result container is visible. + $this->assertTrue($autocomplete_container->isVisible()); + + // Find all the autocomplete results. + $results = $page->findAll('css', '.linkit-result-line.ui-menu-item'); + $this->assertEquals(1, count($results), 'Found autocomplete result'); + + // Find the first result and click it. + $page->find('xpath', '//li[contains(@class, "linkit-result-line") and contains(@class, "ui-menu-item")][1]')->click(); + + // Make sure the linkit field field is populated with the node url. + $this->assertEquals($entity->toUrl()->toString(), $href_field->getValue(), 'The href field is populated with the node url.'); + + // Make sure all other fields are populated. + $this->assertEqualsWithJs('attributes[data-entity-type]', $entity->getEntityTypeId()); + $this->assertEqualsWithJs('attributes[data-entity-uuid]', $entity->uuid()); + $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical'); + $this->assertEqualsWithJs('href_dirty_check', $entity->toUrl()->toString()); + + // Save the dialog input. + $this->click('.editor-link-dialog button:contains("Save")'); + + // Wait for the dialog to close. + $web_assert->assertWaitOnAjaxRequest(); + + $fields = [ + 'data-entity-type' => $entity->getEntityTypeId(), + 'data-entity-uuid' => $entity->uuid(), + 'data-entity-substitution' => 'canonical', + 'href' => $entity->toUrl()->toString(), + ]; + foreach ($fields as $attribute => $value) { + $link_attribute = $this->getLinkAttributeFromEditor($attribute); + $this->assertEquals($value, $link_attribute, 'The link contain an attribute by the name of "' . $attribute . '" with a value of "' . $value . '"'); + } + + // Select the link in the editor. + $javascript = <<executeScript($javascript); + + // Click on the drupallink plugin. + $page->find('css', 'a.cke_button__drupallink')->click(); + + // Wait for the form to load. + $web_assert->assertWaitOnAjaxRequest(); + + // Find the href field. + $href_field = $page->findField('attributes[href]'); + $this->assertEquals($entity->toUrl()->toString(), $href_field->getValue(), 'Href field contains the node url when edit.'); + + // Make sure all other fields are populated when editing a link. + $this->assertEqualsWithJs('attributes[data-entity-type]', $entity->getEntityTypeId()); + $this->assertEqualsWithJs('attributes[data-entity-uuid]', $entity->uuid()); + $this->assertEqualsWithJs('attributes[data-entity-substitution]', 'canonical'); + $this->assertEqualsWithJs('href_dirty_check', $entity->toUrl()->toString()); + + // Edit the href field and set an external url. + $href_field->setValue('http://example.com'); + + // Save the dialog input. + $this->click('.editor-link-dialog button:contains("Save")'); + + // Wait for the dialog to close. + $web_assert->assertWaitOnAjaxRequest(); + + $fields = [ + 'data-entity-type', + 'data-entity-uuid', + 'data-entity-substitution', + ]; + foreach ($fields as $attribute) { + $link_attribute = $this->getLinkAttributeFromEditor($attribute); + $this->assertNull($link_attribute, 'The link does not contain an attribute by the name of "' . $attribute . '"'); + } + + $href_attribute = $this->getLinkAttributeFromEditor('href'); + $this->assertEquals('http://example.com', $href_attribute, 'The link href is correct.'); + } + + /** + * Asserts that a variable is empty. + * + * @param string $field_name + * The name of the field. + */ + private function assertEmptyWithJs($field_name) { + $javascript = "(function (){ return jQuery('input[name=\"" . $field_name . "\"]').val(); })()"; + $field_value = $this->getSession()->evaluateScript($javascript); + $this->assertEmpty($field_value, 'The "' . $field_name . '" field is empty.'); + } + + /** + * Asserts that two variables are equal. + * + * @param string $field_name + * The name of the field. + * @param string $expected + * The expected value. + */ + private function assertEqualsWithJs($field_name, $expected) { + $javascript = "(function (){ return jQuery('input[name=\"" . $field_name . "\"]').val(); })()"; + $field_value = $this->getSession()->evaluateScript($javascript); + $this->assertEquals($expected, $field_value, 'The "' . $field_name . '" field has a value of "' . $expected . '".'); + } + + /** + * Gets an attribute of the first link in the ckeditor editor. + * + * @param string $attribute + * The attribute name. + * + * @return string|null + * The attribute, or null if the attribute is not found on the element. + */ + private function getLinkAttributeFromEditor($attribute) { + // We can't use $session->switchToIFrame() here, because the iframe does not + // have a name. + $javascript = <<getSession()->evaluateScript($javascript); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php new file mode 100644 index 000000000..7d2d79c64 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/FunctionalJavascript/LinkitFormatAdminTest.php @@ -0,0 +1,59 @@ +drupalCreateUser([ + 'administer filters', + ]); + $this->drupalLogin($account); + } + + /** + * Tests that linkit filter is toggling the filter_html allowed tags. + */ + public function testToggleLinkitFilter() { + $session = $this->getSession(); + $page = $session->getPage(); + + // Go to add filter page. + $this->drupalGet('admin/config/content/formats/add'); + $this->assertSession()->statusCodeEquals(200); + + // Enable the 'Limit allowed HTML tags and correct faulty HTML' filter. + $page->findField('filters[filter_html][status]')->check(); + + $javascript = "(function (){ return jQuery('p.editor-update-message > strong').text(); })()"; + $this->assertNotContains('', $session->evaluateScript($javascript)); + + // Enable the 'Linkit filter' filter. + $page->findField('filters[linkit][status]')->check(); + $this->assertContains('', $session->evaluateScript($javascript)); + + // Disable the 'Linkit filter' filter. + $page->findField('filters[linkit][status]')->uncheck(); + $this->assertNotContains('', $session->evaluateScript($javascript)); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php new file mode 100644 index 000000000..24ca82273 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/AssertLinkitFilterTrait.php @@ -0,0 +1,83 @@ +getEntityTypeId() === "file") { + /** @var \Drupal\file\Entity\File $entity */ + $href = file_create_url($entity->getFileUri()); + } + else { + $href = $entity->toUrl()->toString(); + } + + $input = 'Link text'; + $expected = 'Link text'; + $this->assertSame($expected, $this->process($input, $langcode)->getProcessedText()); + } + + /** + * Asserts that Linkit filter correctly processes the content titles. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity object to check. + * @param string $langcode + * The language code of the text to be filtered. + */ + protected function assertLinkitFilterWithTitle(EntityInterface $entity, $langcode = LanguageInterface::LANGCODE_SITE_DEFAULT) { + if ($entity->getEntityTypeId() === "file") { + /** @var \Drupal\file\Entity\File $entity */ + $href = file_create_url($entity->getFileUri()); + } + else { + $href = $entity->toUrl()->toString(); + } + + $input = 'Link text'; + $expected = 'Link text'; + $this->assertSame($expected, $this->process($input, $langcode)->getProcessedText()); + } + + /** + * Test helper method that wraps the filter process method. + * + * @param string $input + * The text string to be filtered. + * @param string $langcode + * The language code of the text to be filtered. + * + * @return \Drupal\filter\FilterProcessResult + * The filtered text, wrapped in a FilterProcessResult object, and possibly + * with associated assets, cacheability metadata and placeholders. + * + * @see \Drupal\filter\Plugin\FilterInterface::process + */ + protected function process($input, $langcode = LanguageInterface::LANGCODE_SITE_DEFAULT) { + return $this->filter->process($input, $langcode); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php new file mode 100644 index 000000000..db6107aa7 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Entity/ProfileTest.php @@ -0,0 +1,32 @@ +createProfile(['description' => 'foo']); + $this->assertEquals('foo', $profile->getDescription()); + $profile->setDescription('bar'); + $this->assertEquals('bar', $profile->getDescription()); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php new file mode 100644 index 000000000..cf3832a7e --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/EntityMatcherDeriverTest.php @@ -0,0 +1,49 @@ +installConfig(['block_content']); + $this->installEntitySchema('block_content'); + + $this->installEntitySchema('node'); + $this->installConfig(['field', 'node']); + + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); + } + + /** + * Tests the deriver. + */ + public function testDeriver() { + $definition = $this->manager->getDefinition('entity:block_content', FALSE); + $this->assertNull($definition); + $definition = $this->manager->getDefinition('entity:node', FALSE); + $this->assertNotNull($definition); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php new file mode 100644 index 000000000..5c167b869 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitAutocompleteTest.php @@ -0,0 +1,259 @@ +createUser(); + + \Drupal::currentUser()->setAccount($this->createUser([], ['view test entity'])); + + \Drupal::service('router.builder')->rebuild(); + $this->installEntitySchema('user'); + $this->installEntitySchema('entity_test'); + $this->installEntitySchema('entity_test_mul'); + + $this->matcherManager = $this->container->get('plugin.manager.linkit.matcher'); + $this->linkitProfile = $this->createProfile(); + } + + /** + * Tests that inaccessible entities isn't included in the results. + */ + public function testAutocompletionAccess() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->matcherManager->createInstance('entity:entity_test'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $entity_1 = EntityTest::create(['name' => 'no_forbid_access']); + $entity_1->save(); + $entity_2 = EntityTest::create(['name' => 'forbid_access']); + $entity_2->save(); + + $suggestions = $this->getAutocompleteResult('forbid'); + $this->assertTrue(count($suggestions) == 1, 'Autocomplete returned the expected amount of suggestions.'); + $this->assertSame($entity_1->label(), $suggestions[0]['label'], 'Autocomplete did not include the inaccessible entity.'); + } + + /** + * Tests that 'front' adds the front page match. + */ + public function testAutocompletionFront() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->matcherManager->createInstance('front_page'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $data = $this->getAutocompleteResult('front'); + $this->assertSame('Front page', $data[0]['label'], 'Autocomplete returned the front page suggestion.'); + } + + /** + * Tests the autocomplete with an email address. + */ + public function testAutocompletionEmail() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->matcherManager->createInstance('email'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $email = 'drupal@example.com'; + $data = $this->getAutocompleteResult($email); + $this->assertSame((string) new FormattableMarkup('E-mail @email', ['@email' => $email]), $data[0]['label'], 'Autocomplete returned email suggestion.'); + $this->assertSame('mailto:' . $email, $data[0]['path'], 'Autocomplete returned email suggestion with an mailto href.'); + } + + /** + * Tests autocompletion in general. + */ + public function testAutocompletion() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->matcherManager->createInstance('entity:entity_test'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $entity_1 = EntityTest::create(['name' => 'Barbar']); + $entity_1->save(); + $entity_2 = EntityTest::create(['name' => 'Foobar']); + $entity_2->save(); + $entity_3 = EntityTest::create(['name' => 'Basbar']); + $entity_3->save(); + + // Search for something that doesn't exists. + $data = $this->getAutocompleteResult('no_suggestions'); + $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.'); + $this->assertSame(Html::escape('no_suggestions'), $data[0]['label'], 'Autocomplete returned the "no result" suggestion.'); + + // Search for something that exists one time. + $data = $this->getAutocompleteResult('bas'); + $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.'); + $this->assertSame(Html::escape($entity_3->label()), $data[0]['label'], 'Autocomplete returned the matching entity'); + + // Search for something that exists three times. + $data = $this->getAutocompleteResult('bar'); + $this->assertTrue(count($data) == 3, 'Autocomplete returned the expected amount of suggestions.'); + $this->assertSame(Html::escape($entity_1->label()), $data[0]['label'], 'Autocomplete returned the first matching entity.'); + $this->assertSame(Html::escape($entity_3->label()), $data[1]['label'], 'Autocomplete returned the second matching entity.'); + $this->assertSame(Html::escape($entity_2->label()), $data[2]['label'], 'Autocomplete returned the third matching entity.'); + + // Search for something with an empty string. + $data = $this->getAutocompleteResult(''); + $this->assertEmpty(count($data), 'Autocomplete did not return any suggestions.'); + } + + /** + * Tests autocompletion with translated entities. + */ + public function testAutocompletionTranslations() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->matcherManager->createInstance('entity:entity_test_mul'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + $this->setupLanguages(); + + $entity = EntityTestMul::create(['name' => 'Barbar']); + + // Copy the array and shift the default language. + $translations = $this->langcodes; + array_shift($translations); + + foreach ($translations as $langcode) { + $entity->addTranslation($langcode, ['name' => 'Barbar ' . $langcode]); + } + + $entity->save(); + + foreach ($this->langcodes as $langcode) { + $this->config('system.site')->set('default_langcode', $langcode)->save(); + $data = $this->getAutocompleteResult('bar'); + $this->assertTrue(count($data) == 1, 'Autocomplete returned the expected amount of suggestions.'); + $this->assertSame($entity->getTranslation($langcode)->label(), $data[0]['label'], 'Autocomplete returned the "no results."'); + } + } + + /** + * Returns the result of an Linkit autocomplete request. + * + * @param string $input + * The label of the entity to query by. + * + * @return array + * An array of suggestions. + */ + protected function getAutocompleteResult($input) { + $request = Request::create('linkit/autocomplete/' . $this->linkitProfile->id()); + $request->query->set('q', $input); + + $controller = AutocompleteController::create($this->container); + $result = Json::decode($controller->autocomplete($request, $this->linkitProfile->id())->getContent()); + return $result['suggestions']; + } + + /** + * Creates a profile based on default settings. + * + * @param array $settings + * (optional) An associative array of settings for the profile, as used in + * entity_create(). Override the defaults by specifying the key and value + * in the array + * + * The following defaults are provided: + * - label: Random string. + * + * @return \Drupal\linkit\ProfileInterface + * The created profile entity. + * + * @todo Do a trait of this? + */ + protected function createProfile(array $settings = []) { + // Populate defaults array. + $settings += [ + 'id' => Unicode::strtolower($this->randomMachineName()), + 'label' => $this->randomMachineName(), + ]; + + $profile = Profile::create($settings); + $profile->save(); + + return $profile; + } + + /** + * Returns the "no results" suggestion. + * + * @return array + * An array with a fixed value of no results. + * + * @todo Should this use some kind of t() function? + */ + protected function noResults() { + return [ + 'title' => 'No results', + ]; + } + + /** + * Adds additional languages. + */ + protected function setupLanguages() { + $this->langcodes = ['sv', 'da', 'fi']; + foreach ($this->langcodes as $langcode) { + ConfigurableLanguage::createFromLangcode($langcode)->save(); + } + array_unshift($this->langcodes, \Drupal::languageManager()->getDefaultLanguage()->getId()); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php new file mode 100644 index 000000000..0a1963b44 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitEditorLinkDialogTest.php @@ -0,0 +1,243 @@ +installEntitySchema('entity_test'); + $this->installSchema('system', ['key_value_expire']); + + // Create a profile. + $this->linkitProfile = $this->createProfile(); + + /** @var \Drupal\linkit\MatcherManager $matcherManager */ + $matcherManager = $this->container->get('plugin.manager.linkit.matcher'); + + // Add the entity_test matcher to the profile. + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $matcherManager->createInstance('entity:entity_test'); + $this->linkitProfile->addMatcher($plugin->getConfiguration()); + $this->linkitProfile->save(); + + // Add a text format. + $format = FilterFormat::create([ + 'format' => 'filtered_html', + 'name' => 'Filtered HTML', + 'weight' => 0, + 'filters' => [], + ]); + $format->save(); + + // Set up editor. + $this->editor = Editor::create([ + 'format' => 'filtered_html', + 'editor' => 'ckeditor', + ]); + $this->editor->setSettings([ + 'plugins' => [ + 'drupallink' => [ + 'linkit_enabled' => TRUE, + 'linkit_profile' => $this->linkitProfile->id(), + ], + ], + ]); + $this->editor->save(); + } + + /** + * Tests adding a link. + */ + public function testAdd() { + $entity_label = $this->randomString(); + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + $entity = EntityTest::create(['name' => $entity_label]); + $entity->save(); + + $form_object = new EditorLinkDialog(); + + $input = [ + 'editor_object' => [], + 'dialogOptions' => [ + 'title' => 'Add Link', + 'dialogClass' => 'editor-link-dialog', + 'autoResize' => 'true', + ], + '_drupal_ajax' => '1', + 'ajax_page_state' => [ + 'theme' => 'bartik', + 'theme_token' => 'some-token', + 'libraries' => '', + ], + ]; + $form_state = (new FormState()) + ->setRequestMethod('POST') + ->setUserInput($input) + ->addBuildInfo('args', [$this->editor]); + + /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */ + $form_builder = $this->container->get('form_builder'); + $form_id = $form_builder->getFormId($form_object, $form_state); + $form = $form_builder->retrieveForm($form_id, $form_state); + $form_builder->prepareForm($form_id, $form, $form_state); + $form_builder->processForm($form_id, $form, $form_state); + + $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the linkit field.'); + $this->assertEmpty($form['attributes']['href']['#default_value'], 'The linkit field is empty.'); + + $form_state->setValue(['attributes', 'href'], 'https://example.com/'); + $form_state->setValue('href_dirty_check', ''); + $form_state->setValue(['attributes', 'data-entity-type'], $this->randomString()); + $form_state->setValue(['attributes', 'data-entity-uuid'], $this->randomString()); + $form_state->setValue(['attributes', 'data-entity-substitution'], $this->randomString()); + $form_builder->submitForm($form_object, $form_state); + $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-type'])); + $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-uuid'])); + $this->assertEmpty($form_state->getValue(['attributes', 'data-entity-substitution'])); + + $entity_url = $entity->toUrl('canonical', ['path_processing' => FALSE])->toString(); + $form_state->setValue(['attributes', 'href'], $entity_url); + $form_state->setValue('href_dirty_check', $entity_url); + $form_state->setValue(['attributes', 'data-entity-type'], $entity->getEntityTypeId()); + $form_state->setValue(['attributes', 'data-entity-uuid'], $entity->uuid()); + $form_state->setValue(['attributes', 'data-entity-substitution'], SubstitutionManagerInterface::DEFAULT_SUBSTITUTION); + $form_builder->submitForm($form_object, $form_state); + + $this->assertEquals($entity->getEntityTypeId(), $form_state->getValue(['attributes', 'data-entity-type']), 'Attribute "data-entity-type" exists and has the correct value.'); + $this->assertEquals($entity->uuid(), $form_state->getValue(['attributes', 'data-entity-uuid']), 'Attribute "data-entity-uuid" exists and has the correct value.'); + $this->assertEquals(SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, $form_state->getValue(['attributes', 'data-entity-substitution']), 'Attribute "data-entity-substitution" exists and has the correct value.'); + } + + /** + * Tests editing a link with data attributes. + */ + public function testEditWithDataAttributes() { + $entity_label = $this->randomString(); + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + $entity = EntityTest::create(['name' => $entity_label]); + $entity->save(); + $entity_url = $entity->toUrl('canonical', ['path_processing' => FALSE])->toString(); + + $form_object = new EditorLinkDialog(); + + $input = [ + 'editor_object' => [ + 'href' => $entity_url, + 'data-entity-type' => $entity->getEntityTypeId(), + 'data-entity-uuid' => $entity->uuid(), + 'data-entity-substitution' => SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, + ], + 'dialogOptions' => [ + 'title' => 'Edit Link', + 'dialogClass' => 'editor-link-dialog', + 'autoResize' => 'true', + ], + '_drupal_ajax' => '1', + 'ajax_page_state' => [ + 'theme' => 'bartik', + 'theme_token' => 'some-token', + 'libraries' => '', + ], + ]; + $form_state = (new FormState()) + ->setRequestMethod('POST') + ->setUserInput($input) + ->addBuildInfo('args', [$this->editor]); + + /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */ + $form_builder = $this->container->get('form_builder'); + $form_id = $form_builder->getFormId($form_object, $form_state); + $form = $form_builder->retrieveForm($form_id, $form_state); + $form_builder->prepareForm($form_id, $form, $form_state); + $form_builder->processForm($form_id, $form, $form_state); + + $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.'); + $this->assertEquals($entity_url, $form['attributes']['href']['#default_value'], 'The href field has the url as default value.'); + $this->assertEquals($entity->getEntityTypeId(), $form_state->getValue(['attributes', 'data-entity-type']), 'Attribute "data-entity-type" exists and has the correct value.'); + $this->assertEquals($entity->uuid(), $form_state->getValue(['attributes', 'data-entity-uuid']), 'Attribute "data-entity-uuid" exists and has the correct value.'); + $this->assertEquals(SubstitutionManagerInterface::DEFAULT_SUBSTITUTION, $form_state->getValue(['attributes', 'data-entity-substitution']), 'Attribute "data-entity-substitution" exists and has the correct value.'); + } + + /** + * Tests editing a link without data attributes. + */ + public function testEditWithoutDataAttributes() { + $form_object = new EditorLinkDialog(); + + $input = [ + 'editor_object' => [ + 'href' => 'http://example.com/', + ], + 'dialogOptions' => [ + 'title' => 'Edit Link', + 'dialogClass' => 'editor-link-dialog', + 'autoResize' => 'true', + ], + '_drupal_ajax' => '1', + 'ajax_page_state' => [ + 'theme' => 'bartik', + 'theme_token' => 'some-token', + 'libraries' => '', + ], + ]; + $form_state = (new FormState()) + ->setRequestMethod('POST') + ->setUserInput($input) + ->addBuildInfo('args', [$this->editor]); + + /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */ + $form_builder = $this->container->get('form_builder'); + $form_id = $form_builder->getFormId($form_object, $form_state); + $form = $form_builder->retrieveForm($form_id, $form_state); + $form_builder->prepareForm($form_id, $form, $form_state); + $form_builder->processForm($form_id, $form, $form_state); + + $this->assertEquals('linkit.autocomplete', $form['attributes']['href']['#autocomplete_route_name'], 'Linkit is enabled on the href field.'); + $this->assertEquals('http://example.com/', $form['attributes']['href']['#default_value'], 'The href field default value is the external URI.'); + $this->assertEmpty($form['attributes']['data-entity-type']['#default_value']); + $this->assertEmpty($form['attributes']['data-entity-uuid']['#default_value']); + $this->assertEmpty($form['attributes']['data-entity-substitution']['#default_value']); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php new file mode 100644 index 000000000..bd2db531a --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitFilterEntityTest.php @@ -0,0 +1,148 @@ +installEntitySchema('entity_test'); + $this->installEntitySchema('entity_test_mul'); + $this->installEntitySchema('file'); + + // Add Swedish, Danish and Finnish. + ConfigurableLanguage::createFromLangcode('sv')->save(); + ConfigurableLanguage::createFromLangcode('da')->save(); + ConfigurableLanguage::createFromLangcode('fi')->save(); + + /** @var \Drupal\Component\Plugin\PluginManagerInterface $manager */ + $manager = $this->container->get('plugin.manager.filter'); + $bag = new FilterPluginCollection($manager, []); + $this->filter = $bag->get('linkit'); + } + + /** + * Tests the linkit filter for entities with different access. + */ + public function testFilterEntityAccess() { + // Create an entity that no one have access to. + $entity_no_access = EntityTest::create(['name' => 'forbid_access']); + $entity_no_access->save(); + + // Create an entity that is accessible. + $entity_with_access = EntityTest::create(['name' => $this->randomMachineName()]); + $entity_with_access->save(); + + // Automatically set the title. + $this->filter->setConfiguration(['settings' => ['title' => 1]]); + + // Make sure the title is not included. + $input = 'Link text'; + $this->assertFalse(strpos($this->process($input)->getProcessedText(), 'title'), 'The link does not contain a title attribute.'); + + $this->assertLinkitFilterWithTitle($entity_with_access); + } + + /** + * Tests the linkit filter for entities with translations. + */ + public function testFilterEntityTranslations() { + // Create an entity and add translations to that. + /** @var \Drupal\entity_test\Entity\EntityTestMul $entity */ + $entity = EntityTestMul::create(['name' => $this->randomMachineName()]); + $entity->addTranslation('sv', ['name' => $this->randomMachineName(), 'langcode' => 'sv']); + $entity->addTranslation('da', ['name' => $this->randomMachineName(), 'langcode' => 'da']); + $entity->addTranslation('fi', ['name' => $this->randomMachineName(), 'langcode' => 'fi']); + $entity->save(); + + /** @var \Drupal\Core\Path\AliasStorageInterface $path_alias_storage */ + $path_alias_storage = $this->container->get('path.alias_storage'); + + $url = $entity->toUrl()->toString(); + + // Add url aliases. + $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'en'); + $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'sv'); + $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'da'); + $path_alias_storage->save($url, '/' . $this->randomMachineName(), 'fi'); + + // Disable the automatic title attribute. + $this->filter->setConfiguration(['settings' => ['title' => 0]]); + /** @var \Drupal\Core\Language\Language $language */ + foreach ($entity->getTranslationLanguages() as $language) { + $this->assertLinkitFilter($entity->getTranslation($language->getId()), $language->getId()); + } + + // Enable the automatic title attribute. + $this->filter->setConfiguration(['settings' => ['title' => 1]]); + /** @var \Drupal\Core\Language\Language $language */ + foreach ($entity->getTranslationLanguages() as $language) { + $this->assertLinkitFilterWithTitle($entity->getTranslation($language->getId()), $language->getId()); + } + } + + /** + * Tests the linkit filter for file entities. + */ + public function testFilterFileEntity() { + $file = File::create([ + 'uid' => 1, + 'filename' => 'druplicon.txt', + 'uri' => 'public://druplicon.txt', + 'filemime' => 'text/plain', + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + + // Disable the automatic title attribute. + $this->filter->setConfiguration(['settings' => ['title' => 0]]); + $this->assertLinkitFilter($file); + + // Automatically set the title. + $this->filter->setConfiguration(['settings' => ['title' => 1]]); + $this->assertLinkitFilterWithTitle($file); + } + + /** + * Tests that the linkit filter do not overwrite provided title attributes. + */ + public function testTitleOverwritten() { + // Create an entity. + $entity = EntityTest::create(['name' => $this->randomMachineName()]); + $entity->save(); + + // Automatically set the title. + $this->filter->setConfiguration(['settings' => ['title' => 1]]); + + // Make sure the title is not overwritten. + $input = 'Link text'; + $this->assertTrue(strpos($this->process($input)->getProcessedText(), 'Do not override'), 'The filer is not overwrite the provided title attribute value.'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php new file mode 100644 index 000000000..737a0bb1f --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/LinkitKernelTestBase.php @@ -0,0 +1,71 @@ +installSchema('system', 'router'); + $this->installSchema('system', 'sequences'); + $this->installEntitySchema('user'); + $this->installConfig(['filter']); + } + + /** + * Creates a user. + * + * @param array $values + * (optional) The values used to create the entity. + * @param array $permissions + * (optional) Array of permission names to assign to user. + * + * @return \Drupal\user\Entity\User + * The created user entity. + */ + protected function createUser(array $values = [], array $permissions = []) { + if ($permissions) { + // Create a new role and apply permissions to it. + $role = Role::create([ + 'id' => strtolower($this->randomMachineName(8)), + 'label' => $this->randomMachineName(8), + ]); + $role->save(); + user_role_grant_permissions($role->id(), $permissions); + $values['roles'][] = $role->id(); + } + + $account = User::create($values + [ + 'name' => $this->randomMachineName(), + 'status' => 1, + ]); + $account->enforceIsNew(); + $account->save(); + return $account; + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php new file mode 100644 index 000000000..7d8050337 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/ContactFormMatcherTest.php @@ -0,0 +1,58 @@ +createUser(); + + \Drupal::currentUser()->setAccount($this->createUser([], ['access site-wide contact form', 'view test entity translations'])); + + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); + + ContactForm::create([ + 'id' => 'lorem', + 'label' => 'Lorem', + ])->save(); + } + + /** + * Tests contact form matcher. + */ + public function testMatcherWidthDefaultConfiguration() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:contact_form', []); + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php new file mode 100644 index 000000000..4999aae1e --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/FileMatcherTest.php @@ -0,0 +1,113 @@ +installEntitySchema('file'); + $this->installSchema('system', ['key_value_expire']); + $this->installSchema('file', ['file_usage']); + + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); + + // Linkit doesn't care about the actual resource, only the entity. + foreach (['gif', 'jpg', 'png'] as $ext) { + $file = File::create([ + 'uid' => 1, + 'filename' => 'image-test.' . $ext, + 'uri' => 'public://image-test.' . $ext, + 'filemime' => 'text/plain', + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + } + + // Create user 1 who has special permissions. + \Drupal::currentUser()->setAccount($this->createUser(['uid' => 1])); + } + + /** + * Tests file matcher. + */ + public function testFileMatcherWithDefaultConfiguration() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:file', []); + $suggestions = $plugin->execute('image-test'); + $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions.'); + } + + /** + * Tests file matcher with extension filer. + */ + public function testFileMatcherWithExtensionFiler() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:file', [ + 'settings' => [ + 'file_extensions' => 'png', + ], + ]); + + $suggestions = $plugin->execute('image-test'); + $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions with single file extension filter.'); + + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:file', [ + 'settings' => [ + 'file_extensions' => 'png jpg', + ], + ]); + + $suggestions = $plugin->execute('image-test'); + $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions with multiple file extension filter.'); + } + + /** + * Tests file matcher with tokens in the matcher metadata. + */ + public function testTermMatcherWidthMetadataTokens() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:file', [ + 'settings' => [ + 'metadata' => '[file:fid] [file:field_with_no_value]', + ], + ]); + + $suggestionCollection = $plugin->execute('Lorem'); + /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */ + $suggestions = $suggestionCollection->getSuggestions(); + + foreach ($suggestions as $suggestion) { + $this->assertNotContains('[file:fid]', $suggestion->getDescription(), 'Raw token "[file:fid]" is not present in the description'); + $this->assertNotContains('[file:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[file:field_with_no_value]" is not present in the description'); + } + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php new file mode 100644 index 000000000..8783a4f97 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/NodeMatcherTest.php @@ -0,0 +1,160 @@ +installEntitySchema('node'); + $this->installConfig(['field', 'node']); + + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); + + // Set the current user to a new user, else the nodes will be created by an + // anonymous user. + \Drupal::currentUser()->setAccount($this->createUser()); + + $type1 = NodeType::create([ + 'type' => 'test1', + 'name' => 'Test1', + ]); + $type1->save(); + + $type2 = NodeType::create([ + 'type' => 'test2', + 'name' => 'Test2', + ]); + $type2->save(); + + // Nodes with type 1. + $node = Node::create([ + 'title' => 'Lorem Ipsum 1', + 'type' => $type1->id(), + ]); + $node->save(); + + $node = Node::create([ + 'title' => 'Lorem Ipsum 2', + 'type' => $type1->id(), + ]); + $node->save(); + + // Node with type 2. + $node = Node::create([ + 'title' => 'Lorem Ipsum 3', + 'type' => $type2->id(), + ]); + $node->save(); + + // Unpublished node. + $node = Node::create([ + 'title' => 'Lorem unpublishd', + 'type' => $type1->id(), + 'status' => FALSE, + ]); + $node->save(); + + // Set the current user to someone that is not the node owner. + \Drupal::currentUser()->setAccount($this->createUser([], ['access content'])); + } + + /** + * Tests node matcher. + */ + public function testNodeMatcherWidthDefaultConfiguration() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:node', []); + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests node matcher with bundle filer. + */ + public function testNodeMatcherWidthBundleFiler() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:node', [ + 'settings' => [ + 'bundles' => [ + 'test1' => 'test1', + ], + ], + ]); + + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests node matcher with include unpublished setting activated. + */ + public function testNodeMatcherWidthIncludeUnpublished() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:node', [ + 'settings' => [ + 'include_unpublished' => TRUE, + ], + ]); + + // Test without permissions to see unpublished nodes. + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + + // Set the current user to a user with 'bypass node access' permission. + \Drupal::currentUser()->setAccount($this->createUser([], ['bypass node access'])); + + // Test with permissions to see unpublished nodes. + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(4, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests node matcher with tokens in the matcher metadata. + */ + public function testNodeMatcherWidthMetadataTokens() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:node', [ + 'settings' => [ + 'metadata' => '[node:nid] [node:field_with_no_value]', + ], + ]); + + $suggestionCollection = $plugin->execute('Lorem'); + /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */ + $suggestions = $suggestionCollection->getSuggestions(); + + foreach ($suggestions as $suggestion) { + $this->assertNotContains('[node:nid]', $suggestion->getDescription(), 'Raw token "[node:nid]" is not present in the description'); + $this->assertNotContains('[node:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[node:field_with_no_value]" is not present in the description'); + } + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php similarity index 51% rename from sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php rename to sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php index d28a484a2..22f2c446e 100644 --- a/sites/all/modules/contrib/fields/linkit/src/Tests/Matchers/TermMatcherTest.php +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/TermMatcherTest.php @@ -1,23 +1,20 @@ getStorage('taxonomy_vocabulary'); - $vocabulary = $vocabularyStorage->create([ - 'name' => $name, - 'description' => $name, - 'vid' => Unicode::strtolower($name), - 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, - ]); - $vocabulary->save(); - return $vocabulary; - } - - /** - * Creates and saves a new term with in vocabulary $vid. - * - * @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary - * The vocabulary object. - * @param array $values - * (optional) An array of values to set, keyed by property name. If the - * entity type has bundles, the bundle key has to be specified. - * - * @return \Drupal\taxonomy\Entity\Term - * The new taxonomy term object. - */ - private function createTerm(Vocabulary $vocabulary, $values = array()) { - $filter_formats = filter_formats(); - $format = array_pop($filter_formats); - - $termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); - $term = $termStorage->create($values + array( - 'name' => $this->randomMachineName(), - 'description' => array( - 'value' => $this->randomMachineName(), - // Use the first available text format. - 'format' => $format->id(), - ), - 'vid' => $vocabulary->id(), - 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, - )); - $term->save(); - return $term; - } - /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - $this->drupalLogin($this->adminUser); + + // Create user 1 who has special permissions. + $this->createUser(); + + \Drupal::currentUser()->setAccount($this->createUser([], ['access content'])); + + $this->installEntitySchema('taxonomy_term'); + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); $testing_vocabulary_1 = $this->createVocabulary('testing_vocabulary_1'); @@ -107,28 +59,101 @@ class TermMatcherTest extends LinkitTestBase { /** * Tests term matcher with default configuration. */ - function testTermMatcherWidthDefaultConfiguration() { + public function testTermMatcherWidthDefaultConfiguration() { /** @var \Drupal\linkit\MatcherInterface $plugin */ $plugin = $this->manager->createInstance('entity:taxonomy_term', []); - $matches = $plugin->getMatches('foo'); - $this->assertEqual(5, count($matches), 'Correct number of matches'); + $suggestions = $plugin->execute('foo'); + $this->assertEquals(5, count($suggestions->getSuggestions()), 'Correct number of suggestions'); } /** * Tests term matcher with bundle filer. */ - function testTermMatcherWidthBundleFiler() { + public function testTermMatcherWidthBundleFiler() { /** @var \Drupal\linkit\MatcherInterface $plugin */ $plugin = $this->manager->createInstance('entity:taxonomy_term', [ 'settings' => [ 'bundles' => [ - 'testing_vocabulary_1' => 'testing_vocabulary_1' + 'testing_vocabulary_1' => 'testing_vocabulary_1', ], ], ]); - $matches = $plugin->getMatches('foo'); - $this->assertEqual(3, count($matches), 'Correct number of matches'); + $suggestions = $plugin->execute('foo'); + $this->assertEquals(3, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests term matcher with tokens in the matcher metadata. + */ + public function testTermMatcherWidthMetadataTokens() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:taxonomy_term', [ + 'settings' => [ + 'metadata' => '[term:tid] [term:field_with_no_value]', + ], + ]); + + $suggestionCollection = $plugin->execute('Lorem'); + /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */ + $suggestions = $suggestionCollection->getSuggestions(); + + foreach ($suggestions as $suggestion) { + $this->assertNotContains('[term:nid]', $suggestion->getDescription(), 'Raw token "[term:nid]" is not present in the description'); + $this->assertNotContains('[term:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[term:field_with_no_value]" is not present in the description'); + } + } + + /** + * Creates and saves a vocabulary. + * + * @param string $name + * The vocabulary name. + * + * @return \Drupal\Core\Entity\EntityInterface|\Drupal\taxonomy\VocabularyInterface + * The new vocabulary object. + */ + private function createVocabulary($name) { + $vocabularyStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_vocabulary'); + $vocabulary = $vocabularyStorage->create([ + 'name' => $name, + 'description' => $name, + 'vid' => Unicode::strtolower($name), + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]); + $vocabulary->save(); + return $vocabulary; + } + + /** + * Creates and saves a new term with in vocabulary $vid. + * + * @param \Drupal\taxonomy\VocabularyInterface $vocabulary + * The vocabulary object. + * @param array $values + * (optional) An array of values to set, keyed by property name. If the + * entity type has bundles, the bundle key has to be specified. + * + * @return \Drupal\taxonomy\Entity\Term + * The new taxonomy term object. + */ + private function createTerm(VocabularyInterface $vocabulary, array $values = []) { + $filter_formats = filter_formats(); + $format = array_pop($filter_formats); + + $termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); + $term = $termStorage->create($values + [ + 'name' => $this->randomMachineName(), + 'description' => [ + 'value' => $this->randomMachineName(), + // Use the first available text format. + 'format' => $format->id(), + ], + 'vid' => $vocabulary->id(), + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]); + $term->save(); + return $term; } } diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php new file mode 100644 index 000000000..a9d8df5b3 --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/Matchers/UserMatcherTest.php @@ -0,0 +1,138 @@ +createUser(); + + \Drupal::currentUser()->setAccount($this->createUser([], ['access user profiles'])); + + $this->manager = $this->container->get('plugin.manager.linkit.matcher'); + + $custom_role = Role::create([ + 'id' => 'custom_role', + 'label' => 'custom_role', + ]); + $custom_role->save(); + + $custom_role_admin = Role::create([ + 'id' => 'custom_role_admin', + 'label' => 'custom_role_admin', + ]); + $custom_role_admin->save(); + + $this->createUser(['name' => 'lorem']); + $this->createUser(['name' => 'foo']); + + $account = $this->createUser(['name' => 'ipsumlorem']); + $account->addRole($custom_role); + $account->save(); + + $account = $this->createUser(['name' => 'lorem_custom_role']); + $account->addRole($custom_role); + $account->save(); + + $account = $this->createUser(['name' => 'lorem_custom_role_admin']); + $account->addRole($custom_role_admin); + $account->save(); + + $account = $this->createUser(['name' => 'blocked_lorem']); + $account->block(); + $account->save(); + } + + /** + * Tests user matcher. + */ + public function testUserMatcherWidthDefaultConfiguration() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:user', []); + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(4, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests user matcher with role filer. + */ + public function testUserMatcherWidthRoleFiler() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:user', [ + 'settings' => [ + 'roles' => [ + 'custom_role' => 'custom_role', + ], + ], + ]); + + $suggestions = $plugin->execute('Lorem'); + $this->assertEquals(2, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests user matcher with include blocked setting activated. + */ + public function testUserMatcherWidthIncludeBlocked() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:user', [ + 'settings' => [ + 'include_blocked' => TRUE, + ], + ]); + + // Test without permissions to see blocked users. + $suggestions = $plugin->execute('blocked'); + $this->assertEquals(0, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + + // Set the current user to a user with 'administer users' permission. + \Drupal::currentUser()->setAccount($this->createUser([], ['administer users'])); + + // Test with permissions to see blocked users. + $suggestions = $plugin->execute('blocked'); + $this->assertEquals(1, count($suggestions->getSuggestions()), 'Correct number of suggestions'); + } + + /** + * Tests user matcher with tokens in the matcher metadata. + */ + public function testTermMatcherWidthMetadataTokens() { + /** @var \Drupal\linkit\MatcherInterface $plugin */ + $plugin = $this->manager->createInstance('entity:user', [ + 'settings' => [ + 'metadata' => '[user:uid] [term:field_with_no_value]', + ], + ]); + + $suggestionCollection = $plugin->execute('Lorem'); + /** @var \Drupal\linkit\Suggestion\EntitySuggestion[] $suggestions */ + $suggestions = $suggestionCollection->getSuggestions(); + + foreach ($suggestions as $suggestion) { + $this->assertNotContains('[user:uid]', $suggestion->getDescription(), 'Raw token "[user:nid]" is not present in the description'); + $this->assertNotContains('[user:field_with_no_value]', $suggestion->getDescription(), 'Raw token "[user:field_with_no_value]" is not present in the description'); + } + } + +} diff --git a/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php new file mode 100644 index 000000000..18f78943d --- /dev/null +++ b/sites/all/modules/contrib/fields/linkit/tests/src/Kernel/SubstitutionPluginTest.php @@ -0,0 +1,181 @@ +substitutionManager = $this->container->get('plugin.manager.linkit.substitution'); + $this->entityTypeManager = $this->container->get('entity_type.manager'); + + $this->installEntitySchema('file'); + $this->installEntitySchema('entity_test'); + $this->installEntitySchema('media'); + $this->installEntitySchema('media_type'); + $this->installEntitySchema('field_storage_config'); + $this->installEntitySchema('field_config'); + $this->installSchema('file', ['file_usage']); + + unset($GLOBALS['config']['system.file']); + \Drupal::configFactory()->getEditable('system.file')->set('default_scheme', 'public')->save(); + } + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container) { + parent::register($container); + + $container->register('stream_wrapper.public', 'Drupal\Core\StreamWrapper\PublicStream') + ->addTag('stream_wrapper', ['scheme' => 'public']); + } + + /** + * {@inheritdoc} + */ + protected function setUpFilesystem() { + $public_file_directory = $this->siteDirectory . '/files'; + + require_once 'core/includes/file.inc'; + + mkdir($this->siteDirectory, 0775); + mkdir($this->siteDirectory . '/files', 0775); + mkdir($this->siteDirectory . '/files/config/' . CONFIG_SYNC_DIRECTORY, 0775, TRUE); + + $this->setSetting('file_public_path', $public_file_directory); + + $GLOBALS['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => $this->siteDirectory . '/files/config/sync', + ]; + } + + /** + * Test the file substitution. + */ + public function testFileSubstitutions() { + $fileSubstitution = $this->substitutionManager->createInstance('file'); + $file = File::create([ + 'uid' => 1, + 'filename' => 'druplicon.txt', + 'uri' => 'public://druplicon.txt', + 'filemime' => 'text/plain', + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + $this->assertEquals($GLOBALS['base_url'] . '/' . $this->siteDirectory . '/files/druplicon.txt', $fileSubstitution->getUrl($file)->getGeneratedUrl()); + + $entity_type = $this->entityTypeManager->getDefinition('file'); + $this->assertTrue(FileSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is applicable the file substitution.'); + + $entity_type = $this->entityTypeManager->getDefinition('entity_test'); + $this->assertFalse(FileSubstitutionPlugin::isApplicable($entity_type), 'The entity type EntityTest is not applicable the file substitution.'); + } + + /** + * Test the canonical substitution. + */ + public function testCanonicalSubstitution() { + $canonicalSubstitution = $this->substitutionManager->createInstance('canonical'); + $entity = EntityTest::create([]); + $entity->save(); + $this->assertEquals('/entity_test/1', $canonicalSubstitution->getUrl($entity)->getGeneratedUrl()); + + $entity_type = $this->entityTypeManager->getDefinition('entity_test'); + $this->assertTrue(CanonicalSubstitutionPlugin::isApplicable($entity_type), 'The entity type EntityTest is applicable the canonical substitution.'); + + $entity_type = $this->entityTypeManager->getDefinition('file'); + $this->assertFalse(CanonicalSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is not applicable the canonical substitution.'); + } + + /** + * Test the media substitution. + */ + public function testMediaSubstitution() { + // Set up media bundle and fields. + $media_type = MediaType::create([ + 'label' => 'test', + 'id' => 'test', + 'description' => 'Test type.', + 'source' => 'file', + ]); + $media_type->save(); + $source_field = $media_type->getSource()->createSourceField($media_type); + $source_field->getFieldStorageDefinition()->save(); + $source_field->save(); + $media_type->set('source_configuration', [ + 'source_field' => $source_field->getName(), + ])->save(); + + $file = File::create([ + 'uid' => 1, + 'filename' => 'druplicon.txt', + 'uri' => 'public://druplicon.txt', + 'filemime' => 'text/plain', + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + + $media = Media::create([ + 'bundle' => 'test', + $source_field->getName() => ['target_id' => $file->id()], + ]); + $media->save(); + + $media_substitution = $this->substitutionManager->createInstance('media'); + $this->assertEquals($GLOBALS['base_url'] . '/' . $this->siteDirectory . '/files/druplicon.txt', $media_substitution->getUrl($media)->getGeneratedUrl()); + + $entity_type = $this->entityTypeManager->getDefinition('media'); + $this->assertTrue(MediaSubstitutionPlugin::isApplicable($entity_type), 'The entity type Media is applicable the media substitution.'); + + $entity_type = $this->entityTypeManager->getDefinition('file'); + $this->assertFalse(MediaSubstitutionPlugin::isApplicable($entity_type), 'The entity type File is not applicable the media substitution.'); + } + +} diff --git a/sites/default/config/sync/editor.editor.wysiwyg.yml b/sites/default/config/sync/editor.editor.wysiwyg.yml index 833cb8d7a..239bc4af9 100644 --- a/sites/default/config/sync/editor.editor.wysiwyg.yml +++ b/sites/default/config/sync/editor.editor.wysiwyg.yml @@ -23,7 +23,6 @@ settings: items: - DrupalLink - DrupalUnlink - - Linkit - name: Listes items: @@ -47,12 +46,13 @@ settings: - PasteText - PasteFromWord plugins: + drupallink: + linkit_enabled: true + linkit_profile: collection stylescombo: styles: '' language: language_list: un - linkit: - linkit_profile: collection image_upload: status: true scheme: public diff --git a/sites/default/config/sync/filter.format.wysiwyg.yml b/sites/default/config/sync/filter.format.wysiwyg.yml index e26b2c49c..861c7eaab 100644 --- a/sites/default/config/sync/filter.format.wysiwyg.yml +++ b/sites/default/config/sync/filter.format.wysiwyg.yml @@ -6,6 +6,7 @@ dependencies: - editor - edlp_admin - edlp_corpus + - linkit - url_to_video_filter name: wysiwyg format: wysiwyg @@ -48,7 +49,7 @@ filters: status: false weight: -43 settings: - allowed_html: '