From bfbba508964731508b9bd6d5835c2edc858db95b Mon Sep 17 00:00:00 2001 From: jenny Date: Fri, 18 Aug 2017 13:52:03 +0100 Subject: [PATCH] Upgraded drupal core with security updates --- composer.lock | 15 +- composer.phar | Bin 1838958 -> 1856985 bytes vendor/composer/installed.json | 374 +++++++++--------- web/core/CHANGELOG.txt | 4 + web/core/INSTALL.txt | 2 +- web/core/MAINTAINERS.txt | 33 +- web/core/core.api.php | 4 +- web/core/core.services.yml | 1 + web/core/includes/entity.inc | 32 +- web/core/lib/Drupal.php | 2 +- .../Drupal/Component/Utility/SafeMarkup.php | 7 + .../lib/Drupal/Core/Block/BlockManager.php | 13 +- .../lib/Drupal/Core/Cache/CacheCollector.php | 12 + .../Database/Query/ConditionInterface.php | 2 +- .../Entity/EntityAccessControlHandler.php | 16 +- .../lib/Drupal/Core/Entity/EntityManager.php | 202 ++++++++++ .../Core/Extension/ModuleHandlerInterface.php | 2 +- .../lib/Drupal/Core/Field/FieldConfigBase.php | 45 ++- .../Drupal/Core/Form/BaseFormIdInterface.php | 2 +- web/core/lib/Drupal/Core/Render/theme.api.php | 2 +- .../src/Functional}/AddFeedTest.php | 2 +- .../src/Functional}/AggregatorAdminTest.php | 14 +- .../src/Functional}/AggregatorCronTest.php | 7 +- .../Functional}/AggregatorRenderingTest.php | 14 +- .../src/Functional}/FeedAdminDisplayTest.php | 2 +- .../src/Functional}/FeedLanguageTest.php | 5 +- .../src/Functional}/UpdateFeedItemTest.php | 2 +- .../src/Functional}/UpdateFeedTest.php | 2 +- .../src/Plugin/Block/BlockContentBlock.php | 2 +- .../src/Tests/Views/BlockContentTestBase.php | 5 + .../Functional}/BlockContentCreationTest.php | 4 +- .../src/Functional}/BlockContentListTest.php | 6 +- .../Functional}/BlockContentListViewsTest.php | 12 +- .../BlockContentTranslationUITest.php | 2 +- .../BlockContentValidationTest.php | 2 +- .../Views/BlockContentFieldFilterTest.php | 6 +- .../Views/BlockContentIntegrationTest.php | 4 +- .../Views/BlockContentRedirectTest.php | 2 +- .../Functional/Views/BlockContentTestBase.php | 107 +++++ .../src/Functional}/Views/FieldTypeTest.php | 2 +- .../Views/RevisionRelationshipsTest.php | 8 +- .../Views/BookRelationshipTest.php | 8 +- .../modules/comment/src/Entity/Comment.php | 23 +- .../tests/src/Unit/Entity/CommentLockTest.php | 4 - .../Functional}/ConfigTranslationFormTest.php | 6 +- .../ConfigTranslationOverviewTest.php | 18 +- .../ConfigTranslationUiThemeTest.php | 8 +- .../ConfigTranslationViewListUiTest.php | 8 +- .../Functional}/Views/ContactFieldsTest.php | 8 +- .../src/Functional}/Views/ContactLinkTest.php | 8 +- .../Plugin/WorkflowType/ContentModeration.php | 2 +- .../tests/src/Kernel/InitialStateTest.php | 6 + .../ModerationStateFieldItemListTest.php | 5 +- .../ContentTestTranslationUITest.php | 2 +- .../ContentTranslationDisableSettingTest.php | 2 +- .../ContentTranslationEnableTest.php | 10 +- .../ContentTranslationLanguageChangeTest.php | 2 +- .../ContentTranslationSettingsTest.php | 8 +- .../ContentTranslationSyncImageTest.php | 7 +- .../Views/ContentTranslationViewsUITest.php | 4 +- .../Functional}/Views/TranslationLinkTest.php | 4 +- .../modules/field_test/field_test.module | 15 +- .../field/tests/src/Kernel/FieldCrudTest.php | 112 ++++-- .../file/migration_templates/d7_file.yml | 1 + .../migration_templates/d7_file_private.yml | 39 ++ .../Migrate/d7/MigratePrivateFileTest.php | 98 +++++ .../process/d6/FilterFormatPermission.php | 6 +- .../Migrate/d6/FilterFormatPermissionTest.php | 32 ++ .../Views/ForumIntegrationTest.php | 8 +- .../src/LinkManager/RelationLinkManager.php | 1 + .../hal/src/LinkManager/TypeLinkManager.php | 1 + .../tests/modules/hal_test/hal_test.module | 4 + .../ImageStyle/ImageStyleHalJsonAnonTest.php | 2 +- .../ImageStyleHalJsonBasicAuthTest.php | 2 +- .../ImageStyleHalJsonCookieTest.php | 2 +- .../tests/src/Functional/ImageEffectsTest.php | 2 +- .../source/d6/LanguageContentSettingsTest.php | 74 ++++ .../source/d7/LanguageContentSettingsTest.php | 72 ++++ .../threecol_33_34_33/threecol_33_34_33.css | 4 +- .../LocaleConfigTranslationImportTest.php | 8 +- .../LocaleConfigTranslationTest.php | 14 +- .../src/Functional}/LocaleExportTest.php | 6 +- .../Functional}/LocaleFileSystemFormTest.php | 6 +- .../LocaleImportFunctionalTest.php | 6 +- .../LocaleJavascriptTranslationTest.php | 11 +- .../Functional}/LocaleLibraryAlterTest.php | 6 +- .../Functional}/LocalePluralFormatTest.php | 6 +- .../LocaleTranslateStringTourTest.php | 2 +- .../Functional}/LocaleTranslationUiTest.php | 28 +- .../src/Functional}/LocaleUpdateBase.php | 6 +- .../src/Functional}/LocaleUpdateCronTest.php | 6 +- .../LocaleUpdateDevelopmentReleaseTest.php | 6 +- .../Functional}/LocaleUpdateInterfaceTest.php | 2 +- .../src/Functional}/LocaleUpdateTest.php | 2 +- .../migrate/process/MigrationLookup.php | 21 +- .../MigrateCckFieldPluginManagerInterface.php | 2 + .../Plugin/migrate/field/UserReference.php | 43 ++ .../migrate_drupal/tests/fixtures/drupal6.php | 42 +- .../migrate_drupal/tests/fixtures/drupal7.php | 306 +++++++++++++- .../src/Batch/MigrateUpgradeImportBatch.php | 3 + .../src/Form/MigrateUpgradeForm.php | 58 ++- .../src/Tests/MigrateUpgradeTestBase.php | 5 + .../src/Functional}/MigrateAccessTest.php | 6 +- .../src/Functional/MigrateUpgradeTestBase.php | 231 +++++++++++ .../Functional}/d6/MigrateUpgrade6Test.php | 8 +- .../core/modules/simpletest/files/html-1.txt | 0 .../core/modules/simpletest/files/image-1.png | Bin .../core/modules/simpletest/files/image-2.jpg | Bin .../modules/simpletest/files/image-test.gif | Bin .../modules/simpletest/files/image-test.jpg | Bin .../modules/simpletest/files/image-test.png | Bin .../d6/files/tmp/some-temp-file.jpg | 0 .../Functional}/d7/MigrateUpgrade7Test.php | 17 +- .../d7/files/sites/default/files/cube.jpeg | 0 .../d7/files/sites/default/files/ds9.txt | 0 .../files/sites/default/private/Babylon5.txt | 1 + .../src/Kernel/Migrate/d6/MigrateNodeTest.php | 4 + .../outside_in/css/outside_in.motion.css | 16 - .../outside_in/css/outside_in.theme.css | 2 +- .../src/Ajax/OpenOffCanvasDialogCommand.php | 11 + .../src/Block/BlockEntityOffCanvasForm.php | 14 +- .../src/Tests/Ajax/OffCanvasDialogTest.php | 1 + .../outside-in-page-wrapper.html.twig | 8 +- .../FunctionalJavascript/OffCanvasTest.php | 6 +- .../OutsideInBlockFormTest.php | 45 ++- .../OutsideInJavascriptTestBase.php | 19 +- .../Ajax/OpenOffCanvasDialogCommandTest.php | 1 + .../EntityReferenceFieldAttributesTest.php | 2 +- .../src/Functional/TaxonomyAttributesTest.php | 2 +- .../rest/config/schema/rest.schema.yml | 1 + web/core/modules/rest/rest.api.php | 4 + .../ConfigurableLinkManagerInterface.php | 2 + .../rest/src/LinkManager/LinkManager.php | 2 + .../rest/src/LinkManager/LinkManagerBase.php | 2 + .../src/LinkManager/LinkManagerInterface.php | 2 + .../src/LinkManager/RelationLinkManager.php | 2 + .../RelationLinkManagerInterface.php | 2 + .../rest/src/LinkManager/TypeLinkManager.php | 2 + .../LinkManager/TypeLinkManagerInterface.php | 2 + .../src/Plugin/Type/ResourcePluginManager.php | 2 + .../modules/rest/src/RestServiceProvider.php | 3 + .../Comment/CommentResourceTestBase.php | 33 ++ ...oParsingTest.php => TestDiscoveryTest.php} | 51 ++- .../Tests/Database/DatabaseWebTestBase.php | 5 + .../system/src/Tests/Database/FakeRecord.php | 5 + .../src/Tests/Image/ToolkitTestBase.php | 7 + .../modules/entity_test/entity_test.module | 19 +- .../src/Entity/EntityTestNoUuid.php | 29 ++ .../src/Entity/EntityTestUpdate.php | 51 --- .../entity_test_update.module | 9 + .../src/Plugin/ImageToolkit/TestToolkit.php | 4 +- .../Functional/Database/DatabaseTestBase.php | 27 ++ .../src/Functional/Database/FakeRecord.php | 12 + .../Database/SelectPagerDefaultTest.php | 13 +- .../Database/SelectTableSortDefaultTest.php | 16 +- .../Database/TemporaryQueryTest.php | 10 +- .../DrupalKernel/ContainerRebuildWebTest.php | 20 +- .../d6_taxonomy_term_translation.yml | 39 ++ .../d6_taxonomy_vocabulary_translation.yml | 27 ++ .../src/Plugin/migrate/source/d6/Term.php | 4 + .../source/d6/VocabularyTranslation.php | 57 +++ .../taxonomy/src/Tests/TaxonomyTestBase.php | 3 + .../taxonomy/src/Tests/TaxonomyTestTrait.php | 5 + .../Tests/TaxonomyTranslationTestTrait.php | 5 + .../src/Functional}/TaxonomyImageTest.php | 8 +- .../Functional}/TaxonomyQueryAlterTest.php | 6 +- .../src/Functional}/TaxonomyTermPagerTest.php | 2 +- .../tests/src/Functional/TaxonomyTestBase.php | 1 - .../src/Functional/TaxonomyTestTrait.php | 60 +++ .../TaxonomyTranslationTestTrait.php | 105 +++++ .../TermTranslationFieldViewTest.php | 1 - .../src/Functional}/TermTranslationUITest.php | 4 +- .../src/Functional}/ThemeTest.php | 2 +- .../Views/ArgumentValidatorTermTest.php | 6 +- .../Views/RelationshipNodeTermDataTest.php | 2 +- .../RelationshipRepresentativeNodeTest.php | 2 +- .../Views/TaxonomyDefaultArgumentTest.php | 2 +- .../Views/TaxonomyFieldAllTermsTest.php | 10 +- .../Views/TaxonomyFieldFilterTest.php | 8 +- .../Views/TaxonomyFieldTidTest.php | 2 +- .../Views/TaxonomyIndexTidFilterTest.php | 4 +- .../Views/TaxonomyIndexTidUiTest.php | 15 +- .../Views/TaxonomyParentUITest.php | 8 +- .../Views/TaxonomyRelationshipTest.php | 6 +- .../Views/TaxonomyTermArgumentDepthTest.php | 6 +- .../Views/TaxonomyTermFilterDepthTest.php | 6 +- .../Views/TaxonomyTermViewTest.php | 6 +- .../Functional}/Views/TaxonomyTestBase.php | 4 +- .../Views/TaxonomyVocabularyArgumentTest.php | 6 +- .../Functional}/Views/TermNameFieldTest.php | 2 +- .../src/Functional}/VocabularyUiTest.php | 3 +- .../Migrate/d6/MigrateTaxonomyTermTest.php | 8 +- .../d6/MigrateTaxonomyTermTranslationTest.php | 124 ++++++ ...grateTaxonomyVocabularyTranslationTest.php | 47 +++ .../migrate/source/d6/TermTranslationTest.php | 206 ++++++++++ .../source/d6/VocabularyTranslationTest.php | 125 ++++++ .../tests/src/Kernel/TermKernelTest.php | 2 +- .../update/src/Tests/UpdateTestBase.php | 7 +- .../FileTransferAuthorizeFormTest.php | 4 +- .../src/Functional}/UpdateContribTest.php | 2 +- .../src/Functional}/UpdateCoreTest.php | 10 +- .../UpdateDeleteFileIfStaleTest.php | 2 +- .../tests/src/Functional/UpdateTestBase.php | 84 ++++ .../src/Functional}/UpdateUploadTest.php | 11 +- web/core/modules/user/src/UserData.php | 6 +- .../src/Functional}/AccessRoleUITest.php | 10 +- .../src/Functional/UserLoginHttpTest.php | 147 +++---- .../Unit/Plugin/Action/AddRoleUserTest.php | 8 +- .../src/Controller/ViewAjaxController.php | 2 +- .../Plugin/views/field/FieldPluginBase.php | 12 +- .../src/Plugin/views/style/DefaultStyle.php | 4 +- .../views/src/Plugin/views/style/Grid.php | 4 +- .../views/src/Plugin/views/style/HtmlList.php | 4 +- .../views/src/Plugin/views/style/Opml.php | 4 +- .../views/src/Plugin/views/style/Rss.php | 4 +- .../Plugin/views/style/StylePluginBase.php | 2 +- .../views/src/Plugin/views/style/Table.php | 4 +- .../modules/views/src/Tests/ViewAjaxTest.php | 12 +- .../Plugin/views/style/StyleTemplateTest.php | 4 +- .../src/Plugin/views/style/StyleTest.php | 4 +- .../src/Functional/TaxonomyGlossaryTest.php | 2 +- .../Controller/ViewAjaxControllerTest.php | 74 +++- .../Unit/Plugin/field/FieldPluginBaseTest.php | 44 +++ .../views_ui/src/Tests/PreviewTest.php | 6 + .../modules/views_ui/src/Tests/UITestBase.php | 5 + .../views_ui/src/Tests/ViewEditTest.php | 6 + .../modules/views_ui/src/ViewEditForm.php | 5 +- web/core/modules/views_ui/src/ViewUI.php | 7 +- .../src/Functional}/AnalyzeTest.php | 19 +- .../src/Functional}/AreaEntityUITest.php | 8 +- .../src/Functional}/ArgumentValidatorTest.php | 2 +- .../src/Functional}/CachedDataUITest.php | 2 +- .../src/Functional}/CustomBooleanTest.php | 5 +- .../src/Functional}/DefaultViewsTest.php | 15 +- .../src/Functional}/DisplayAttachmentTest.php | 7 +- .../src/Functional}/DisplayCRUDTest.php | 2 +- .../src/Functional}/DisplayExtenderUITest.php | 2 +- .../src/Functional}/DisplayFeedTest.php | 9 +- .../src/Functional}/DisplayPathTest.php | 18 +- .../src/Functional}/DisplayTest.php | 59 +-- .../src/Functional}/DuplicateTest.php | 8 +- .../src/Functional}/FieldUITest.php | 16 +- .../src/Functional}/FilterBooleanWebTest.php | 10 +- .../src/Functional}/FilterNumericWebTest.php | 18 +- .../src/Functional}/FilterUITest.php | 11 +- .../src/Functional}/GroupByTest.php | 2 +- .../src/Functional}/HandlerTest.php | 12 +- .../Functional}/NewViewConfigSchemaTest.php | 6 +- .../src/Functional}/OverrideDisplaysTest.php | 10 +- .../src/Functional}/QueryTest.php | 2 +- .../src/Functional}/RearrangeFieldsTest.php | 2 +- .../src/Functional}/RedirectTest.php | 2 +- .../src/Functional}/ReportFieldsTest.php | 2 +- .../src/Functional}/ReportTest.php | 10 +- .../src/Functional}/SettingsTest.php | 12 +- .../src/Functional}/StorageTest.php | 2 +- .../src/Functional}/StyleTableTest.php | 2 +- .../src/Functional}/StyleUITest.php | 2 +- .../src/Functional}/TokenizeAreaUITest.php | 2 +- .../src/Functional}/TranslatedViewTest.php | 9 +- .../tests/src/Functional/UITestBase.php | 90 +++++ .../src/Functional}/UnsavedPreviewTest.php | 8 +- .../src/Functional}/ViewsListTest.php | 9 +- .../src/Functional}/WizardTest.php | 4 +- .../src/Functional}/XssTest.php | 2 +- .../src/FunctionalJavascript/DisplayTest.php | 125 ++++++ .../FunctionalTests/BrowserTestBaseTest.php | 14 + .../Image/ToolkitSetupFormTest.php | 6 +- .../FunctionalTests}/Image/ToolkitTest.php | 2 +- .../FunctionalTests/Image/ToolkitTestBase.php | 159 ++++++++ .../KernelTests/Core/Database/FetchTest.php | 4 +- .../Entity/EntityAccessControlHandlerTest.php | 70 ++++ .../KernelTests/Core/Path/AliasTest.php | 58 +++ .../Drupal/KernelTests/KernelTestBaseTest.php | 8 + .../Tests/Core/Block/BlockManagerTest.php | 89 +++++ .../Tests/Core/Cache/CacheCollectorTest.php | 3 +- .../Tests/TestSuites/TestSuiteBaseTest.php | 8 + 277 files changed, 4256 insertions(+), 1054 deletions(-) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/AddFeedTest.php (98%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/AggregatorAdminTest.php (83%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/AggregatorCronTest.php (93%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/AggregatorRenderingTest.php (91%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/FeedAdminDisplayTest.php (98%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/FeedLanguageTest.php (95%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/UpdateFeedItemTest.php (98%) rename web/core/modules/aggregator/{src/Tests => tests/src/Functional}/UpdateFeedTest.php (97%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/BlockContentCreationTest.php (98%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/BlockContentListTest.php (95%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/BlockContentListViewsTest.php (91%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/BlockContentTranslationUITest.php (99%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/BlockContentValidationTest.php (96%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/Views/BlockContentFieldFilterTest.php (95%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/Views/BlockContentIntegrationTest.php (95%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/Views/BlockContentRedirectTest.php (95%) create mode 100644 web/core/modules/block_content/tests/src/Functional/Views/BlockContentTestBase.php rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/Views/FieldTypeTest.php (93%) rename web/core/modules/block_content/{src/Tests => tests/src/Functional}/Views/RevisionRelationshipsTest.php (92%) rename web/core/modules/book/{src/Tests => tests/src/Functional}/Views/BookRelationshipTest.php (95%) rename web/core/modules/config_translation/{src/Tests => tests/src/Functional}/ConfigTranslationFormTest.php (92%) rename web/core/modules/config_translation/{src/Tests => tests/src/Functional}/ConfigTranslationOverviewTest.php (90%) rename web/core/modules/config_translation/{src/Tests => tests/src/Functional}/ConfigTranslationUiThemeTest.php (86%) rename web/core/modules/config_translation/{src/Tests => tests/src/Functional}/ConfigTranslationViewListUiTest.php (86%) rename web/core/modules/contact/{src/Tests => tests/src/Functional}/Views/ContactFieldsTest.php (88%) rename web/core/modules/contact/{src/Tests => tests/src/Functional}/Views/ContactLinkTest.php (94%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTestTranslationUITest.php (93%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTranslationDisableSettingTest.php (96%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTranslationEnableTest.php (88%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTranslationLanguageChangeTest.php (98%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTranslationSettingsTest.php (98%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/ContentTranslationSyncImageTest.php (98%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/Views/ContentTranslationViewsUITest.php (86%) rename web/core/modules/content_translation/{src/Tests => tests/src/Functional}/Views/TranslationLinkTest.php (92%) create mode 100644 web/core/modules/file/migration_templates/d7_file_private.yml create mode 100644 web/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php create mode 100644 web/core/modules/filter/tests/src/Kernel/Migrate/d6/FilterFormatPermissionTest.php rename web/core/modules/forum/{src/Tests => tests/src/Functional}/Views/ForumIntegrationTest.php (92%) create mode 100644 web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentSettingsTest.php create mode 100644 web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d7/LanguageContentSettingsTest.php rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleConfigTranslationImportTest.php (98%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleConfigTranslationTest.php (97%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleExportTest.php (97%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleFileSystemFormTest.php (91%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleImportFunctionalTest.php (99%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleJavascriptTranslationTest.php (92%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleLibraryAlterTest.php (85%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocalePluralFormatTest.php (99%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleTranslateStringTourTest.php (96%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleTranslationUiTest.php (96%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleUpdateBase.php (98%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleUpdateCronTest.php (97%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleUpdateDevelopmentReleaseTest.php (88%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleUpdateInterfaceTest.php (99%) rename web/core/modules/locale/{src/Tests => tests/src/Functional}/LocaleUpdateTest.php (99%) create mode 100644 web/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/MigrateAccessTest.php (82%) create mode 100644 web/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/MigrateUpgrade6Test.php (90%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/html-1.txt (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/image-1.png (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/image-2.jpg (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/image-test.gif (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/image-test.jpg (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/core/modules/simpletest/files/image-test.png (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d6/files/tmp/some-temp-file.jpg (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d7/MigrateUpgrade7Test.php (86%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d7/files/sites/default/files/cube.jpeg (100%) rename web/core/modules/migrate_drupal_ui/{src/Tests => tests/src/Functional}/d7/files/sites/default/files/ds9.txt (100%) create mode 100644 web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/private/Babylon5.txt rename web/core/modules/simpletest/tests/src/Unit/{TestInfoParsingTest.php => TestDiscoveryTest.php} (97%) create mode 100644 web/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoUuid.php delete mode 100644 web/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestUpdate.php create mode 100644 web/core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php create mode 100644 web/core/modules/system/tests/src/Functional/Database/FakeRecord.php rename web/core/modules/system/{src/Tests => tests/src/Functional}/Database/SelectPagerDefaultTest.php (89%) rename web/core/modules/system/{src/Tests => tests/src/Functional}/Database/SelectTableSortDefaultTest.php (85%) rename web/core/modules/system/{src/Tests => tests/src/Functional}/Database/TemporaryQueryTest.php (90%) rename web/core/modules/system/{src/Tests => tests/src/Functional}/DrupalKernel/ContainerRebuildWebTest.php (63%) create mode 100644 web/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml create mode 100644 web/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml create mode 100644 web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyTranslation.php rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/TaxonomyImageTest.php (94%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/TaxonomyQueryAlterTest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/TaxonomyTermPagerTest.php (97%) create mode 100644 web/core/modules/taxonomy/tests/src/Functional/TaxonomyTestTrait.php create mode 100644 web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/TermTranslationUITest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/ThemeTest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/ArgumentValidatorTermTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/RelationshipNodeTermDataTest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/RelationshipRepresentativeNodeTest.php (94%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyDefaultArgumentTest.php (98%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyFieldAllTermsTest.php (86%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyFieldFilterTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyFieldTidTest.php (94%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyIndexTidFilterTest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyIndexTidUiTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyParentUITest.php (81%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyRelationshipTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyTermArgumentDepthTest.php (89%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyTermFilterDepthTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyTermViewTest.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyTestBase.php (97%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TaxonomyVocabularyArgumentTest.php (92%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/Views/TermNameFieldTest.php (96%) rename web/core/modules/taxonomy/{src/Tests => tests/src/Functional}/VocabularyUiTest.php (97%) create mode 100644 web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php create mode 100644 web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTranslationTest.php create mode 100644 web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermTranslationTest.php create mode 100644 web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/VocabularyTranslationTest.php rename web/core/modules/update/{src/Tests => tests/src/Functional}/FileTransferAuthorizeFormTest.php (92%) rename web/core/modules/update/{src/Tests => tests/src/Functional}/UpdateContribTest.php (99%) rename web/core/modules/update/{src/Tests => tests/src/Functional}/UpdateCoreTest.php (98%) rename web/core/modules/update/{src/Tests => tests/src/Functional}/UpdateDeleteFileIfStaleTest.php (96%) create mode 100644 web/core/modules/update/tests/src/Functional/UpdateTestBase.php rename web/core/modules/update/{src/Tests => tests/src/Functional}/UpdateUploadTest.php (96%) rename web/core/modules/user/{src/Tests/Views => tests/src/Functional}/AccessRoleUITest.php (88%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/AnalyzeTest.php (70%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/AreaEntityUITest.php (93%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/ArgumentValidatorTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/CachedDataUITest.php (98%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/CustomBooleanTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DefaultViewsTest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayAttachmentTest.php (95%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayCRUDTest.php (99%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayExtenderUITest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayFeedTest.php (92%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayPathTest.php (94%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DisplayTest.php (77%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/DuplicateTest.php (84%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/FieldUITest.php (87%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/FilterBooleanWebTest.php (89%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/FilterNumericWebTest.php (86%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/FilterUITest.php (94%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/GroupByTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/HandlerTest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/NewViewConfigSchemaTest.php (90%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/OverrideDisplaysTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/QueryTest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/RearrangeFieldsTest.php (98%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/RedirectTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/ReportFieldsTest.php (97%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/ReportTest.php (72%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/SettingsTest.php (91%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/StorageTest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/StyleTableTest.php (95%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/StyleUITest.php (98%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/TokenizeAreaUITest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/TranslatedViewTest.php (90%) create mode 100644 web/core/modules/views_ui/tests/src/Functional/UITestBase.php rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/UnsavedPreviewTest.php (92%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/ViewsListTest.php (89%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/WizardTest.php (96%) rename web/core/modules/views_ui/{src/Tests => tests/src/Functional}/XssTest.php (96%) create mode 100644 web/core/modules/views_ui/tests/src/FunctionalJavascript/DisplayTest.php rename web/core/{modules/system/src/Tests => tests/Drupal/FunctionalTests}/Image/ToolkitSetupFormTest.php (94%) rename web/core/{modules/system/src/Tests => tests/Drupal/FunctionalTests}/Image/ToolkitTest.php (98%) create mode 100644 web/core/tests/Drupal/FunctionalTests/Image/ToolkitTestBase.php create mode 100644 web/core/tests/Drupal/Tests/Core/Block/BlockManagerTest.php diff --git a/composer.lock b/composer.lock index 9ca54eb81..ec4a0f43c 100644 --- a/composer.lock +++ b/composer.lock @@ -2016,16 +2016,16 @@ }, { "name": "drupal/core", - "version": "8.3.4", + "version": "8.3.7", "source": { "type": "git", "url": "https://github.com/drupal/core.git", - "reference": "f34eee7255142ab5416107972ef13d011f11e163" + "reference": "32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/f34eee7255142ab5416107972ef13d011f11e163", - "reference": "f34eee7255142ab5416107972ef13d011f11e163", + "url": "https://api.github.com/repos/drupal/core/zipball/32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff", + "reference": "32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff", "shasum": "" }, "require": { @@ -2197,7 +2197,7 @@ "GPL-2.0+" ], "description": "Drupal is an open source content management platform powering millions of websites and applications.", - "time": "2017-06-21T18:13:27+00:00" + "time": "2017-08-16T17:10:35+00:00" }, { "name": "drupal/crop", @@ -5309,8 +5309,7 @@ "homepage": "https://www.drupal.org/project/security_review", "support": { "source": "http://cgit.drupalcode.org/security_review" - }, - "time": "2016-10-20 15:43:48" + } }, { "name": "drupal/simple_sitemap", @@ -6512,7 +6511,7 @@ "standards", "syntax" ], - "time": "2015-09-20 22:14:29" + "time": "2015-09-20T22:14:29+00:00" }, { "name": "guzzlehttp/guzzle", diff --git a/composer.phar b/composer.phar index e44722e933f8ebf9b4501f04b42c9accc594ab00..fc46f0e003d0490f016716111879b4952a9624ae 100755 GIT binary patch delta 25954 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 C8fIMp diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 048ac50bb..6e357d5ee 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -7162,193 +7162,6 @@ "source": "http://cgit.drupalcode.org/layouter" } }, - { - "name": "drupal/core", - "version": "8.3.4", - "version_normalized": "8.3.4.0", - "source": { - "type": "git", - "url": "https://github.com/drupal/core.git", - "reference": "f34eee7255142ab5416107972ef13d011f11e163" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/f34eee7255142ab5416107972ef13d011f11e163", - "reference": "f34eee7255142ab5416107972ef13d011f11e163", - "shasum": "" - }, - "require": { - "asm89/stack-cors": "~1.0", - "composer/semver": "~1.0", - "doctrine/annotations": "1.2.*", - "doctrine/common": "^2.5", - "easyrdf/easyrdf": "0.9.*", - "egulias/email-validator": "1.2.*", - "guzzlehttp/guzzle": "^6.2.1", - "masterminds/html5": "~2.1", - "paragonie/random_compat": "^1.0|^2.0", - "php": ">=5.5.9", - "stack/builder": "1.0.*", - "symfony-cmf/routing": "~1.4", - "symfony/class-loader": "~2.8", - "symfony/console": "~2.8", - "symfony/dependency-injection": "~2.8", - "symfony/event-dispatcher": "~2.8", - "symfony/http-foundation": "~2.8", - "symfony/http-kernel": "~2.8", - "symfony/polyfill-iconv": "~1.0", - "symfony/process": "~2.8", - "symfony/psr-http-message-bridge": "^1.0", - "symfony/routing": "~2.8", - "symfony/serializer": "~2.8", - "symfony/translation": "~2.8", - "symfony/validator": "~2.8", - "symfony/yaml": "~2.8", - "twig/twig": "^1.23.1", - "zendframework/zend-diactoros": "~1.1", - "zendframework/zend-feed": "~2.4" - }, - "conflict": { - "drush/drush": "<8.1.10" - }, - "replace": { - "drupal/action": "self.version", - "drupal/aggregator": "self.version", - "drupal/automated_cron": "self.version", - "drupal/ban": "self.version", - "drupal/bartik": "self.version", - "drupal/basic_auth": "self.version", - "drupal/big_pipe": "self.version", - "drupal/block": "self.version", - "drupal/block_content": "self.version", - "drupal/block_place": "self.version", - "drupal/book": "self.version", - "drupal/breakpoint": "self.version", - "drupal/ckeditor": "self.version", - "drupal/classy": "self.version", - "drupal/color": "self.version", - "drupal/comment": "self.version", - "drupal/config": "self.version", - "drupal/config_translation": "self.version", - "drupal/contact": "self.version", - "drupal/content_moderation": "self.version", - "drupal/content_translation": "self.version", - "drupal/contextual": "self.version", - "drupal/core-annotation": "self.version", - "drupal/core-assertion": "self.version", - "drupal/core-bridge": "self.version", - "drupal/core-datetime": "self.version", - "drupal/core-dependency-injection": "self.version", - "drupal/core-diff": "self.version", - "drupal/core-discovery": "self.version", - "drupal/core-event-dispatcher": "self.version", - "drupal/core-file-cache": "self.version", - "drupal/core-filesystem": "self.version", - "drupal/core-gettext": "self.version", - "drupal/core-graph": "self.version", - "drupal/core-http-foundation": "self.version", - "drupal/core-php-storage": "self.version", - "drupal/core-plugin": "self.version", - "drupal/core-proxy-builder": "self.version", - "drupal/core-render": "self.version", - "drupal/core-serialization": "self.version", - "drupal/core-transliteration": "self.version", - "drupal/core-utility": "self.version", - "drupal/core-uuid": "self.version", - "drupal/datetime": "self.version", - "drupal/datetime_range": "self.version", - "drupal/dblog": "self.version", - "drupal/dynamic_page_cache": "self.version", - "drupal/editor": "self.version", - "drupal/entity_reference": "self.version", - "drupal/field": "self.version", - "drupal/field_layout": "self.version", - "drupal/field_ui": "self.version", - "drupal/file": "self.version", - "drupal/filter": "self.version", - "drupal/forum": "self.version", - "drupal/hal": "self.version", - "drupal/help": "self.version", - "drupal/history": "self.version", - "drupal/image": "self.version", - "drupal/inline_form_errors": "self.version", - "drupal/language": "self.version", - "drupal/layout_discovery": "self.version", - "drupal/link": "self.version", - "drupal/locale": "self.version", - "drupal/menu_link_content": "self.version", - "drupal/menu_ui": "self.version", - "drupal/migrate": "self.version", - "drupal/migrate_drupal": "self.version", - "drupal/migrate_drupal_ui": "self.version", - "drupal/minimal": "self.version", - "drupal/node": "self.version", - "drupal/options": "self.version", - "drupal/outside_in": "self.version", - "drupal/page_cache": "self.version", - "drupal/path": "self.version", - "drupal/quickedit": "self.version", - "drupal/rdf": "self.version", - "drupal/responsive_image": "self.version", - "drupal/rest": "self.version", - "drupal/search": "self.version", - "drupal/serialization": "self.version", - "drupal/seven": "self.version", - "drupal/shortcut": "self.version", - "drupal/simpletest": "self.version", - "drupal/standard": "self.version", - "drupal/stark": "self.version", - "drupal/statistics": "self.version", - "drupal/syslog": "self.version", - "drupal/system": "self.version", - "drupal/taxonomy": "self.version", - "drupal/telephone": "self.version", - "drupal/text": "self.version", - "drupal/toolbar": "self.version", - "drupal/tour": "self.version", - "drupal/tracker": "self.version", - "drupal/update": "self.version", - "drupal/user": "self.version", - "drupal/views": "self.version", - "drupal/views_ui": "self.version", - "drupal/workflows": "self.version" - }, - "require-dev": { - "behat/mink": "1.7.x-dev", - "behat/mink-goutte-driver": "~1.2", - "drupal/coder": "8.2.12", - "jcalderonzumba/gastonjs": "~1.0.2", - "jcalderonzumba/mink-phantomjs-driver": "~0.3.1", - "mikey179/vfsstream": "~1.2", - "phpunit/phpunit": ">=4.8.28 <5", - "symfony/browser-kit": ">=2.8.13 <3.0", - "symfony/css-selector": "~2.8" - }, - "time": "2017-06-21T18:13:27+00:00", - "type": "drupal-core", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Drupal\\Core\\": "lib/Drupal/Core", - "Drupal\\Component\\": "lib/Drupal/Component", - "Drupal\\Driver\\": "../drivers/lib/Drupal/Driver" - }, - "classmap": [ - "lib/Drupal.php", - "lib/Drupal/Component/Utility/Timer.php", - "lib/Drupal/Component/Utility/Unicode.php", - "lib/Drupal/Core/Database/Database.php", - "lib/Drupal/Core/DrupalKernel.php", - "lib/Drupal/Core/DrupalKernelInterface.php", - "lib/Drupal/Core/Site/Settings.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0+" - ], - "description": "Drupal is an open source content management platform powering millions of websites and applications." - }, { "name": "drupal-composer/drupal-scaffold", "version": "2.3.0", @@ -11526,5 +11339,192 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it" + }, + { + "name": "drupal/core", + "version": "8.3.7", + "version_normalized": "8.3.7.0", + "source": { + "type": "git", + "url": "https://github.com/drupal/core.git", + "reference": "32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/drupal/core/zipball/32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff", + "reference": "32f66ed9cc593f8e9ab0eaaaeff4cadbd859d5ff", + "shasum": "" + }, + "require": { + "asm89/stack-cors": "~1.0", + "composer/semver": "~1.0", + "doctrine/annotations": "1.2.*", + "doctrine/common": "^2.5", + "easyrdf/easyrdf": "0.9.*", + "egulias/email-validator": "1.2.*", + "guzzlehttp/guzzle": "^6.2.1", + "masterminds/html5": "~2.1", + "paragonie/random_compat": "^1.0|^2.0", + "php": ">=5.5.9", + "stack/builder": "1.0.*", + "symfony-cmf/routing": "~1.4", + "symfony/class-loader": "~2.8", + "symfony/console": "~2.8", + "symfony/dependency-injection": "~2.8", + "symfony/event-dispatcher": "~2.8", + "symfony/http-foundation": "~2.8", + "symfony/http-kernel": "~2.8", + "symfony/polyfill-iconv": "~1.0", + "symfony/process": "~2.8", + "symfony/psr-http-message-bridge": "^1.0", + "symfony/routing": "~2.8", + "symfony/serializer": "~2.8", + "symfony/translation": "~2.8", + "symfony/validator": "~2.8", + "symfony/yaml": "~2.8", + "twig/twig": "^1.23.1", + "zendframework/zend-diactoros": "~1.1", + "zendframework/zend-feed": "~2.4" + }, + "conflict": { + "drush/drush": "<8.1.10" + }, + "replace": { + "drupal/action": "self.version", + "drupal/aggregator": "self.version", + "drupal/automated_cron": "self.version", + "drupal/ban": "self.version", + "drupal/bartik": "self.version", + "drupal/basic_auth": "self.version", + "drupal/big_pipe": "self.version", + "drupal/block": "self.version", + "drupal/block_content": "self.version", + "drupal/block_place": "self.version", + "drupal/book": "self.version", + "drupal/breakpoint": "self.version", + "drupal/ckeditor": "self.version", + "drupal/classy": "self.version", + "drupal/color": "self.version", + "drupal/comment": "self.version", + "drupal/config": "self.version", + "drupal/config_translation": "self.version", + "drupal/contact": "self.version", + "drupal/content_moderation": "self.version", + "drupal/content_translation": "self.version", + "drupal/contextual": "self.version", + "drupal/core-annotation": "self.version", + "drupal/core-assertion": "self.version", + "drupal/core-bridge": "self.version", + "drupal/core-datetime": "self.version", + "drupal/core-dependency-injection": "self.version", + "drupal/core-diff": "self.version", + "drupal/core-discovery": "self.version", + "drupal/core-event-dispatcher": "self.version", + "drupal/core-file-cache": "self.version", + "drupal/core-filesystem": "self.version", + "drupal/core-gettext": "self.version", + "drupal/core-graph": "self.version", + "drupal/core-http-foundation": "self.version", + "drupal/core-php-storage": "self.version", + "drupal/core-plugin": "self.version", + "drupal/core-proxy-builder": "self.version", + "drupal/core-render": "self.version", + "drupal/core-serialization": "self.version", + "drupal/core-transliteration": "self.version", + "drupal/core-utility": "self.version", + "drupal/core-uuid": "self.version", + "drupal/datetime": "self.version", + "drupal/datetime_range": "self.version", + "drupal/dblog": "self.version", + "drupal/dynamic_page_cache": "self.version", + "drupal/editor": "self.version", + "drupal/entity_reference": "self.version", + "drupal/field": "self.version", + "drupal/field_layout": "self.version", + "drupal/field_ui": "self.version", + "drupal/file": "self.version", + "drupal/filter": "self.version", + "drupal/forum": "self.version", + "drupal/hal": "self.version", + "drupal/help": "self.version", + "drupal/history": "self.version", + "drupal/image": "self.version", + "drupal/inline_form_errors": "self.version", + "drupal/language": "self.version", + "drupal/layout_discovery": "self.version", + "drupal/link": "self.version", + "drupal/locale": "self.version", + "drupal/menu_link_content": "self.version", + "drupal/menu_ui": "self.version", + "drupal/migrate": "self.version", + "drupal/migrate_drupal": "self.version", + "drupal/migrate_drupal_ui": "self.version", + "drupal/minimal": "self.version", + "drupal/node": "self.version", + "drupal/options": "self.version", + "drupal/outside_in": "self.version", + "drupal/page_cache": "self.version", + "drupal/path": "self.version", + "drupal/quickedit": "self.version", + "drupal/rdf": "self.version", + "drupal/responsive_image": "self.version", + "drupal/rest": "self.version", + "drupal/search": "self.version", + "drupal/serialization": "self.version", + "drupal/seven": "self.version", + "drupal/shortcut": "self.version", + "drupal/simpletest": "self.version", + "drupal/standard": "self.version", + "drupal/stark": "self.version", + "drupal/statistics": "self.version", + "drupal/syslog": "self.version", + "drupal/system": "self.version", + "drupal/taxonomy": "self.version", + "drupal/telephone": "self.version", + "drupal/text": "self.version", + "drupal/toolbar": "self.version", + "drupal/tour": "self.version", + "drupal/tracker": "self.version", + "drupal/update": "self.version", + "drupal/user": "self.version", + "drupal/views": "self.version", + "drupal/views_ui": "self.version", + "drupal/workflows": "self.version" + }, + "require-dev": { + "behat/mink": "1.7.x-dev", + "behat/mink-goutte-driver": "~1.2", + "drupal/coder": "8.2.12", + "jcalderonzumba/gastonjs": "~1.0.2", + "jcalderonzumba/mink-phantomjs-driver": "~0.3.1", + "mikey179/vfsstream": "~1.2", + "phpunit/phpunit": ">=4.8.28 <5", + "symfony/browser-kit": ">=2.8.13 <3.0", + "symfony/css-selector": "~2.8" + }, + "time": "2017-08-16T17:10:35+00:00", + "type": "drupal-core", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Drupal\\Core\\": "lib/Drupal/Core", + "Drupal\\Component\\": "lib/Drupal/Component", + "Drupal\\Driver\\": "../drivers/lib/Drupal/Driver" + }, + "classmap": [ + "lib/Drupal.php", + "lib/Drupal/Component/Utility/Timer.php", + "lib/Drupal/Component/Utility/Unicode.php", + "lib/Drupal/Core/Database/Database.php", + "lib/Drupal/Core/DrupalKernel.php", + "lib/Drupal/Core/DrupalKernelInterface.php", + "lib/Drupal/Core/Site/Settings.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "description": "Drupal is an open source content management platform powering millions of websites and applications." } ] diff --git a/web/core/CHANGELOG.txt b/web/core/CHANGELOG.txt index eab901996..1cfd863cf 100644 --- a/web/core/CHANGELOG.txt +++ b/web/core/CHANGELOG.txt @@ -1,3 +1,7 @@ +Drupal 8.3.7, 2017-08-16 +------------------------ +- Fixed security issues. See SA-CORE-2017-004. + Drupal 8.3.4, 2017-06-21 ------------------------ - Fixed security issues. See SA-CORE-2017-003. diff --git a/web/core/INSTALL.txt b/web/core/INSTALL.txt index 74ceed95d..5d5525b1a 100644 --- a/web/core/INSTALL.txt +++ b/web/core/INSTALL.txt @@ -88,7 +88,7 @@ INSTALLATION directory within your web server's document root or your public HTML directory, continue with this command: - mv drupal-x.y.z/* drupal-x.y.z/.htaccess drupal-x.y.z/.csslintrc drupal-x.y.z/.editorconfig drupal-x.y.z/.eslintignore drupal-x.y.z/.eslintrc drupal-x.y.z/.gitattributes /path/to/your/installation + mv drupal-x.y.z/* drupal-x.y.z/.htaccess drupal-x.y.z/.csslintrc drupal-x.y.z/.editorconfig drupal-x.y.z/.eslintignore drupal-x.y.z/.eslintrc.json drupal-x.y.z/.gitattributes /path/to/your/installation You can also download the latest version of Drupal using Git on the command line and set up a repository by following the instructions at diff --git a/web/core/MAINTAINERS.txt b/web/core/MAINTAINERS.txt index 9e9431638..4e5f4e619 100644 --- a/web/core/MAINTAINERS.txt +++ b/web/core/MAINTAINERS.txt @@ -36,6 +36,8 @@ Provisional membership: (Framework Manager - Frontend) - Gábor Hojtsy 'Gábor Hojtsy' https://www.drupal.org/u/gábor-hojtsy (Product Manager) +- Lee Rowlands 'larowlan' https://www.drupal.org/u/larowlan + (Framework Manager) - Roy Scholten 'yoroy' https://www.drupal.org/u/yoroy (Product Manager) @@ -168,10 +170,8 @@ CSS - John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin Database API -- Larry Garfield 'Crell' https://www.drupal.org/u/crell MySQL DB driver - - Larry Garfield 'Crell' https://www.drupal.org/u/crell - David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss PostgreSQL DB driver @@ -272,6 +272,17 @@ Mail Markup - ? +Menu +- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner +- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin + +Menu Link Content +- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner +- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin + +Menu UI +- ? + Migrate - Adam Globus-Hoenich 'phenaproxima' https://www.drupal.org/u/phenaproxima - Ben Dougherty 'benjy' https://www.drupal.org/u/benjy @@ -285,17 +296,6 @@ Migrate (Drupal) - Mike Ryan 'mikeryan' https://www.drupal.org/u/mikeryan - Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone -Menu -- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner -- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin - -Menu Link Content -- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner -- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin - -Menu UI -- ? - Node - Tim Millwood 'timmillwood' https://www.drupal.org/u/timmillwood @@ -337,10 +337,9 @@ Render API - Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman Request Processing -- Larry Garfield 'Crell' https://www.drupal.org/u/crell +- ? REST -- Larry Garfield 'Crell' https://www.drupal.org/u/crell - Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers Responsive Image @@ -349,7 +348,6 @@ Responsive Image - Jelle Sebreghts 'Jelle_S' https://www.drupal.org/u/jelle_s Routing -- Larry Garfield 'Crell' https://www.drupal.org/u/crell - Tim Plunkett 'tim.plunkett' https://www.drupal.org/u/tim.plunkett Search @@ -432,6 +430,9 @@ Views - Jess Myrbo 'xjm' https://www.drupal.org/u/xjm - Len Swaneveld 'Lendude' https://www.drupal.org/u/lendude +Workflows +- Sam Becker 'Sam152' https://www.drupal.org/u/sam152 + Topic maintainers ----------------- diff --git a/web/core/core.api.php b/web/core/core.api.php index 7c4ebf40b..161ddb914 100644 --- a/web/core/core.api.php +++ b/web/core/core.api.php @@ -2530,8 +2530,8 @@ function hook_validation_constraint_alter(array &$definitions) { * * @section sec_dispatch Dispatching events * To dispatch an event, call the - * \Symfony\Component\EventDispatcher\EventDispatchInterface::dispatch() method - * on the 'event_dispatcher' service (see the + * \Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch() + * method on the 'event_dispatcher' service (see the * @link container Services topic @endlink for more information about how to * interact with services). The first argument is the unique event name, which * you should normally define as a constant in a separate static class (see diff --git a/web/core/core.services.yml b/web/core/core.services.yml index 2527845c7..bd2f2c1e7 100644 --- a/web/core/core.services.yml +++ b/web/core/core.services.yml @@ -316,6 +316,7 @@ services: - { name: backend_overridable } # @deprecated in Drupal 8.0.x and will be removed before 9.0.0. Use # config.storage.sync instead. + # @see https://www.drupal.org/node/2574957 config.storage.staging: class: Drupal\Core\Config\FileStorage factory: Drupal\Core\Config\FileStorageFactory::getSync diff --git a/web/core/includes/entity.inc b/web/core/includes/entity.inc index 45eaa3d8e..c69c588f0 100644 --- a/web/core/includes/entity.inc +++ b/web/core/includes/entity.inc @@ -531,24 +531,24 @@ function entity_get_display($entity_type, $bundle, $view_mode) { * * @deprecated as of Drupal 8.0.x, will be removed before Drupal 9.0.0. * If the entity form display is available in configuration use: - * @code - * \Drupal::entityTypeManager() - * ->getStorage('entity_form_display') - * ->load($entity_type . '.' . $bundle . '.' . $form_mode); - * @endcode + * @code + * \Drupal::entityTypeManager() + * ->getStorage('entity_form_display') + * ->load($entity_type . '.' . $bundle . '.' . $form_mode); + * @endcode * When the entity form display is not available in configuration, you can * create a new EntityFormDisplay object using: - * @code - * $values = array( - * 'targetEntityType' => $entity_type, - * 'bundle' => $bundle, - * 'mode' => $form_mode, - * 'status' => TRUE, - * ); - * \Drupal::entityTypeManager() - * ->getStorage('entity_form_display') - * ->create($values); - * @endcode + * @code + * $values = array( + * 'targetEntityType' => $entity_type, + * 'bundle' => $bundle, + * 'mode' => $form_mode, + * 'status' => TRUE, + * ); + * \Drupal::entityTypeManager() + * ->getStorage('entity_form_display') + * ->create($values); + * @endcode * * @see \Drupal\Core\Entity\EntityStorageInterface::create() * @see \Drupal\Core\Entity\EntityStorageInterface::load() diff --git a/web/core/lib/Drupal.php b/web/core/lib/Drupal.php index 9371f1e5f..db54df3d5 100644 --- a/web/core/lib/Drupal.php +++ b/web/core/lib/Drupal.php @@ -81,7 +81,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '8.3.4'; + const VERSION = '8.3.7'; /** * Core API compatibility. diff --git a/web/core/lib/Drupal/Component/Utility/SafeMarkup.php b/web/core/lib/Drupal/Component/Utility/SafeMarkup.php index be35d96b4..b2d00a309 100644 --- a/web/core/lib/Drupal/Component/Utility/SafeMarkup.php +++ b/web/core/lib/Drupal/Component/Utility/SafeMarkup.php @@ -13,6 +13,8 @@ use Drupal\Component\Render\MarkupInterface; * @link sanitization sanitization functions @endlink or the @link theme_render theme and render systems @endlink * so that the output can can be themed, escaped, and altered properly. * + * @see https://www.drupal.org/node/2549395 + * * @see TwigExtension::escapeFilter() * @see twig_render_template() * @see sanitization @@ -34,6 +36,8 @@ class SafeMarkup { * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0. * Instead, you should just check if a variable is an instance of * \Drupal\Component\Render\MarkupInterface. + * + * @see https://www.drupal.org/node/2549395 */ public static function isSafe($string, $strategy = 'html') { return $string instanceof MarkupInterface; @@ -58,6 +62,7 @@ class SafeMarkup { * possible, \Drupal\Component\Utility\Html::escape() can be used in places * where explicit escaping is needed. * + * @see https://www.drupal.org/node/2549395 * @see drupal_validate_utf8() */ public static function checkPlain($text) { @@ -84,6 +89,8 @@ class SafeMarkup { * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. * Use \Drupal\Component\Render\FormattableMarkup. + * + * @see https://www.drupal.org/node/2549395 */ public static function format($string, array $args) { return new FormattableMarkup($string, $args); diff --git a/web/core/lib/Drupal/Core/Block/BlockManager.php b/web/core/lib/Drupal/Core/Block/BlockManager.php index a837340a3..30b52b612 100644 --- a/web/core/lib/Drupal/Core/Block/BlockManager.php +++ b/web/core/lib/Drupal/Core/Block/BlockManager.php @@ -20,7 +20,6 @@ class BlockManager extends DefaultPluginManager implements BlockManagerInterface use CategorizingPluginManagerTrait { getSortedDefinitions as traitGetSortedDefinitions; - getGroupedDefinitions as traitGetGroupedDefinitions; } use ContextAwarePluginManagerTrait; @@ -54,23 +53,13 @@ class BlockManager extends DefaultPluginManager implements BlockManagerInterface * {@inheritdoc} */ public function getSortedDefinitions(array $definitions = NULL) { - // Sort the plugins first by category, then by label. + // Sort the plugins first by category, then by admin label. $definitions = $this->traitGetSortedDefinitions($definitions, 'admin_label'); // Do not display the 'broken' plugin in the UI. unset($definitions['broken']); return $definitions; } - /** - * {@inheritdoc} - */ - public function getGroupedDefinitions(array $definitions = NULL) { - $definitions = $this->traitGetGroupedDefinitions($definitions, 'admin_label'); - // Do not display the 'broken' plugin in the UI. - unset($definitions[$this->t('Block')]['broken']); - return $definitions; - } - /** * {@inheritdoc} */ diff --git a/web/core/lib/Drupal/Core/Cache/CacheCollector.php b/web/core/lib/Drupal/Core/Cache/CacheCollector.php index acbbf006a..b0c9f45b1 100644 --- a/web/core/lib/Drupal/Core/Cache/CacheCollector.php +++ b/web/core/lib/Drupal/Core/Cache/CacheCollector.php @@ -246,6 +246,18 @@ abstract class CacheCollector implements CacheCollectorInterface, DestructableIn } $data = array_merge($cache->data, $data); } + elseif ($this->cacheCreated) { + // Getting here indicates that there was a cache entry at the + // beginning of the request, but now it's gone (some other process + // must have cleared it). We back out to prevent corrupting the cache + // with incomplete data, since we won't be able to properly merge + // the existing cache data from earlier with the new data. + // A future request will properly hydrate the cache from scratch. + if ($lock) { + $this->lock->release($lock_name); + } + return; + } // Remove keys marked for deletion. foreach ($this->keysToRemove as $delete_key) { unset($data[$delete_key]); diff --git a/web/core/lib/Drupal/Core/Database/Query/ConditionInterface.php b/web/core/lib/Drupal/Core/Database/Query/ConditionInterface.php index aa5090a89..221f0e2b4 100644 --- a/web/core/lib/Drupal/Core/Database/Query/ConditionInterface.php +++ b/web/core/lib/Drupal/Core/Database/Query/ConditionInterface.php @@ -197,7 +197,7 @@ interface ConditionInterface { * * @param $conjunction * - AND (default): this is the equivalent of andConditionGroup(). - * - OR: this is the equivalent of andConditionGroup(). + * - OR: this is the equivalent of orConditionGroup(). * * @return \Drupal\Core\Database\Query\ConditionInterface * An object holding a group of conditions. diff --git a/web/core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php b/web/core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php index 3b16d1cdd..ac364115e 100644 --- a/web/core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php +++ b/web/core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php @@ -66,7 +66,19 @@ class EntityAccessControlHandler extends EntityHandlerBase implements EntityAcce $operation = 'view'; } - if (($return = $this->getCache($entity->uuid(), $operation, $langcode, $account)) !== NULL) { + // If an entity does not have a UUID, either from not being set or from not + // having them, use the 'entity type:ID' pattern as the cache $cid. + $cid = $entity->uuid() ?: $entity->getEntityTypeId() . ':' . $entity->id(); + + // If the entity is revisionable, then append the revision ID to allow + // individual revisions to have specific access control and be cached + // separately. + if ($entity instanceof RevisionableInterface) { + /** @var $entity \Drupal\Core\Entity\RevisionableInterface */ + $cid .= ':' . $entity->getRevisionId(); + } + + if (($return = $this->getCache($cid, $operation, $langcode, $account)) !== NULL) { // Cache hit, no work necessary. return $return_as_object ? $return : $return->isAllowed(); } @@ -92,7 +104,7 @@ class EntityAccessControlHandler extends EntityHandlerBase implements EntityAcce if (!$return->isForbidden()) { $return = $return->orIf($this->checkAccess($entity, $operation, $account)); } - $result = $this->setCache($return, $entity->uuid(), $operation, $langcode, $account); + $result = $this->setCache($return, $cid, $operation, $langcode, $account); return $return_as_object ? $result : $result->isAllowed(); } diff --git a/web/core/lib/Drupal/Core/Entity/EntityManager.php b/web/core/lib/Drupal/Core/Entity/EntityManager.php index fa2ddf8c7..6f2ce7672 100644 --- a/web/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/web/core/lib/Drupal/Core/Entity/EntityManager.php @@ -25,6 +25,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::clearCachedDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function clearCachedDefinitions() { $this->container->get('entity_type.manager')->clearCachedDefinitions(); @@ -41,6 +45,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getDefinition() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getDefinition($entity_type_id, $exception_on_invalid = TRUE) { return $this->container->get('entity_type.manager')->getDefinition($entity_type_id, $exception_on_invalid); @@ -50,6 +58,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::hasHandler() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function hasHandler($entity_type, $handler_type) { return $this->container->get('entity_type.manager')->hasHandler($entity_type, $handler_type); @@ -59,6 +71,9 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getStorage() instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getStorage($entity_type) { return $this->container->get('entity_type.manager')->getStorage($entity_type); @@ -68,6 +83,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getListBuilder() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getListBuilder($entity_type) { return $this->container->get('entity_type.manager')->getListBuilder($entity_type); @@ -77,6 +96,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getFormObject() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFormObject($entity_type, $operation) { return $this->container->get('entity_type.manager')->getFormObject($entity_type, $operation); @@ -86,6 +109,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getRouteProviders() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getRouteProviders($entity_type) { return $this->container->get('entity_type.manager')->getRouteProviders($entity_type); @@ -95,6 +122,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getViewBuilder() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getViewBuilder($entity_type) { return $this->container->get('entity_type.manager')->getViewBuilder($entity_type); @@ -104,6 +135,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getAccessControlHandler() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getAccessControlHandler($entity_type) { return $this->container->get('entity_type.manager')->getAccessControlHandler($entity_type); @@ -113,6 +148,9 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getHandler() instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getHandler($entity_type, $handler_type) { return $this->container->get('entity_type.manager')->getHandler($entity_type, $handler_type); @@ -122,6 +160,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::createHandlerInstance() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function createHandlerInstance($class, EntityTypeInterface $definition = NULL) { return $this->container->get('entity_type.manager')->createHandlerInstance($class, $definition); @@ -131,6 +173,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::getBaseFieldDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getBaseFieldDefinitions($entity_type_id) { return $this->container->get('entity_field.manager')->getBaseFieldDefinitions($entity_type_id); @@ -140,6 +186,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::getFieldDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFieldDefinitions($entity_type_id, $bundle) { return $this->container->get('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle); @@ -149,6 +199,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::getFieldStorageDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFieldStorageDefinitions($entity_type_id) { return $this->container->get('entity_field.manager')->getFieldStorageDefinitions($entity_type_id); @@ -158,6 +212,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::setFieldMap() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function setFieldMap(array $field_map) { return $this->container->get('entity_field.manager')->setFieldMap($field_map); @@ -167,6 +225,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::getFieldMap() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFieldMap() { return $this->container->get('entity_field.manager')->getFieldMap(); @@ -176,6 +238,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::getFieldMapByFieldType() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFieldMapByFieldType($field_type) { return $this->container->get('entity_field.manager')->getFieldMapByFieldType($field_type); @@ -185,6 +251,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldDefinitionListenerInterface::onFieldDefinitionCreate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldDefinitionCreate(FieldDefinitionInterface $field_definition) { $this->container->get('field_definition.listener')->onFieldDefinitionCreate($field_definition); @@ -194,6 +264,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldDefinitionListenerInterface::onFieldDefinitionUpdate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldDefinitionUpdate(FieldDefinitionInterface $field_definition, FieldDefinitionInterface $original) { $this->container->get('field_definition.listener')->onFieldDefinitionUpdate($field_definition, $original); @@ -203,6 +277,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldDefinitionListenerInterface::onFieldDefinitionDelete() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definition) { $this->container->get('field_definition.listener')->onFieldDefinitionDelete($field_definition); @@ -212,6 +290,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityFieldManagerInterface::clearCachedFieldDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function clearCachedFieldDefinitions() { $this->container->get('entity_field.manager')->clearCachedFieldDefinitions(); @@ -221,6 +303,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::clearCachedBundles() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function clearCachedBundles() { $this->container->get('entity_type.bundle.info')->clearCachedBundles(); @@ -230,6 +316,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::getBundleInfo() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getBundleInfo($entity_type) { return $this->container->get('entity_type.bundle.info')->getBundleInfo($entity_type); @@ -239,6 +329,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::getAllBundleInfo() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getAllBundleInfo() { return $this->container->get('entity_type.bundle.info')->getAllBundleInfo(); @@ -255,6 +349,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeRepositoryInterface::getEntityTypeLabels() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getEntityTypeLabels($group = FALSE) { return $this->container->get('entity_type.repository')->getEntityTypeLabels($group); @@ -264,6 +362,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityRepositoryInterface::getTranslationFromContext() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = []) { return $this->container->get('entity.repository')->getTranslationFromContext($entity, $langcode, $context); @@ -273,6 +375,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getAllViewModes() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getAllViewModes() { return $this->container->get('entity_display.repository')->getAllViewModes(); @@ -282,6 +388,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getViewModes() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getViewModes($entity_type_id) { return $this->container->get('entity_display.repository')->getViewModes($entity_type_id); @@ -291,6 +401,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getAllFormModes() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getAllFormModes() { return $this->container->get('entity_display.repository')->getAllFormModes(); @@ -300,6 +414,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getFormModes() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFormModes($entity_type_id) { return $this->container->get('entity_display.repository')->getFormModes($entity_type_id); @@ -309,6 +427,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getViewModeOptions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getViewModeOptions($entity_type_id) { return $this->container->get('entity_display.repository')->getViewModeOptions($entity_type_id); @@ -318,6 +440,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getFormModeOptions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFormModeOptions($entity_type_id) { return $this->container->get('entity_display.repository')->getFormModeOptions($entity_type_id); @@ -327,6 +453,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getViewModeOptionsByBundle() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getViewModeOptionsByBundle($entity_type_id, $bundle) { return $this->container->get('entity_display.repository')->getViewModeOptionsByBundle($entity_type_id, $bundle); @@ -336,6 +466,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::getFormModeOptionsByBundle() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getFormModeOptionsByBundle($entity_type_id, $bundle) { return $this->container->get('entity_display.repository')->getFormModeOptionsByBundle($entity_type_id, $bundle); @@ -345,6 +479,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityDisplayRepositoryInterface::clearDisplayModeInfo() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function clearDisplayModeInfo() { $this->container->get('entity_display.repository')->clearDisplayModeInfo(); @@ -354,6 +492,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityRepositoryInterface::loadEntityByUuid() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function loadEntityByUuid($entity_type_id, $uuid) { return $this->container->get('entity.repository')->loadEntityByUuid($entity_type_id, $uuid); @@ -363,6 +505,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityRepositoryInterface::loadEntityByConfigTarget() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function loadEntityByConfigTarget($entity_type_id, $target) { return $this->container->get('entity.repository')->loadEntityByConfigTarget($entity_type_id, $target); @@ -372,6 +518,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeRepositoryInterface::getEntityTypeFromClass() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getEntityTypeFromClass($class_name) { return $this->container->get('entity_type.repository')->getEntityTypeFromClass($class_name); @@ -388,6 +538,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeListenerInterface::onEntityTypeUpdate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original) { $this->container->get('entity_type.listener')->onEntityTypeUpdate($entity_type, $original); @@ -397,6 +551,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeListenerInterface::onEntityTypeDelete() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onEntityTypeDelete(EntityTypeInterface $entity_type) { $this->container->get('entity_type.listener')->onEntityTypeDelete($entity_type); @@ -406,6 +564,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldStorageDefinitionListenerInterface::onFieldStorageDefinitionCreate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $storage_definition) { $this->container->get('field_storage_definition.listener')->onFieldStorageDefinitionCreate($storage_definition); @@ -415,6 +577,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldStorageDefinitionListenerInterface::onFieldStorageDefinitionUpdate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) { $this->container->get('field_storage_definition.listener')->onFieldStorageDefinitionUpdate($storage_definition, $original); @@ -424,6 +590,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Field\FieldStorageDefinitionListenerInterface::onFieldStorageDefinitionDelete() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) { $this->container->get('field_storage_definition.listener')->onFieldStorageDefinitionDelete($storage_definition); @@ -433,6 +603,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityBundleListenerInterface::onBundleCreate() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onBundleCreate($bundle, $entity_type_id) { $this->container->get('entity_bundle.listener')->onBundleCreate($bundle, $entity_type_id); @@ -442,6 +616,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityBundleListenerInterface::onBundleDelete() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function onBundleDelete($bundle, $entity_type_id) { $this->container->get('entity_bundle.listener')->onBundleDelete($bundle, $entity_type_id); @@ -451,6 +629,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface::getLastInstalledDefinition() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getLastInstalledDefinition($entity_type_id) { return $this->container->get('entity.last_installed_schema.repository')->getLastInstalledDefinition($entity_type_id); @@ -471,6 +653,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface::getLastInstalledFieldStorageDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getLastInstalledFieldStorageDefinitions($entity_type_id) { return $this->container->get('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions($entity_type_id); @@ -480,6 +666,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getDefinitions() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getDefinitions() { return $this->container->get('entity_type.manager')->getDefinitions(); @@ -489,6 +679,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::hasDefinition() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function hasDefinition($plugin_id) { return $this->container->get('entity_type.manager')->hasDefinition($plugin_id); @@ -498,6 +692,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::createInstance() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function createInstance($plugin_id, array $configuration = []) { return $this->container->get('entity_type.manager')->createInstance($plugin_id, $configuration); @@ -507,6 +705,10 @@ class EntityManager implements EntityManagerInterface, ContainerAwareInterface { * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getInstance() + * instead. + * + * @see https://www.drupal.org/node/2549139 */ public function getInstance(array $options) { return $this->container->get('entity_type.manager')->getInstance($options); diff --git a/web/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php b/web/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php index 6b2738c77..03d3f66c7 100644 --- a/web/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php +++ b/web/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php @@ -144,7 +144,7 @@ interface ModuleHandlerInterface { * // Load node.admin.inc from the node module. * $this->loadInclude('node', 'inc', 'node.admin'); * // Load content_types.inc from the node module. - * $this->loadInclude('node', 'inc', ''content_types'); + * $this->loadInclude('node', 'inc', 'content_types'); * @endcode * * @param string $module diff --git a/web/core/lib/Drupal/Core/Field/FieldConfigBase.php b/web/core/lib/Drupal/Core/Field/FieldConfigBase.php index 76366bfe2..e53e84b6c 100644 --- a/web/core/lib/Drupal/Core/Field/FieldConfigBase.php +++ b/web/core/lib/Drupal/Core/Field/FieldConfigBase.php @@ -180,6 +180,14 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn */ protected $constraints = []; + /** + * Array of property constraint options keyed by property ID. The values are + * associative array of constraint options keyed by constraint plugin ID. + * + * @var array[] + */ + protected $propertyConstraints = []; + /** * {@inheritdoc} */ @@ -515,7 +523,20 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn if (!isset($this->itemDefinition)) { $this->itemDefinition = FieldItemDataDefinition::create($this) ->setSettings($this->getSettings()); + + // Add any custom property constraints, overwriting as required. + $item_constraints = $this->itemDefinition->getConstraint('ComplexData') ?: []; + foreach ($this->propertyConstraints as $name => $constraints) { + if (isset($item_constraints[$name])) { + $item_constraints[$name] = $constraints + $item_constraints[$name]; + } + else { + $item_constraints[$name] = $constraints; + } + $this->itemDefinition->addConstraint('ComplexData', $item_constraints); + } } + return $this->itemDefinition; } @@ -546,9 +567,12 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn * {@inheritdoc} */ public function setPropertyConstraints($name, array $constraints) { - $item_constraints = $this->getItemDefinition()->getConstraints(); - $item_constraints['ComplexData'][$name] = $constraints; - $this->getItemDefinition()->setConstraints($item_constraints); + $this->propertyConstraints[$name] = $constraints; + + // Reset the field item definition so the next time it is instantiated it + // will receive the new constraints. + $this->itemDefinition = NULL; + return $this; } @@ -556,15 +580,14 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn * {@inheritdoc} */ public function addPropertyConstraints($name, array $constraints) { - $item_constraints = $this->getItemDefinition()->getConstraint('ComplexData') ?: []; - if (isset($item_constraints[$name])) { - // Add the new property constraints, overwriting as required. - $item_constraints[$name] = $constraints + $item_constraints[$name]; - } - else { - $item_constraints[$name] = $constraints; + foreach ($constraints as $constraint_name => $options) { + $this->propertyConstraints[$name][$constraint_name] = $options; } - $this->getItemDefinition()->addConstraint('ComplexData', $item_constraints); + + // Reset the field item definition so the next time it is instantiated it + // will receive the new constraints. + $this->itemDefinition = NULL; + return $this; } diff --git a/web/core/lib/Drupal/Core/Form/BaseFormIdInterface.php b/web/core/lib/Drupal/Core/Form/BaseFormIdInterface.php index de0c99828..6c9bb5901 100644 --- a/web/core/lib/Drupal/Core/Form/BaseFormIdInterface.php +++ b/web/core/lib/Drupal/Core/Form/BaseFormIdInterface.php @@ -5,7 +5,7 @@ namespace Drupal\Core\Form; /** * Provides an interface for a Form that has a base form ID. * - * This will become the $form_state->getBaseInfo()['base_form_id'] used to + * This will become the $form_state->getBuildInfo()['base_form_id'] used to * generate the name of hook_form_BASE_FORM_ID_alter(). */ interface BaseFormIdInterface extends FormInterface { diff --git a/web/core/lib/Drupal/Core/Render/theme.api.php b/web/core/lib/Drupal/Core/Render/theme.api.php index 6e78d527a..db7a16165 100644 --- a/web/core/lib/Drupal/Core/Render/theme.api.php +++ b/web/core/lib/Drupal/Core/Render/theme.api.php @@ -627,7 +627,7 @@ function hook_preprocess_HOOK(&$variables) { function hook_theme_suggestions_HOOK(array $variables) { $suggestions = []; - $suggestions[] = 'node__' . $variables['elements']['#langcode']; + $suggestions[] = 'hookname__' . $variables['elements']['#langcode']; return $suggestions; } diff --git a/web/core/modules/aggregator/src/Tests/AddFeedTest.php b/web/core/modules/aggregator/tests/src/Functional/AddFeedTest.php similarity index 98% rename from web/core/modules/aggregator/src/Tests/AddFeedTest.php rename to web/core/modules/aggregator/tests/src/Functional/AddFeedTest.php index 4dfeb9557..e4f63ea73 100644 --- a/web/core/modules/aggregator/src/Tests/AddFeedTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/AddFeedTest.php @@ -1,6 +1,6 @@ assertEqual(1, count($result), 'Created feed is found in the overview'); // Check if the fields in the table match with what's expected. - $this->assertEqual($feed->label(), (string) $result[0]->td[0]->a); + $link = $this->xpath('//table/tbody/tr//td[1]/a'); + $this->assertEquals($feed->label(), $link[0]->getText()); $count = $this->container->get('entity.manager')->getStorage('aggregator_item')->getItemCount($feed); - $this->assertEqual(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), (string) $result[0]->td[1]); + $td = $this->xpath('//table/tbody/tr//td[2]'); + $this->assertEquals(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), $td[0]->getText()); // Update the items of the first feed. $feed->refreshItems(); $this->drupalGet('admin/config/services/aggregator'); $result = $this->xpath('//table/tbody/tr'); // Check if the fields in the table match with what's expected. - $this->assertEqual($feed->label(), (string) $result[0]->td[0]->a); + $link = $this->xpath('//table/tbody/tr//td[1]/a'); + $this->assertEquals($feed->label(), $link[0]->getText()); $count = $this->container->get('entity.manager')->getStorage('aggregator_item')->getItemCount($feed); - $this->assertEqual(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), (string) $result[0]->td[1]); + $td = $this->xpath('//table/tbody/tr//td[2]'); + $this->assertEquals(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), $td[0]->getText()); } } diff --git a/web/core/modules/aggregator/src/Tests/AggregatorCronTest.php b/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php similarity index 93% rename from web/core/modules/aggregator/src/Tests/AggregatorCronTest.php rename to web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php index 9ebb2d25c..bb7c90ae3 100644 --- a/web/core/modules/aggregator/src/Tests/AggregatorCronTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php @@ -1,6 +1,8 @@ drupalGet('aggregator/opml'); - $outline = $this->xpath('//outline[1]'); - $this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.'); - $this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.'); - $this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.'); + $content = $this->getSession()->getPage()->getContent(); + // We can't use Mink xpath queries here because it only supports HTML pages, + // but we are dealing with XML here. + $xml = simplexml_load_string($content); + $attributes = $xml->xpath('//outline[1]')[0]->attributes(); + $this->assertEquals('rss', $attributes->type); + $this->assertEquals($feed->label(), $attributes->text); + $this->assertEquals($feed->getUrl(), $attributes->xmlUrl); // Check for the presence of a pager. $this->drupalGet('aggregator/sources/' . $feed->id()); diff --git a/web/core/modules/aggregator/src/Tests/FeedAdminDisplayTest.php b/web/core/modules/aggregator/tests/src/Functional/FeedAdminDisplayTest.php similarity index 98% rename from web/core/modules/aggregator/src/Tests/FeedAdminDisplayTest.php rename to web/core/modules/aggregator/tests/src/Functional/FeedAdminDisplayTest.php index 46366b495..e057be6e6 100644 --- a/web/core/modules/aggregator/src/Tests/FeedAdminDisplayTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/FeedAdminDisplayTest.php @@ -1,6 +1,6 @@ getDerivativeId(); if (!isset($this->blockContent)) { + $uuid = $this->getDerivativeId(); $this->blockContent = $this->entityManager->loadEntityByUuid('block_content', $uuid); } return $this->blockContent; diff --git a/web/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php b/web/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php index db665c9e4..3ea2dba06 100644 --- a/web/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php +++ b/web/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php @@ -2,6 +2,8 @@ namespace Drupal\block_content\Tests\Views; +@trigger_error('\Drupal\block_content\Tests\Views\BlockContentTestBase is deprecated in 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\Tests\block_content\Functional\Views\BlockContentTestBase.', E_USER_DEPRECATED); + use Drupal\block_content\Entity\BlockContent; use Drupal\block_content\Entity\BlockContentType; use Drupal\Component\Utility\SafeMarkup; @@ -10,6 +12,9 @@ use Drupal\views\Tests\ViewTestData; /** * Base class for all block_content tests. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. + * Use \Drupal\Tests\block_content\Functional\Views\BlockContentTestBase. */ abstract class BlockContentTestBase extends ViewTestBase { diff --git a/web/core/modules/block_content/src/Tests/BlockContentCreationTest.php b/web/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php similarity index 98% rename from web/core/modules/block_content/src/Tests/BlockContentCreationTest.php rename to web/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php index ac9e824d4..562a4bd10 100644 --- a/web/core/modules/block_content/src/Tests/BlockContentCreationTest.php +++ b/web/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php @@ -1,6 +1,6 @@ drupalGet('admin/structure/block/manage/testblock'); - $this->assertFieldByXPath('//select[@name="settings[view_mode]"]/option[@selected="selected"]/@value', 'test_view_mode', 'View mode changed to Test View Mode'); + $this->assertFieldByXPath('//select[@name="settings[view_mode]"]/option[@selected="selected"]', 'test_view_mode', 'View mode changed to Test View Mode'); // Check that the block exists in the database. $blocks = entity_load_multiple_by_properties('block_content', ['info' => $edit['info[0][value]']]); diff --git a/web/core/modules/block_content/src/Tests/BlockContentListTest.php b/web/core/modules/block_content/tests/src/Functional/BlockContentListTest.php similarity index 95% rename from web/core/modules/block_content/src/Tests/BlockContentListTest.php rename to web/core/modules/block_content/tests/src/Functional/BlockContentListTest.php index e00706e9f..aba60c366 100644 --- a/web/core/modules/block_content/src/Tests/BlockContentListTest.php +++ b/web/core/modules/block_content/tests/src/Functional/BlockContentListTest.php @@ -1,6 +1,6 @@ $element) { - $this->assertEqual($element[0], $expected_items[$key]); + $this->assertEqual($element->getText(), $expected_items[$key]); } $label = 'Antelope'; @@ -66,7 +66,7 @@ class BlockContentListTest extends BlockContentTestBase { // Check the contents of each row cell. The first cell contains the label, // the second contains the machine name, and the third contains the // operations list. - $this->assertIdentical((string) $elements[0], $label); + $this->assertIdentical($elements[0]->getText(), $label); // Edit the entity using the operations link. $blocks = $this->container diff --git a/web/core/modules/block_content/src/Tests/BlockContentListViewsTest.php b/web/core/modules/block_content/tests/src/Functional/BlockContentListViewsTest.php similarity index 91% rename from web/core/modules/block_content/src/Tests/BlockContentListViewsTest.php rename to web/core/modules/block_content/tests/src/Functional/BlockContentListViewsTest.php index 77117fb00..1c623be82 100644 --- a/web/core/modules/block_content/src/Tests/BlockContentListViewsTest.php +++ b/web/core/modules/block_content/tests/src/Functional/BlockContentListViewsTest.php @@ -1,6 +1,6 @@ assertEqual(count($elements), 4, 'Correct number of table header cells found.'); // Test the contents of each th cell. - $expected_items = ['Block description', 'Block type', 'Updated', 'Operations']; + $expected_items = ['Block description', 'Block type', 'Updated Sort ascending', 'Operations']; foreach ($elements as $key => $element) { - if ($element->xpath('a')) { - $this->assertIdentical(trim((string) $element->xpath('a')[0]), $expected_items[$key]); + if ($element->find('xpath', 'a')) { + $this->assertIdentical(trim($element->find('xpath', 'a')->getText()), $expected_items[$key]); } else { - $this->assertIdentical(trim((string) $element[0]), $expected_items[$key]); + $this->assertIdentical(trim($element->getText()), $expected_items[$key]); } } @@ -73,7 +73,7 @@ class BlockContentListViewsTest extends BlockContentTestBase { // Check the contents of each row cell. The first cell contains the label, // the second contains the machine name, and the third contains the // operations list. - $this->assertIdentical((string) $elements[0]->xpath('a')[0], $label); + $this->assertIdentical($elements[0]->find('xpath', 'a')->getText(), $label); // Edit the entity using the operations link. $blocks = $this->container diff --git a/web/core/modules/block_content/src/Tests/BlockContentTranslationUITest.php b/web/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php similarity index 99% rename from web/core/modules/block_content/src/Tests/BlockContentTranslationUITest.php rename to web/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php index 198beee8f..2699fcfb6 100644 --- a/web/core/modules/block_content/src/Tests/BlockContentTranslationUITest.php +++ b/web/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php @@ -1,6 +1,6 @@ save(); diff --git a/web/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php b/web/core/modules/block_content/tests/src/Functional/Views/BlockContentIntegrationTest.php similarity index 95% rename from web/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php rename to web/core/modules/block_content/tests/src/Functional/Views/BlockContentIntegrationTest.php index 8ec17e238..93661578b 100644 --- a/web/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php +++ b/web/core/modules/block_content/tests/src/Functional/Views/BlockContentIntegrationTest.php @@ -1,6 +1,6 @@ xpath('//span[@class="field-content"]'); $ids = []; foreach ($result as $element) { - $ids[] = (int) $element; + $ids[] = $element->getText(); } $this->assertEqual($ids, $expected_ids); } diff --git a/web/core/modules/block_content/src/Tests/Views/BlockContentRedirectTest.php b/web/core/modules/block_content/tests/src/Functional/Views/BlockContentRedirectTest.php similarity index 95% rename from web/core/modules/block_content/src/Tests/Views/BlockContentRedirectTest.php rename to web/core/modules/block_content/tests/src/Functional/Views/BlockContentRedirectTest.php index 828aa8468..10ce140e9 100644 --- a/web/core/modules/block_content/src/Tests/Views/BlockContentRedirectTest.php +++ b/web/core/modules/block_content/tests/src/Functional/Views/BlockContentRedirectTest.php @@ -1,6 +1,6 @@ createBlockContentType(['id' => 'basic']); + + $this->adminUser = $this->drupalCreateUser($this->permissions); + + if ($import_test_views) { + ViewTestData::createTestViews(get_class($this), ['block_content_test_views']); + } + } + + /** + * Creates a custom block. + * + * @param array $settings + * (optional) An associative array of settings for the block_content, as + * used in entity_create(). + * + * @return \Drupal\block_content\Entity\BlockContent + * Created custom block. + */ + protected function createBlockContent(array $settings = []) { + $status = 0; + $settings += [ + 'info' => $this->randomMachineName(), + 'type' => 'basic', + 'langcode' => 'en', + ]; + if ($block_content = BlockContent::create($settings)) { + $status = $block_content->save(); + } + $this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content %info.', ['%info' => $block_content->label()])); + return $block_content; + } + + /** + * Creates a custom block type (bundle). + * + * @param array $values + * An array of settings to change from the defaults. + * + * @return \Drupal\block_content\Entity\BlockContentType + * Created custom block type. + */ + protected function createBlockContentType(array $values = []) { + // Find a non-existent random type name. + if (!isset($values['id'])) { + do { + $id = strtolower($this->randomMachineName(8)); + } while (BlockContentType::load($id)); + } + else { + $id = $values['id']; + } + $values += [ + 'id' => $id, + 'label' => $id, + 'revision' => FALSE + ]; + $bundle = BlockContentType::create($values); + $status = $bundle->save(); + block_content_add_body_field($bundle->id()); + + $this->assertEqual($status, SAVED_NEW, SafeMarkup::format('Created block content type %bundle.', ['%bundle' => $bundle->id()])); + return $bundle; + } + +} diff --git a/web/core/modules/block_content/src/Tests/Views/FieldTypeTest.php b/web/core/modules/block_content/tests/src/Functional/Views/FieldTypeTest.php similarity index 93% rename from web/core/modules/block_content/src/Tests/Views/FieldTypeTest.php rename to web/core/modules/block_content/tests/src/Functional/Views/FieldTypeTest.php index e9aa33698..8ff2fc05c 100644 --- a/web/core/modules/block_content/src/Tests/Views/FieldTypeTest.php +++ b/web/core/modules/block_content/tests/src/Functional/Views/FieldTypeTest.php @@ -1,6 +1,6 @@ 'basic', 'label' => 'basic', diff --git a/web/core/modules/book/src/Tests/Views/BookRelationshipTest.php b/web/core/modules/book/tests/src/Functional/Views/BookRelationshipTest.php similarity index 95% rename from web/core/modules/book/src/Tests/Views/BookRelationshipTest.php rename to web/core/modules/book/tests/src/Functional/Views/BookRelationshipTest.php index c1f872803..9ee79c78d 100644 --- a/web/core/modules/book/src/Tests/Views/BookRelationshipTest.php +++ b/web/core/modules/book/tests/src/Functional/Views/BookRelationshipTest.php @@ -1,8 +1,8 @@ bookAuthor = $this->drupalCreateUser( diff --git a/web/core/modules/comment/src/Entity/Comment.php b/web/core/modules/comment/src/Entity/Comment.php index a5f196646..8ce0c73ed 100644 --- a/web/core/modules/comment/src/Entity/Comment.php +++ b/web/core/modules/comment/src/Entity/Comment.php @@ -81,14 +81,6 @@ class Comment extends ContentEntityBase implements CommentInterface { public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); - if (is_null($this->get('status')->value)) { - if (\Drupal::currentUser()->hasPermission('skip comment approval')) { - $this->setPublished(); - } - else { - $this->setUnpublished(); - } - } if ($this->isNew()) { // Add the comment to database. This next section builds the thread field. // @see \Drupal\comment\CommentViewBuilder::buildComponents() @@ -237,6 +229,9 @@ class Comment extends ContentEntityBase implements CommentInterface { $fields['langcode']->setDescription(t('The comment language code.')); + // Set the default value callback for the status field. + $fields['status']->setDefaultValueCallback('Drupal\comment\Entity\Comment::getDefaultStatus'); + $fields['pid'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Parent ID')) ->setDescription(t('The parent comment ID if this is a reply to a comment.')) @@ -558,4 +553,16 @@ class Comment extends ContentEntityBase implements CommentInterface { return $this->bundle(); } + /** + * Default value callback for 'status' base field definition. + * + * @see ::baseFieldDefinitions() + * + * @return bool + * TRUE if the comment should be published, FALSE otherwise. + */ + public static function getDefaultStatus() { + return \Drupal::currentUser()->hasPermission('skip comment approval') ? CommentInterface::PUBLISHED : CommentInterface::NOT_PUBLISHED; + } + } diff --git a/web/core/modules/comment/tests/src/Unit/Entity/CommentLockTest.php b/web/core/modules/comment/tests/src/Unit/Entity/CommentLockTest.php index e724dc6b8..9dbe6d36e 100644 --- a/web/core/modules/comment/tests/src/Unit/Entity/CommentLockTest.php +++ b/web/core/modules/comment/tests/src/Unit/Entity/CommentLockTest.php @@ -81,10 +81,6 @@ class CommentLockTest extends UnitTestCase { $comment->expects($this->any()) ->method('getEntityType') ->will($this->returnValue($entity_type)); - $comment->expects($this->at(1)) - ->method('get') - ->with('status') - ->will($this->returnValue((object) ['value' => NULL])); $storage = $this->getMock('Drupal\comment\CommentStorageInterface'); // preSave() should acquire the lock. (This is what's really being tested.) diff --git a/web/core/modules/config_translation/src/Tests/ConfigTranslationFormTest.php b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationFormTest.php similarity index 92% rename from web/core/modules/config_translation/src/Tests/ConfigTranslationFormTest.php rename to web/core/modules/config_translation/tests/src/Functional/ConfigTranslationFormTest.php index 387d68646..4698b05a8 100644 --- a/web/core/modules/config_translation/src/Tests/ConfigTranslationFormTest.php +++ b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationFormTest.php @@ -1,16 +1,16 @@ cssSelect('ul.dropbutton') as $i => $dropbutton) { - $this->assertIdentical(1, $dropbutton->count()); - foreach ($dropbutton->li as $link) { - $this->assertTrue(((string) $link->a === 'Translate') || ((string) $link->a === 'List')); - } + $this->assertIdentical(1, count($dropbutton->find('xpath', 'li'))); + $this->assertTrue(($dropbutton->getText() === 'Translate') || ($dropbutton->getText() === 'List')); } $labels = [ @@ -104,10 +102,8 @@ class ConfigTranslationOverviewTest extends WebTestBase { // Make sure there is only a single 'Translate' operation for each // dropbutton. foreach ($this->cssSelect('ul.dropbutton') as $i => $dropbutton) { - $this->assertIdentical(1, $dropbutton->count()); - foreach ($dropbutton->li as $link) { - $this->assertIdentical('Translate', (string) $link->a); - } + $this->assertIdentical(1, count($dropbutton->find('xpath', 'li'))); + $this->assertIdentical('Translate', $dropbutton->getText()); } $entity_type = \Drupal::entityManager()->getDefinition($test_entity->getEntityTypeId()); diff --git a/web/core/modules/config_translation/src/Tests/ConfigTranslationUiThemeTest.php b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiThemeTest.php similarity index 86% rename from web/core/modules/config_translation/src/Tests/ConfigTranslationUiThemeTest.php rename to web/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiThemeTest.php index 53713a923..dcfb7916f 100644 --- a/web/core/modules/config_translation/src/Tests/ConfigTranslationUiThemeTest.php +++ b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiThemeTest.php @@ -1,16 +1,16 @@ 'Install and set as default', ':theme' => $theme, ]); - $this->drupalGet($GLOBALS['base_root'] . $elements[0]['href'], ['external' => TRUE]); + $this->drupalGet($GLOBALS['base_root'] . $elements[0]->getAttribute('href'), ['external' => TRUE]); $translation_base_url = 'admin/config/development/performance/translate'; $this->drupalGet($translation_base_url); diff --git a/web/core/modules/config_translation/src/Tests/ConfigTranslationViewListUiTest.php b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationViewListUiTest.php similarity index 86% rename from web/core/modules/config_translation/src/Tests/ConfigTranslationViewListUiTest.php rename to web/core/modules/config_translation/tests/src/Functional/ConfigTranslationViewListUiTest.php index b259a1858..edb41f9ad 100644 --- a/web/core/modules/config_translation/src/Tests/ConfigTranslationViewListUiTest.php +++ b/web/core/modules/config_translation/tests/src/Functional/ConfigTranslationViewListUiTest.php @@ -1,8 +1,8 @@ fieldStorage = FieldStorageConfig::create([ 'field_name' => strtolower($this->randomMachineName()), diff --git a/web/core/modules/contact/src/Tests/Views/ContactLinkTest.php b/web/core/modules/contact/tests/src/Functional/Views/ContactLinkTest.php similarity index 94% rename from web/core/modules/contact/src/Tests/Views/ContactLinkTest.php rename to web/core/modules/contact/tests/src/Functional/Views/ContactLinkTest.php index f6b6013b4..c3b68f067 100644 --- a/web/core/modules/contact/src/Tests/Views/ContactLinkTest.php +++ b/web/core/modules/contact/tests/src/Functional/Views/ContactLinkTest.php @@ -1,9 +1,9 @@ getState($entity->isPublished() ? 'published' : 'draft'); + return $workflow->getState($entity->isPublished() && !$entity->isNew() ? 'published' : 'draft'); } return parent::getInitialState($workflow); } diff --git a/web/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php b/web/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php index 0150d3c6e..3db6a662c 100644 --- a/web/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php +++ b/web/core/modules/content_moderation/tests/src/Kernel/InitialStateTest.php @@ -77,6 +77,12 @@ class InitialStateTest extends KernelTestBase { $this->assertEquals('draft', $loaded_unpublished_node->moderation_state->value); $this->assertEquals('published', $loaded_published_node->moderation_state->value); $this->assertEquals('draft', $loaded_entity_test->moderation_state->value); + + $presave_node = Node::create([ + 'type' => 'example', + 'title' => 'Presave node', + ]); + $this->assertEquals('draft', $presave_node->moderation_state->value); } } diff --git a/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php index 7e9a75c3f..5a2f6a0b3 100644 --- a/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php +++ b/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php @@ -64,7 +64,8 @@ class ModerationStateFieldItemListTest extends KernelTestBase { * Test the field item list when accessing an index. */ public function testArrayIndex() { - $this->assertEquals('published', $this->testNode->moderation_state[0]->value); + $this->assertFalse($this->testNode->isPublished()); + $this->assertEquals('draft', $this->testNode->moderation_state[0]->value); } /** @@ -75,7 +76,7 @@ class ModerationStateFieldItemListTest extends KernelTestBase { foreach ($this->testNode->moderation_state as $item) { $states[] = $item->value; } - $this->assertEquals(['published'], $states); + $this->assertEquals(['draft'], $states); } } diff --git a/web/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php b/web/core/modules/content_translation/tests/src/Functional/ContentTestTranslationUITest.php similarity index 93% rename from web/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php rename to web/core/modules/content_translation/tests/src/Functional/ContentTestTranslationUITest.php index 1688f75fd..0b1de0b20 100644 --- a/web/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php +++ b/web/core/modules/content_translation/tests/src/Functional/ContentTestTranslationUITest.php @@ -1,6 +1,6 @@ drupalGet('admin/reports/status'); $requirement_value = $this->cssSelect("details.system-status-report__entry summary:contains('Entity/field definitions') + div"); - $this->assertEqual(t('Up to date'), trim((string) $requirement_value[0])); + $this->assertEqual(t('Up to date'), trim($requirement_value[0]->getText())); $this->drupalGet('admin/config/regional/content-language'); // The node entity type should not be an option because it has no bundles. @@ -54,7 +54,7 @@ class ContentTranslationEnableTest extends WebTestBase { // No pending updates should be available. $this->drupalGet('admin/reports/status'); $requirement_value = $this->cssSelect("details.system-status-report__entry summary:contains('Entity/field definitions') + div"); - $this->assertEqual(t('Up to date'), trim((string) $requirement_value[0])); + $this->assertEqual(t('Up to date'), trim($requirement_value[0]->getText())); // Create a node type and check the content translation settings are now // available for nodes. diff --git a/web/core/modules/content_translation/src/Tests/ContentTranslationLanguageChangeTest.php b/web/core/modules/content_translation/tests/src/Functional/ContentTranslationLanguageChangeTest.php similarity index 98% rename from web/core/modules/content_translation/src/Tests/ContentTranslationLanguageChangeTest.php rename to web/core/modules/content_translation/tests/src/Functional/ContentTranslationLanguageChangeTest.php index bb9b2235e..3236a592c 100644 --- a/web/core/modules/content_translation/src/Tests/ContentTranslationLanguageChangeTest.php +++ b/web/core/modules/content_translation/tests/src/Functional/ContentTranslationLanguageChangeTest.php @@ -1,6 +1,6 @@ xpath('//select[@id="edit-settings-node-article-settings-language-langcode"]/option'); // Compare values inside the option elements with expected values. for ($i = 0; $i < count($elements); $i++) { - $this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]); + $this->assertEqual($elements[$i]->getValue(), $expected_elements[$i]); } } diff --git a/web/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php b/web/core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php similarity index 98% rename from web/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php rename to web/core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php index 30ff32de5..5f7c9fd9b 100644 --- a/web/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php +++ b/web/core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php @@ -1,11 +1,12 @@ get('field_test_set_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) { + if (($field_name = \Drupal::state()->get('field_test_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) { + // Set a property constraint using + // \Drupal\Core\Field\FieldConfigInterface::setPropertyConstraints(). $fields[$field_name]->setPropertyConstraints('value', [ - 'Range' => [ - 'min' => 0, - 'max' => 32, + 'TestField' => [ + 'value' => -2, + 'message' => t('%name does not accept the value @value.', ['%name' => $field_name, '@value' => -2]), ], ]); - } - if (($field_name = \Drupal::state()->get('field_test_add_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) { + + // Add a property constraint using + // \Drupal\Core\Field\FieldConfigInterface::addPropertyConstraints(). $fields[$field_name]->addPropertyConstraints('value', [ 'Range' => [ 'min' => 0, diff --git a/web/core/modules/field/tests/src/Kernel/FieldCrudTest.php b/web/core/modules/field/tests/src/Kernel/FieldCrudTest.php index 87441dc40..08fe18c5c 100644 --- a/web/core/modules/field/tests/src/Kernel/FieldCrudTest.php +++ b/web/core/modules/field/tests/src/Kernel/FieldCrudTest.php @@ -12,6 +12,8 @@ use Drupal\field\Entity\FieldConfig; /** * Create field entities by attaching fields to entities. * + * @coversDefaultClass \Drupal\Core\Field\FieldConfigBase + * * @group field */ class FieldCrudTest extends FieldKernelTestBase { @@ -64,10 +66,6 @@ class FieldCrudTest extends FieldKernelTestBase { * Test the creation of a field. */ public function testCreateField() { - // Set a state flag so that field_test.module knows to add an in-memory - // constraint for this field. - \Drupal::state()->set('field_test_add_constraint', $this->fieldStorage->getName()); - /** @var \Drupal\Core\Field\FieldConfigInterface $field */ $field = FieldConfig::create($this->fieldDefinition); $field->save(); @@ -100,17 +98,6 @@ class FieldCrudTest extends FieldKernelTestBase { // Check that the denormalized 'field_type' was properly written. $this->assertEqual($config['field_type'], $this->fieldStorageDefinition['type']); - // Test constraints are applied. A Range constraint is added dynamically to - // limit the field to values between 0 and 32. - // @see field_test_entity_bundle_field_info_alter() - $this->doFieldValidationTests(); - - // Test FieldConfigBase::setPropertyConstraints(). - \Drupal::state()->set('field_test_set_constraint', $this->fieldStorage->getName()); - \Drupal::state()->set('field_test_add_constraint', FALSE); - \Drupal::entityManager()->clearCachedFieldDefinitions(); - $this->doFieldValidationTests(); - // Guarantee that the field/bundle combination is unique. try { FieldConfig::create($this->fieldDefinition)->save(); @@ -133,6 +120,81 @@ class FieldCrudTest extends FieldKernelTestBase { // TODO: test other failures. } + /** + * Tests setting and adding property constraints to a configurable field. + * + * @covers ::setPropertyConstraints + * @covers ::addPropertyConstraints + */ + public function testFieldPropertyConstraints() { + $field = FieldConfig::create($this->fieldDefinition); + $field->save(); + $field_name = $this->fieldStorage->getName(); + + // Test that constraints are applied to configurable fields. A TestField and + // a Range constraint are added dynamically to limit the field to values + // between 0 and 32. + // @see field_test_entity_bundle_field_info_alter() + \Drupal::state()->set('field_test_constraint', $field_name); + + // Clear the field definitions cache so the new constraints added by + // field_test_entity_bundle_field_info_alter() are taken into consideration. + \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions(); + + // Test the newly added property constraints in the same request as when the + // caches were cleared. This will test the field definitions that are stored + // in the static cache of + // \Drupal\Core\Entity\EntityFieldManager::getFieldDefinitions(). + $this->doFieldPropertyConstraintsTests(); + + // In order to test a real-world scenario where the property constraints are + // only stored in the persistent cache of + // \Drupal\Core\Entity\EntityFieldManager::getFieldDefinitions(), we need to + // simulate a new request by removing the 'entity_field.manager' service, + // thus forcing it to be re-initialized without static caches. + \Drupal::getContainer()->set('entity_field.manager', NULL); + + // This will test the field definitions that are stored in the persistent + // cache by \Drupal\Core\Entity\EntityFieldManager::getFieldDefinitions(). + $this->doFieldPropertyConstraintsTests(); + } + + /** + * Tests configurable field validation. + * + * @see field_test_entity_bundle_field_info_alter() + */ + protected function doFieldPropertyConstraintsTests() { + $field_name = $this->fieldStorage->getName(); + + // Check that a valid value (not -2 and between 0 and 32) doesn't trigger + // any violation. + $entity = EntityTest::create(); + $entity->set($field_name, 1); + $violations = $entity->validate(); + $this->assertCount(0, $violations, 'No violations found when in-range value passed.'); + + // Check that a value that is specifically restricted triggers both + // violations. + $entity->set($field_name, -2); + $violations = $entity->validate(); + $this->assertCount(2, $violations, 'Two violations found when using a null and outside the range value.'); + + $this->assertEquals($field_name . '.0.value', $violations[0]->getPropertyPath()); + $this->assertEquals(t('%name does not accept the value @value.', ['%name' => $field_name, '@value' => -2]), $violations[0]->getMessage()); + + $this->assertEquals($field_name . '.0.value', $violations[1]->getPropertyPath()); + $this->assertEquals(t('This value should be %limit or more.', ['%limit' => 0]), $violations[1]->getMessage()); + + // Check that a value that is not specifically restricted but outside the + // range triggers the expected violation. + $entity->set($field_name, 33); + $violations = $entity->validate(); + $this->assertCount(1, $violations, 'Violations found when using value outside the range.'); + $this->assertEquals($field_name . '.0.value', $violations[0]->getPropertyPath()); + $this->assertEquals(t('This value should be %limit or less.', ['%limit' => 32]), $violations[0]->getMessage()); + } + /** * Test creating a field with custom storage set. */ @@ -280,24 +342,4 @@ class FieldCrudTest extends FieldKernelTestBase { $this->assertFalse(FieldStorageConfig::loadByName('entity_test', $field_storage->getName())); } - /** - * Tests configurable field validation. - * - * @see field_test_entity_bundle_field_info_alter() - */ - protected function doFieldValidationTests() { - $entity = EntityTest::create(); - $entity->set($this->fieldStorage->getName(), 1); - $violations = $entity->validate(); - $this->assertEqual(count($violations), 0, 'No violations found when in-range value passed.'); - - $entity->set($this->fieldStorage->getName(), 33); - $violations = $entity->validate(); - $this->assertEqual(count($violations), 1, 'Violations found when using value outside the range.'); - $this->assertEqual($violations[0]->getPropertyPath(), $this->fieldStorage->getName() . '.0.value'); - $this->assertEqual($violations[0]->getMessage(), t('This value should be %limit or less.', [ - '%limit' => 32, - ])); - } - } diff --git a/web/core/modules/file/migration_templates/d7_file.yml b/web/core/modules/file/migration_templates/d7_file.yml index 7b35aff9c..3fee04662 100644 --- a/web/core/modules/file/migration_templates/d7_file.yml +++ b/web/core/modules/file/migration_templates/d7_file.yml @@ -6,6 +6,7 @@ migration_tags: - Drupal 7 source: plugin: d7_file + scheme: public constants: # The tool configuring this migration must set source_base_path. It # represents the fully qualified path relative to which URIs in the files diff --git a/web/core/modules/file/migration_templates/d7_file_private.yml b/web/core/modules/file/migration_templates/d7_file_private.yml new file mode 100644 index 000000000..9c6b8e233 --- /dev/null +++ b/web/core/modules/file/migration_templates/d7_file_private.yml @@ -0,0 +1,39 @@ +id: d7_file_private +label: Files +migration_tags: + - Drupal 7 +source: + plugin: d7_file + scheme: private + constants: + # source_base_path must be set by the tool configuring this migration. + # It represents the fully qualified path relative to which uris in the files + # table are specified, and must end with a /. See source_full_path + # configuration in this migration's process pipeline as an example. + source_base_path: '' +process: + # If you are using this file to build a custom migration consider removing + # the fid field to allow incremental migrations. + fid: fid + filename: filename + source_full_path: + - + plugin: concat + delimiter: / + source: + - constants/source_base_path + - filepath + uri: + plugin: file_copy + source: + - '@source_full_path' + - uri + filemime: filemime + status: status + # Drupal 7 didn't keep track of the file's creation or update time -- all it + # had was the vague "timestamp" column. So we'll use it for both. + created: timestamp + changed: timestamp + uid: uid +destination: + plugin: entity:file diff --git a/web/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php b/web/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php new file mode 100644 index 000000000..7b6f76320 --- /dev/null +++ b/web/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php @@ -0,0 +1,98 @@ +setSetting('file_private_path', $this->container->get('site.path') . '/private'); + $this->installEntitySchema('file'); + $fs = $this->container->get('file_system'); + + // Ensure that the private files directory exists. + $fs->mkdir('private://sites/default/private/', NULL, TRUE); + // Put test file in the source directory. + file_put_contents('private://sites/default/private/Babylon5.txt', str_repeat('*', 3)); + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = $this->getMigration('d7_file_private'); + // Set the source plugin's source_file_private_path configuration value, + // which would normally be set by the user running the migration. + $source = $migration->getSourceConfiguration(); + $source['constants']['source_base_path'] = $fs->realpath('private://'); + $migration->set('source', $source); + $this->executeMigration($migration); + } + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container) { + parent::register($container); + $container->register('stream_wrapper.private', 'Drupal\Core\StreamWrapper\PrivateStream') + ->addTag('stream_wrapper', ['scheme' => 'private']); + } + + /** + * Tests a single file entity. + * + * @param int $id + * The file ID. + * @param string $name + * The expected file name. + * @param string $uri + * The expected URI. + * @param string $mime + * The expected MIME type. + * @param int $size + * The expected file size. + * @param int $created + * The expected creation time. + * @param int $changed + * The expected modification time. + * @param int $uid + * The expected owner ID. + */ + protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) { + /** @var \Drupal\file\FileInterface $file */ + $file = File::load($id); + $this->assertInstanceOf(FileInterface::class, $file); + $this->assertSame($name, $file->getFilename()); + $this->assertSame($uri, $file->getFileUri()); + $this->assertFileExists($uri); + $this->assertSame($mime, $file->getMimeType()); + $this->assertSame($size, $file->getSize()); + // isPermanent(), isTemporary(), etc. are determined by the status column. + $this->assertTrue($file->isPermanent()); + $this->assertSame($created, $file->getCreatedTime()); + $this->assertSame($changed, $file->getChangedTime()); + $this->assertSame($uid, $file->getOwnerId()); + } + + /** + * Tests that all expected files are migrated. + */ + public function testFileMigration() { + $this->assertEntity(3, 'Babylon5.txt', 'private://Babylon5.txt', 'text/plain', '3', '1486104045', '1486104045', '1'); + } + +} diff --git a/web/core/modules/filter/src/Plugin/migrate/process/d6/FilterFormatPermission.php b/web/core/modules/filter/src/Plugin/migrate/process/d6/FilterFormatPermission.php index 8c7a16016..ae8fb9da6 100644 --- a/web/core/modules/filter/src/Plugin/migrate/process/d6/FilterFormatPermission.php +++ b/web/core/modules/filter/src/Plugin/migrate/process/d6/FilterFormatPermission.php @@ -40,12 +40,16 @@ class FilterFormatPermission extends ProcessPluginBase implements ContainerFacto * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + $migration_plugin_configuration = $configuration + [ + 'migration' => 'd6_filter_format', + ]; + return new static( $configuration, $plugin_id, $plugin_definition, $migration, - $container->get('plugin.manager.migrate.process')->createInstance('migration', ['migration' => 'd6_filter_format'], $migration) + $container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_plugin_configuration, $migration) ); } diff --git a/web/core/modules/filter/tests/src/Kernel/Migrate/d6/FilterFormatPermissionTest.php b/web/core/modules/filter/tests/src/Kernel/Migrate/d6/FilterFormatPermissionTest.php new file mode 100644 index 000000000..80b0c7d81 --- /dev/null +++ b/web/core/modules/filter/tests/src/Kernel/Migrate/d6/FilterFormatPermissionTest.php @@ -0,0 +1,32 @@ +container, [], 'custom_migration', []); + $filterFormatPermissionMigration = FilterFormatPermission::create($this->container, ['migration' => 'custom_filter_format'], 'custom_filter_format', [], $migration); + $migrationPlugin = $this->readAttribute($filterFormatPermissionMigration, 'migrationPlugin'); + $config = $this->readAttribute($migrationPlugin, 'configuration'); + + $this->assertEquals($config['migration'], 'custom_filter_format'); + } + +} diff --git a/web/core/modules/forum/src/Tests/Views/ForumIntegrationTest.php b/web/core/modules/forum/tests/src/Functional/Views/ForumIntegrationTest.php similarity index 92% rename from web/core/modules/forum/src/Tests/Views/ForumIntegrationTest.php rename to web/core/modules/forum/tests/src/Functional/Views/ForumIntegrationTest.php index f5677e41b..19c000012 100644 --- a/web/core/modules/forum/src/Tests/Views/ForumIntegrationTest.php +++ b/web/core/modules/forum/tests/src/Functional/Views/ForumIntegrationTest.php @@ -1,10 +1,10 @@ moduleHandler->alter('hal_relation_uri', $uri, $context); // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This // hook is invoked to maintain backwards compatibility + // @see https://www.drupal.org/node/2830467 $this->moduleHandler->alter('rest_relation_uri', $uri, $context); return $uri; } diff --git a/web/core/modules/hal/src/LinkManager/TypeLinkManager.php b/web/core/modules/hal/src/LinkManager/TypeLinkManager.php index c3a948ff8..51b2de503 100644 --- a/web/core/modules/hal/src/LinkManager/TypeLinkManager.php +++ b/web/core/modules/hal/src/LinkManager/TypeLinkManager.php @@ -73,6 +73,7 @@ class TypeLinkManager extends LinkManagerBase implements TypeLinkManagerInterfac $this->moduleHandler->alter('hal_type_uri', $uri, $context); // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This // hook is invoked to maintain backwards compatibility + // @see https://www.drupal.org/node/2830467 $this->moduleHandler->alter('rest_type_uri', $uri, $context); return $uri; } diff --git a/web/core/modules/hal/tests/modules/hal_test/hal_test.module b/web/core/modules/hal/tests/modules/hal_test/hal_test.module index 8788eaf41..823634587 100644 --- a/web/core/modules/hal/tests/modules/hal_test/hal_test.module +++ b/web/core/modules/hal/tests/modules/hal_test/hal_test.module @@ -27,6 +27,8 @@ function hal_test_hal_relation_uri_alter(&$uri, $context = []) { * Implements hook_rest_type_uri_alter(). * * @deprecated Kept only for BC test coverage, see \Drupal\Tests\hal\Kernel\HalLinkManagerTest::testGetTypeUri(). + * + * @see https://www.drupal.org/node/2830467 */ function hal_test_rest_type_uri_alter(&$uri, $context = []) { if (!empty($context['rest_test'])) { @@ -38,6 +40,8 @@ function hal_test_rest_type_uri_alter(&$uri, $context = []) { * Implements hook_rest_relation_uri_alter(). * * @deprecated Kept only for BC test coverage, see \Drupal\Tests\hal\Kernel\HalLinkManagerTest::testGetRelationUri(). + * + * @see https://www.drupal.org/node/2830467 */ function hal_test_rest_relation_uri_alter(&$uri, $context = []) { if (!empty($context['rest_test'])) { diff --git a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonAnonTest.php b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonAnonTest.php index 0dabde37c..34cfd4be5 100644 --- a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonAnonTest.php +++ b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonAnonTest.php @@ -6,7 +6,7 @@ use Drupal\Tests\rest\Functional\AnonResourceTestTrait; use Drupal\Tests\rest\Functional\EntityResource\ImageStyle\ImageStyleResourceTestBase; /** - * @group rest + * @group hal */ class ImageStyleHalJsonAnonTest extends ImageStyleResourceTestBase { diff --git a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonBasicAuthTest.php b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonBasicAuthTest.php index 2e4d3eb50..61cc149e3 100644 --- a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonBasicAuthTest.php +++ b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonBasicAuthTest.php @@ -6,7 +6,7 @@ use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait; use Drupal\Tests\rest\Functional\EntityResource\ImageStyle\ImageStyleResourceTestBase; /** - * @group rest + * @group hal */ class ImageStyleHalJsonBasicAuthTest extends ImageStyleResourceTestBase { diff --git a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonCookieTest.php b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonCookieTest.php index b0f57b963..aa496535c 100644 --- a/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonCookieTest.php +++ b/web/core/modules/hal/tests/src/Functional/EntityResource/ImageStyle/ImageStyleHalJsonCookieTest.php @@ -6,7 +6,7 @@ use Drupal\Tests\rest\Functional\CookieResourceTestTrait; use Drupal\Tests\rest\Functional\EntityResource\ImageStyle\ImageStyleResourceTestBase; /** - * @group rest + * @group hal */ class ImageStyleHalJsonCookieTest extends ImageStyleResourceTestBase { diff --git a/web/core/modules/image/tests/src/Functional/ImageEffectsTest.php b/web/core/modules/image/tests/src/Functional/ImageEffectsTest.php index e9cb157ab..3207442ab 100644 --- a/web/core/modules/image/tests/src/Functional/ImageEffectsTest.php +++ b/web/core/modules/image/tests/src/Functional/ImageEffectsTest.php @@ -3,7 +3,7 @@ namespace Drupal\Tests\image\Functional; use Drupal\image\Entity\ImageStyle; -use Drupal\system\Tests\Image\ToolkitTestBase; +use Drupal\FunctionalTests\Image\ToolkitTestBase; /** * Tests that the image effects pass parameters to the toolkit correctly. diff --git a/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentSettingsTest.php b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentSettingsTest.php new file mode 100644 index 000000000..a4c7534e5 --- /dev/null +++ b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentSettingsTest.php @@ -0,0 +1,74 @@ + 'article', + 'name' => 'Article', + 'module' => 'node', + 'description' => 'An article, content type.', + 'help' => '', + 'has_title' => 1, + 'title_label' => 'Title', + 'has_body' => 1, + 'body_label' => 'Body', + 'min_word_count' => 0, + 'custom' => 1, + 'modified' => 1, + 'locked' => 0, + 'orig_type' => 'story', + ], + [ + 'type' => 'company', + 'name' => 'Company', + 'module' => 'node', + 'description' => 'Company node type', + 'help' => '', + 'has_title' => 1, + 'title_label' => 'Name', + 'has_body' => 1, + 'body_label' => 'Description', + 'min_word_count' => 0, + 'custom' => 0, + 'modified' => 1, + 'locked' => 0, + 'orig_type' => 'company', + ], + ]; + + foreach ($tests[0]['source_data']['node_type'] as $node_type) { + $tests[0]['expected_data'][] = [ + 'type' => $node_type['type'], + 'language_content_type' => NULL, + 'i18n_lock_node' => 0, + ]; + } + + return $tests; + } + +} diff --git a/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d7/LanguageContentSettingsTest.php b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d7/LanguageContentSettingsTest.php new file mode 100644 index 000000000..39d645081 --- /dev/null +++ b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d7/LanguageContentSettingsTest.php @@ -0,0 +1,72 @@ + 'article', + 'name' => 'Article', + 'base' => 'node_content', + 'module' => 'node', + 'description' => 'Use articles for time-sensitive content like news, press releases or blog posts.', + 'help' => 'Help text for articles', + 'has_title' => 1, + 'title_label' => 'Title', + 'custom' => 1, + 'modified' => 1, + 'locked' => 0, + 'disabled' => 0, + 'orig_type' => 'article', + ], + [ + 'type' => 'blog', + 'name' => 'Blog entry', + 'base' => 'blog', + 'module' => 'blog', + 'description' => 'Use for multi-user blogs. Every user gets a personal blog.', + 'help' => 'Blog away, good sir!', + 'has_title' => 1, + 'title_label' => 'Title', + 'custom' => 0, + 'modified' => 1, + 'locked' => 1, + 'disabled' => 0, + 'orig_type' => 'blog', + ], + ]; + + foreach ($tests[0]['source_data']['node_type'] as $node_type) { + $tests[0]['expected_data'][] = [ + 'type' => $node_type['type'], + 'language_content_type' => NULL, + 'i18n_lock_node' => 0, + ]; + } + + return $tests; + } + +} diff --git a/web/core/modules/layout_discovery/layouts/threecol_33_34_33/threecol_33_34_33.css b/web/core/modules/layout_discovery/layouts/threecol_33_34_33/threecol_33_34_33.css index 29a816fce..7f6511767 100644 --- a/web/core/modules/layout_discovery/layouts/threecol_33_34_33/threecol_33_34_33.css +++ b/web/core/modules/layout_discovery/layouts/threecol_33_34_33/threecol_33_34_33.css @@ -17,8 +17,10 @@ @media screen and (min-width: 40em) { .layout--threecol-33-34-33 > .layout__region--first, - .layout--threecol-33-34-33 > .layout__region--second, .layout--threecol-33-34-33 > .layout__region--third { flex: 0 1 33%; } + .layout--threecol-33-34-33 > .layout__region--second { + flex: 0 1 34%; + } } diff --git a/web/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php b/web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php similarity index 98% rename from web/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php rename to web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php index 479a60046..67c2dfa70 100644 --- a/web/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php +++ b/web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php @@ -1,9 +1,9 @@ drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textareas = $this->xpath('//textarea'); $textarea = current($textareas); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => '', ]; diff --git a/web/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php b/web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php similarity index 97% rename from web/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php rename to web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php index a90dce0c5..4d1b9df2c 100644 --- a/web/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php +++ b/web/core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php @@ -1,8 +1,8 @@ drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textareas = $this->xpath('//textarea'); $textarea = current($textareas); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $message, ]; @@ -100,7 +100,7 @@ class LocaleConfigTranslationTest extends WebTestBase { $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textareas = $this->xpath('//textarea'); $textarea = current($textareas); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => 'D', ]; @@ -143,7 +143,7 @@ class LocaleConfigTranslationTest extends WebTestBase { ]; $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $image_style_label, ]; @@ -175,7 +175,7 @@ class LocaleConfigTranslationTest extends WebTestBase { ]; $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $category_label, ]; diff --git a/web/core/modules/locale/src/Tests/LocaleExportTest.php b/web/core/modules/locale/tests/src/Functional/LocaleExportTest.php similarity index 97% rename from web/core/modules/locale/src/Tests/LocaleExportTest.php rename to web/core/modules/locale/tests/src/Functional/LocaleExportTest.php index 54d36e2bc..05621f6c1 100644 --- a/web/core/modules/locale/src/Tests/LocaleExportTest.php +++ b/web/core/modules/locale/tests/src/Functional/LocaleExportTest.php @@ -1,15 +1,15 @@ get('locale.translation.javascript'); $js_filename = $prefix . '_' . $js_translation_files[$prefix] . '.js'; + $content = $this->getSession()->getPage()->getContent(); // Assert translations JS is included before drupal.js. - $this->assertTrue(strpos($this->content, $js_filename) < strpos($this->content, 'core/misc/drupal.js'), 'Translations are included before Drupal.t.'); + $this->assertTrue(strpos($content, $js_filename) < strpos($content, 'core/misc/drupal.js'), 'Translations are included before Drupal.t.'); } } diff --git a/web/core/modules/locale/src/Tests/LocaleLibraryAlterTest.php b/web/core/modules/locale/tests/src/Functional/LocaleLibraryAlterTest.php similarity index 85% rename from web/core/modules/locale/src/Tests/LocaleLibraryAlterTest.php rename to web/core/modules/locale/tests/src/Functional/LocaleLibraryAlterTest.php index 68996f44a..5425fc5f4 100644 --- a/web/core/modules/locale/src/Tests/LocaleLibraryAlterTest.php +++ b/web/core/modules/locale/tests/src/Functional/LocaleLibraryAlterTest.php @@ -1,9 +1,9 @@ randomMachineName(16); + $name = 'cucurbitaceae'; // This will be the translation of $name. $translation = $this->randomMachineName(16); $translation_to_en = $this->randomMachineName(16); @@ -89,7 +89,7 @@ class LocaleTranslationUiTest extends WebTestBase { // Assume this is the only result, given the random name. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $translation, ]; @@ -112,7 +112,7 @@ class LocaleTranslationUiTest extends WebTestBase { ]; $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $translation_to_en, ]; @@ -155,7 +155,7 @@ class LocaleTranslationUiTest extends WebTestBase { ]; $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => 'Please enter your Llama username.', ]; @@ -189,7 +189,7 @@ class LocaleTranslationUiTest extends WebTestBase { $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); // Assume this is the only result, given the random name. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => '', ]; @@ -248,7 +248,7 @@ class LocaleTranslationUiTest extends WebTestBase { $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $this->randomMachineName(), ]; @@ -309,7 +309,7 @@ class LocaleTranslationUiTest extends WebTestBase { // Find the edit path. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); foreach ($bad_translations as $translation) { $edit = [ $lid => $translation, @@ -317,7 +317,7 @@ class LocaleTranslationUiTest extends WebTestBase { $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); // Check for a form error on the textarea. $form_class = $this->xpath('//form[@id="locale-translate-edit-form"]//textarea/@class'); - $this->assertNotIdentical(FALSE, strpos($form_class[0], 'error'), 'The string was rejected as unsafe.'); + $this->assertContains('error', $form_class[0]->getText(), 'The string was rejected as unsafe.'); $this->assertNoText(t('The string has been saved.'), 'The string was not saved.'); } } @@ -399,7 +399,7 @@ class LocaleTranslationUiTest extends WebTestBase { // Assume this is the only result, given the random name. // We save the lid from the path. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $translation, ]; @@ -503,7 +503,7 @@ class LocaleTranslationUiTest extends WebTestBase { // Submit the translations without changing the translation. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $translation->getString(), ]; @@ -522,7 +522,7 @@ class LocaleTranslationUiTest extends WebTestBase { // Submit the translations with a new translation. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = [ $lid => $this->randomMachineName(100), ]; diff --git a/web/core/modules/locale/src/Tests/LocaleUpdateBase.php b/web/core/modules/locale/tests/src/Functional/LocaleUpdateBase.php similarity index 98% rename from web/core/modules/locale/src/Tests/LocaleUpdateBase.php rename to web/core/modules/locale/tests/src/Functional/LocaleUpdateBase.php index b228a962d..f4c59b287 100644 --- a/web/core/modules/locale/src/Tests/LocaleUpdateBase.php +++ b/web/core/modules/locale/tests/src/Functional/LocaleUpdateBase.php @@ -1,16 +1,16 @@ id()][$index]; } - $stub_row = new Row($values + $migration->getSourceConfiguration(), $source_ids, TRUE); + $stub_row = $this->createStubRow($values + $migration->getSourceConfiguration(), $source_ids); // Do a normal migration with the stub row. $migrate_executable->processRow($stub_row, $process); @@ -257,4 +257,23 @@ class MigrationLookup extends ProcessPluginBase implements ContainerFactoryPlugi } } + /** + * Create a stub row source for later import as stub data. + * + * This simple wrapper of the Row constructor allows sub-classing plugins to + * have more control over the row. + * + * @param array $values + * An array of values to add as properties on the object. + * @param array $source_ids + * An array containing the IDs of the source using the keys as the field + * names. + * + * @return \Drupal\migrate\Row + * The stub row. + */ + protected function createStubRow(array $values, array $source_ids) { + return new Row($values, $source_ids, TRUE); + } + } diff --git a/web/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php b/web/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php index 3d88d777b..bdb287928 100644 --- a/web/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php +++ b/web/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php @@ -11,5 +11,7 @@ instead.', E_USER_DEPRECATED); * * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use * \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface instead. + * + * @see https://www.drupal.org/node/2751897 */ interface MigrateCckFieldPluginManagerInterface extends MigrateFieldPluginManagerInterface { } diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php new file mode 100644 index 000000000..4f1a6036e --- /dev/null +++ b/web/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php @@ -0,0 +1,43 @@ + 'iterator', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + 'plugin' => 'migration_lookup', + 'migration' => 'd6_user', + 'source' => 'uid', + ], + ], + ]; + $migration->setProcessOfProperty($field_name, $process); + } + +} diff --git a/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php index c94870e2f..0003684eb 100644 --- a/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php +++ b/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php @@ -45966,28 +45966,28 @@ $connection->insert('term_data') ->values(array( 'tid' => '1', 'vid' => '1', - 'name' => 'term 1 of vocabulary 1', - 'description' => 'description of term 1 of vocabulary 1', + 'name' => 'zu - term 1 of vocabulary 1', + 'description' => 'zu - description of term 1 of vocabulary 1', 'weight' => '0', - 'language' => '', + 'language' => 'zu', 'trid' => '0', )) ->values(array( 'tid' => '2', 'vid' => '2', - 'name' => 'term 2 of vocabulary 2', - 'description' => 'description of term 2 of vocabulary 2', + 'name' => 'fr - term 2 of vocabulary 2', + 'description' => 'fr - description of term 2 of vocabulary 2', 'weight' => '3', - 'language' => '', + 'language' => 'fr', 'trid' => '0', )) ->values(array( 'tid' => '3', 'vid' => '2', - 'name' => 'term 3 of vocabulary 2', - 'description' => 'description of term 3 of vocabulary 2', + 'name' => 'fr - term 3 of vocabulary 2', + 'description' => 'fr - description of term 3 of vocabulary 2', 'weight' => '4', - 'language' => '', + 'language' => 'fr', 'trid' => '0', )) ->values(array( @@ -46017,6 +46017,15 @@ $connection->insert('term_data') 'language' => '', 'trid' => '0', )) +->values(array( + 'tid' => '7', + 'vid' => '1', + 'name' => 'fr - term 2 of vocabulary 1', + 'description' => 'fr - desc of term 2 vocab 1', + 'weight' => '0', + 'language' => 'fr', + 'trid' => '0', +)) ->execute(); $connection->schema()->createTable('term_hierarchy', array( @@ -46060,6 +46069,10 @@ $connection->insert('term_hierarchy') 'tid' => '4', 'parent' => '0', )) +->values(array( + 'tid' => '7', + 'parent' => '0', +)) ->values(array( 'tid' => '3', 'parent' => '2', @@ -46120,6 +46133,11 @@ $connection->insert('term_node') 'vid' => '1', 'tid' => '1', )) +->values(array( + 'nid' => '1', + 'vid' => '1', + 'tid' => '2', +)) ->values(array( 'nid' => '2', 'vid' => '3', @@ -47632,6 +47650,10 @@ $connection->insert('variable') 'name' => 'i18nstrings_allowed_formats', 'value' => 'a:2:{i:0;i:1;i:1;i:2;}', )) +->values(array( + 'name' => 'i18ntaxonomy_vocabulary', + 'value' => 'a:2:{i:1;s:1:"3";i:2;s:1:"2";}', +)) ->values(array( 'name' => 'i18n_lock_node_article', 'value' => 'i:1;', @@ -48160,7 +48182,7 @@ $connection->insert('vocabulary') 'tags' => '1', 'module' => 'taxonomy', 'weight' => '5', - 'language' => '', + 'language' => 'fr', )) ->values(array( 'vid' => '3', diff --git a/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php index 78fb095e2..711d2add6 100644 --- a/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php +++ b/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php @@ -3426,6 +3426,21 @@ $connection->insert('field_config') 'translatable' => '0', 'deleted' => '0', )) +->values(array( + 'id' => '25', + 'field_name' => 'field_private_file', + 'type' => 'file', + 'module' => 'file', + 'active' => '1', + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => '1', + 'locked' => '0', + 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:13:"display_field";i:0;s:15:"display_default";i:0;s:10:"uri_scheme";s:7:"private";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:29:"field_data_field_private_file";a:3:{s:3:"fid";s:22:"field_private_file_fid";s:7:"display";s:26:"field_private_file_display";s:11:"description";s:30:"field_private_file_description";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:33:"field_revision_field_private_file";a:3:{s:3:"fid";s:22:"field_private_file_fid";s:7:"display";s:26:"field_private_file_display";s:11:"description";s:30:"field_private_file_description";}}}}}s:12:"foreign keys";a:1:{s:3:"fid";a:2:{s:5:"table";s:12:"file_managed";s:7:"columns";a:1:{s:3:"fid";s:3:"fid";}}}s:7:"indexes";a:1:{s:3:"fid";a:1:{i:0;s:3:"fid";}}s:2:"id";s:2:"25";}', + 'cardinality' => '1', + 'translatable' => '0', + 'deleted' => '0', +)) ->execute(); $connection->schema()->createTable('field_config_instance', array( @@ -3837,6 +3852,15 @@ $connection->insert('field_config_instance') 'data' => 'a:7:{s:5:"label";s:14:"Term Reference";s:6:"widget";a:5:{s:6:"weight";s:2:"14";s:4:"type";s:21:"taxonomy_autocomplete";s:6:"module";s:8:"taxonomy";s:6:"active";i:0;s:8:"settings";a:2:{s:4:"size";i:60;s:17:"autocomplete_path";s:21:"taxonomy/autocomplete";}}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:4:{s:5:"label";s:5:"above";s:4:"type";s:6:"hidden";s:6:"weight";s:2:"13";s:8:"settings";a:0:{}}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', 'deleted' => '0', )) +->values(array( + 'id' => '42', + 'field_id' => '25', + 'field_name' => 'field_private_file', + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'data' => 'a:6:{s:5:"label";s:12:"Private file";s:6:"widget";a:5:{s:6:"weight";s:2:"19";s:4:"type";s:12:"file_generic";s:6:"module";s:4:"file";s:6:"active";i:1;s:8:"settings";a:1:{s:18:"progress_indicator";s:8:"throbber";}}s:8:"settings";a:5:{s:14:"file_directory";s:0:"";s:15:"file_extensions";s:3:"txt";s:12:"max_filesize";s:0:"";s:17:"description_field";i:0;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"file_default";s:8:"settings";a:0:{}s:6:"module";s:4:"file";s:6:"weight";i:18;}}s:8:"required";i:0;s:11:"description";s:0:"";}', + 'deleted' => '0', +)) ->execute(); $connection->schema()->createTable('field_data_body', array( @@ -5340,13 +5364,136 @@ $connection->insert('field_data_field_phone') 'bundle' => 'test_content_type', 'deleted' => '0', 'entity_id' => '1', - 'revision_id' => '1', + 'revision_id' => '6', 'language' => 'und', 'delta' => '0', 'field_phone_value' => '99-99-99-99', )) ->execute(); +$connection->schema()->createTable('field_data_field_private_file', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_private_file_fid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_private_file_display' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '1', + 'unsigned' => TRUE, + ), + 'field_private_file_description' => array( + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'normal', + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_private_file_fid' => array( + 'field_private_file_fid', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_data_field_private_file') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_private_file_fid', + 'field_private_file_display', + 'field_private_file_description', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '6', + 'language' => 'und', + 'delta' => '0', + 'field_private_file_fid' => '4', + 'field_private_file_display' => '1', + 'field_private_file_description' => '', +)) +->execute(); + $connection->schema()->createTable('field_data_field_tags', array( 'fields' => array( 'entity_type' => array( @@ -7579,6 +7726,140 @@ $connection->insert('field_revision_field_phone') 'delta' => '0', 'field_phone_value' => '99-99-99-99', )) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '6', + 'language' => 'und', + 'delta' => '0', + 'field_phone_value' => '99-99-99-99', +)) +->execute(); + +$connection->schema()->createTable('field_revision_field_private_file', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_private_file_fid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_private_file_display' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '1', + 'unsigned' => TRUE, + ), + 'field_private_file_description' => array( + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'normal', + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'revision_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_private_file_fid' => array( + 'field_private_file_fid', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_revision_field_private_file') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_private_file_fid', + 'field_private_file_display', + 'field_private_file_description', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '6', + 'language' => 'und', + 'delta' => '0', + 'field_private_file_fid' => '4', + 'field_private_file_display' => '1', + 'field_private_file_description' => '', +)) ->execute(); $connection->schema()->createTable('field_revision_field_tags', array( @@ -8365,6 +8646,16 @@ $connection->insert('file_managed') 'status' => '1', 'timestamp' => '1421727516', )) +->values(array( + 'fid' => '3', + 'uid' => '1', + 'filename' => 'Babylon5.txt', + 'uri' => 'private://Babylon5.txt', + 'filemime' => 'text/plain', + 'filesize' => '4', + 'status' => '1', + 'timestamp' => '1486104045', +)) ->execute(); $connection->schema()->createTable('file_usage', array( @@ -8424,14 +8715,14 @@ $connection->insert('file_usage') 'module' => 'file', 'type' => 'node', 'id' => '1', - 'count' => '2', + 'count' => '3', )) ->values(array( 'fid' => '2', 'module' => 'file', 'type' => 'node', 'id' => '1', - 'count' => '1', + 'count' => '2', )) ->values(array( 'fid' => '2', @@ -8440,6 +8731,13 @@ $connection->insert('file_usage') 'id' => '2', 'count' => '1', )) +->values(array( + 'fid' => '3', + 'module' => 'file', + 'type' => 'node', + 'id' => '1', + 'count' => '1', +)) ->execute(); $connection->schema()->createTable('filter', array( @@ -43862,7 +44160,7 @@ $connection->insert('variable') )) ->values(array( 'name' => 'file_private_path', - 'value' => 's:0:"";', + 'value' => 's:21:"sites/default/private";', )) ->values(array( 'name' => 'file_public_path', diff --git a/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php b/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php index 8d9fd8f0a..12dc5c1c8 100644 --- a/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php +++ b/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php @@ -104,6 +104,9 @@ class MigrateUpgradeImportBatch { // @todo Find a way to avoid this in https://www.drupal.org/node/2804611. if ($definition['destination']['plugin'] === 'entity:file') { // Make sure we have a single trailing slash. + if ($definition['source']['plugin'] === 'd7_file_private') { + $configuration['source']['constants']['source_base_path'] = rtrim($config['source_private_file_path'], '/') . '/'; + } $configuration['source']['constants']['source_base_path'] = rtrim($config['source_base_path'], '/') . '/'; } diff --git a/web/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/web/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php index 27e014601..c87247eb3 100644 --- a/web/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ b/web/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php @@ -250,6 +250,10 @@ class MigrateUpgradeForm extends ConfirmFormBase { 'source_module' => 'file', 'destination_module' => 'file', ], + 'd7_file_private' => [ + 'source_module' => 'file', + 'destination_module' => 'file', + ], 'd6_filter_format' => [ 'source_module' => 'filter', 'destination_module' => 'filter', @@ -530,10 +534,18 @@ class MigrateUpgradeForm extends ConfirmFormBase { 'source_module' => 'taxonomy', 'destination_module' => 'taxonomy', ], + 'd6_taxonomy_term_translation' => [ + 'source_module' => 'i18n', + 'destination_module' => 'taxonomy', + ], 'd6_taxonomy_vocabulary' => [ 'source_module' => 'taxonomy', 'destination_module' => 'taxonomy', ], + 'd6_taxonomy_vocabulary_translation' => [ + 'source_module' => 'i18n', + 'destination_module' => 'taxonomy', + ], 'd6_term_node' => [ 'source_module' => 'taxonomy', 'destination_module' => 'taxonomy', @@ -877,6 +889,15 @@ class MigrateUpgradeForm extends ConfirmFormBase { $default_options = []; + + $form['version'] = [ + '#type' => 'radios', + '#default_value' => 7, + '#title' => $this->t('Drupal version of the source site'), + '#options' => [6 => $this->t('Drupal 6'), 7 => $this->t('Drupal 7')], + '#required' => TRUE, + ]; + $form['database'] = [ '#type' => 'details', '#title' => $this->t('Source database'), @@ -930,10 +951,38 @@ class MigrateUpgradeForm extends ConfirmFormBase { '#title' => $this->t('Source files'), '#open' => TRUE, ]; - $form['source']['source_base_path'] = [ + $form['source']['d6_source_base_path'] = [ '#type' => 'textfield', '#title' => $this->t('Files directory'), '#description' => $this->t('To import files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'), + '#states' => [ + 'visible' => [ + ':input[name="version"]' => ['value' => 6], + ], + ], + ]; + + $form['source']['source_base_path'] = [ + '#type' => 'textfield', + '#title' => $this->t('Public files directory'), + '#description' => $this->t('To import public files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'), + '#states' => [ + 'visible' => [ + ':input[name="version"]' => ['value' => 7], + ], + ], + ]; + + $form['source']['source_private_file_path'] = [ + '#type' => 'textfield', + '#title' => $this->t('Private file directory'), + '#default_value' => '', + '#description' => $this->t('To import private files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot).'), + '#states' => [ + 'visible' => [ + ':input[name="version"]' => ['value' => 7], + ], + ], ]; $form['actions'] = ['#type' => 'actions']; @@ -984,6 +1033,12 @@ class MigrateUpgradeForm extends ConfirmFormBase { if (!$version) { $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.')); } + elseif ($version != $form_state->getValue('version')) { + $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database is Drupal version @version but version @selected was selected.', [ + '@version' => $version, + '@selected' => $form_state->getValue('version'), + ])); + } else { $this->createDatabaseStateSettings($database, $version); $migrations = $this->getMigrations('migrate_drupal_' . $version, $version); @@ -1001,6 +1056,7 @@ class MigrateUpgradeForm extends ConfirmFormBase { // Store the retrieved migration IDs in form storage. $form_state->set('migrations', $migration_array); $form_state->set('source_base_path', $form_state->getValue('source_base_path')); + $form_state->set('source_private_file_path', $form_state->getValue('source_private_file_path')); // Store the retrived system data in form storage. $form_state->set('system_data', $system_data); diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php b/web/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php index b635f2ab2..4aea3f1d0 100644 --- a/web/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php +++ b/web/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php @@ -2,6 +2,8 @@ namespace Drupal\migrate_drupal_ui\Tests; +@trigger_error('\Drupal\migrate_drupal_ui\Tests\MigrateUpgradeTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeTestBase instead.', E_USER_DEPRECATED); + use Drupal\Core\Database\Database; use Drupal\migrate\Plugin\MigrateIdMapInterface; use Drupal\migrate_drupal\MigrationConfigurationTrait; @@ -9,6 +11,9 @@ use Drupal\simpletest\WebTestBase; /** * Provides a base class for testing migration upgrades in the UI. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use + * \Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeTestBase instead. */ abstract class MigrateUpgradeTestBase extends WebTestBase { use MigrationConfigurationTrait; diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/MigrateAccessTest.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateAccessTest.php similarity index 82% rename from web/core/modules/migrate_drupal_ui/src/Tests/MigrateAccessTest.php rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateAccessTest.php index 04f2048ea..3c475e206 100644 --- a/web/core/modules/migrate_drupal_ui/src/Tests/MigrateAccessTest.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateAccessTest.php @@ -1,15 +1,15 @@ createMigrationConnection(); + $this->sourceDatabase = Database::getConnection('default', 'migrate_drupal_ui'); + + // Log in as user 1. Migrations in the UI can only be performed as user 1. + $this->drupalLogin($this->rootUser); + } + + /** + * Loads a database fixture into the source database connection. + * + * @param string $path + * Path to the dump file. + */ + protected function loadFixture($path) { + $default_db = Database::getConnection()->getKey(); + Database::setActiveConnection($this->sourceDatabase->getKey()); + + if (substr($path, -3) == '.gz') { + $path = 'compress.zlib://' . $path; + } + require $path; + + Database::setActiveConnection($default_db); + } + + /** + * Changes the database connection to the prefixed one. + * + * @todo Remove when we don't use global. https://www.drupal.org/node/2552791 + */ + protected function createMigrationConnection() { + $connection_info = Database::getConnectionInfo('default')['default']; + if ($connection_info['driver'] === 'sqlite') { + // Create database file in the test site's public file directory so that + // \Drupal\simpletest\TestBase::restoreEnvironment() will delete this once + // the test is complete. + $file = $this->publicFilesDirectory . '/' . $this->testId . '-migrate.db.sqlite'; + touch($file); + $connection_info['database'] = $file; + $connection_info['prefix'] = ''; + } + else { + $prefix = is_array($connection_info['prefix']) ? $connection_info['prefix']['default'] : $connection_info['prefix']; + // Simpletest uses fixed length prefixes. Create a new prefix for the + // source database. Adding to the end of the prefix ensures that + // \Drupal\simpletest\TestBase::restoreEnvironment() will remove the + // additional tables. + $connection_info['prefix'] = $prefix . '0'; + } + + Database::addConnectionInfo('migrate_drupal_ui', 'default', $connection_info); + } + + /** + * {@inheritdoc} + */ + protected function tearDown() { + Database::removeConnection('migrate_drupal_ui'); + parent::tearDown(); + } + + /** + * Executes all steps of migrations upgrade. + */ + public function testMigrateUpgrade() { + $connection_options = $this->sourceDatabase->getConnectionOptions(); + $this->drupalGet('/upgrade'); + $this->assertText('Upgrade a site by importing it into a clean and empty new install of Drupal 8. You will lose any existing configuration once you import your site into it. See the online documentation for Drupal site upgrades for more detailed information.'); + + $this->drupalPostForm(NULL, [], t('Continue')); + $this->assertText('Provide credentials for the database of the Drupal site you want to upgrade.'); + $this->assertFieldByName('mysql[host]'); + + $driver = $connection_options['driver']; + $connection_options['prefix'] = $connection_options['prefix']['default']; + + // Use the driver connection form to get the correct options out of the + // database settings. This supports all of the databases we test against. + $drivers = drupal_get_database_types(); + $form = $drivers[$driver]->getFormOptions($connection_options); + $connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']); + $version = $this->getLegacyDrupalVersion($this->sourceDatabase); + $edit = [ + $driver => $connection_options, + 'source_base_path' => $this->getSourceBasePath(), + 'source_private_file_path' => $this->getSourceBasePath(), + 'version' => $version, + ]; + if (count($drivers) !== 1) { + $edit['driver'] = $driver; + } + $edits = $this->translatePostValues($edit); + + // Ensure submitting the form with invalid database credentials gives us a + // nice warning. + $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); + $this->assertText('Resolve the issue below to continue the upgrade.'); + + $this->drupalPostForm(NULL, $edits, t('Review upgrade')); + $this->assertResponse(200); + $this->assertText('Are you sure?'); + $this->drupalPostForm(NULL, [], t('Perform upgrade')); + $this->assertText(t('Congratulations, you upgraded Drupal!')); + + // Have to reset all the statics after migration to ensure entities are + // loadable. + $this->resetAll(); + + $expected_counts = $this->getEntityCounts(); + foreach (array_keys(\Drupal::entityTypeManager() + ->getDefinitions()) as $entity_type) { + $real_count = \Drupal::entityQuery($entity_type)->count()->execute(); + $expected_count = isset($expected_counts[$entity_type]) ? $expected_counts[$entity_type] : 0; + $this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count."); + } + + $plugin_manager = \Drupal::service('plugin.manager.migration'); + /** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */ + $all_migrations = $plugin_manager->createInstancesByTag('Drupal ' . $version); + foreach ($all_migrations as $migration) { + $id_map = $migration->getIdMap(); + foreach ($id_map as $source_id => $map) { + // Convert $source_id into a keyless array so that + // \Drupal\migrate\Plugin\migrate\id_map\Sql::getSourceHash() works as + // expected. + $source_id_values = array_values(unserialize($source_id)); + $row = $id_map->getRowBySource($source_id_values); + $destination = serialize($id_map->currentDestination()); + $message = "Migration of $source_id to $destination as part of the {$migration->id()} migration. The source row status is " . $row['source_row_status']; + // A completed migration should have maps with + // MigrateIdMapInterface::STATUS_IGNORED or + // MigrateIdMapInterface::STATUS_IMPORTED. + if ($row['source_row_status'] == MigrateIdMapInterface::STATUS_FAILED || $row['source_row_status'] == MigrateIdMapInterface::STATUS_NEEDS_UPDATE) { + $this->fail($message); + } + else { + $this->pass($message); + } + } + } + \Drupal::service('module_installer')->install(['forum']); + \Drupal::service('module_installer')->install(['book']); + } + + /** + * Transforms a nested array into a flat array suitable for BrowserTestBase::drupalPostForm(). + * + * @param array $values + * A multi-dimensional form values array to convert. + * + * @return array + * The flattened $edit array suitable for BrowserTestBase::drupalPostForm(). + */ + protected function translatePostValues(array $values) { + $edit = []; + // The easiest and most straightforward way to translate values suitable for + // BrowserTestBase::drupalPostForm() is to actually build the POST data string + // and convert the resulting key/value pairs back into a flat array. + $query = http_build_query($values); + foreach (explode('&', $query) as $item) { + list($key, $value) = explode('=', $item); + $edit[urldecode($key)] = urldecode($value); + } + return $edit; + } + + /** + * Gets the source base path for the concrete test. + * + * @return string + * The source base path. + */ + abstract protected function getSourceBasePath(); + + /** + * Gets the expected number of entities per entity type after migration. + * + * @return int[] + * An array of expected counts keyed by entity type ID. + */ + abstract protected function getEntityCounts(); + +} diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php similarity index 90% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php index 48d3d8d99..0578675c0 100644 --- a/web/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php @@ -1,8 +1,8 @@ 1, 'action' => 22, 'menu' => 8, - 'taxonomy_term' => 6, + 'taxonomy_term' => 7, 'taxonomy_vocabulary' => 6, 'tour' => 4, 'user' => 7, @@ -83,7 +83,7 @@ class MigrateUpgrade6Test extends MigrateUpgradeTestBase { // Ensure migrated users can log in. $user = User::load(2); - $user->pass_raw = 'john.doe_pass'; + $user->passRaw = 'john.doe_pass'; $this->drupalLogin($user); } diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/html-1.txt b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/html-1.txt similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/html-1.txt rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/html-1.txt diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-1.png b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-1.png similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-1.png rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-1.png diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-2.jpg b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-2.jpg similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-2.jpg rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-2.jpg diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.gif b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.gif similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.gif rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.gif diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.jpg b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.jpg similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.jpg rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.jpg diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.png b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.png similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/core/modules/simpletest/files/image-test.png rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/core/modules/simpletest/files/image-test.png diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d6/files/tmp/some-temp-file.jpg b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/tmp/some-temp-file.jpg similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d6/files/tmp/some-temp-file.jpg rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/files/tmp/some-temp-file.jpg diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php similarity index 86% rename from web/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php index 94a42e2c9..2917b163c 100644 --- a/web/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php @@ -1,8 +1,8 @@ 4, 'contact_form' => 3, 'editor' => 2, - 'field_config' => 52, - 'field_storage_config' => 39, - 'file' => 2, + 'field_config' => 53, + 'field_storage_config' => 40, + 'file' => 3, 'filter_format' => 7, 'image_style' => 6, 'language_content_settings' => 2, @@ -84,7 +89,7 @@ class MigrateUpgrade7Test extends MigrateUpgradeTestBase { // Ensure migrated users can log in. $user = User::load(2); - $user->pass_raw = 'a password'; + $user->passRaw = 'a password'; $this->drupalLogin($user); } diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d7/files/sites/default/files/cube.jpeg b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/files/cube.jpeg similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d7/files/sites/default/files/cube.jpeg rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/files/cube.jpeg diff --git a/web/core/modules/migrate_drupal_ui/src/Tests/d7/files/sites/default/files/ds9.txt b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/files/ds9.txt similarity index 100% rename from web/core/modules/migrate_drupal_ui/src/Tests/d7/files/sites/default/files/ds9.txt rename to web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/files/ds9.txt diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/private/Babylon5.txt b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/private/Babylon5.txt new file mode 100644 index 000000000..6a7e45274 --- /dev/null +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/files/sites/default/private/Babylon5.txt @@ -0,0 +1 @@ +*** diff --git a/web/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php b/web/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php index b480f899d..ce4ce76e9 100644 --- a/web/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php +++ b/web/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php @@ -95,6 +95,10 @@ class MigrateNodeTest extends MigrateNodeTestBase { $this->assertSame('Klingon Empire', $node->field_company[0]->entity->label()); $this->assertSame('Romulan Empire', $node->field_company[1]->entity->label()); + // Test that user reference field values were migrated. + $this->assertCount(1, $node->field_commander); + $this->assertSame('joe.roe', $node->field_commander[0]->entity->getUsername()); + $node = Node::load(2); $this->assertIdentical('Test title rev 3', $node->getTitle()); $this->assertIdentical('test rev 3', $node->body->value); diff --git a/web/core/modules/outside_in/css/outside_in.motion.css b/web/core/modules/outside_in/css/outside_in.motion.css index 3c86aca36..64a2ca2ff 100644 --- a/web/core/modules/outside_in/css/outside_in.motion.css +++ b/web/core/modules/outside_in/css/outside_in.motion.css @@ -26,19 +26,3 @@ -moz-transition: all .7s ease; transition: all .7s ease; } - -/* Transition the position of the toolbar. */ -.toolbar-fixed, -.toolbar-tray-open { - -webkit-transition: all .5s ease; - -moz-transition: all .5s ease; - transition: all .5s ease; -} - -/* Transition the administration tray. -#toolbar-administration, -#toolbar-administration * { - -webkit-transition: all .7s ease; - -moz-transition: all .7s ease; - transition: all .7s ease; -}*/ diff --git a/web/core/modules/outside_in/css/outside_in.theme.css b/web/core/modules/outside_in/css/outside_in.theme.css index 011d198da..235631397 100644 --- a/web/core/modules/outside_in/css/outside_in.theme.css +++ b/web/core/modules/outside_in/css/outside_in.theme.css @@ -9,7 +9,7 @@ /* Style the edit mode toolbar and tabs. */ #toolbar-bar.js-outside-in-edit-mode { - background-color: #fff; + background-image: linear-gradient(to bottom,#0c97ed,#1f86c7); } .js-outside-in-edit-mode .toolbar-item:not(.toolbar-icon-edit) { color: #999; diff --git a/web/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php b/web/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php index 9989d91f6..2371483ed 100644 --- a/web/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php +++ b/web/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php @@ -11,6 +11,11 @@ use Drupal\Core\Ajax\OpenDialogCommand; */ class OpenOffCanvasDialogCommand extends OpenDialogCommand { + /** + * The dialog width to use if none is provided. + */ + const DEFAULT_DIALOG_WIDTH = 300; + /** * Constructs an OpenOffCanvasDialogCommand object. * @@ -42,6 +47,12 @@ class OpenOffCanvasDialogCommand extends OpenDialogCommand { // @todo drupal.ajax.js does not respect drupalAutoButtons properly, pass an // empty set of buttons until https://www.drupal.org/node/2793343 is in. $this->dialogOptions['buttons'] = []; + // If no width option is provided then use the default width to avoid the + // dialog staying at the width of the previous instance when opened + // more than once, with different widths, on a single page. + if (!isset($this->dialogOptions['width'])) { + $this->dialogOptions['width'] = static::DEFAULT_DIALOG_WIDTH; + } } /** diff --git a/web/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php b/web/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php index 4e0f081fb..f97f79ae0 100644 --- a/web/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php +++ b/web/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php @@ -44,7 +44,7 @@ class BlockEntityOffCanvasForm extends BlockForm { } $form['advanced_link'] = [ '#type' => 'link', - '#title' => $this->t('Advanced options'), + '#title' => $this->t('Advanced block options'), '#url' => $this->entity->toUrl('edit-form', ['query' => $query]), '#weight' => 1000, ]; @@ -52,6 +52,18 @@ class BlockEntityOffCanvasForm extends BlockForm { // Remove the ID and region elements. unset($form['id'], $form['region'], $form['settings']['admin_label']); + if (isset($form['settings']['label_display']) && isset($form['settings']['label'])) { + // Only show the label input if the label will be shown on the page. + $form['settings']['label_display']['#weight'] = -100; + $form['settings']['label']['#states']['visible'] = [ + ':input[name="settings[label_display]"]' => ['checked' => TRUE], + ]; + + // Relabel to "Block title" because on the front-end this may be confused + // with page title. + $form['settings']['label']['#title'] = $this->t("Block title"); + $form['settings']['label_display']['#title'] = $this->t("Display block title"); + } return $form; } diff --git a/web/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php b/web/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php index 41d66dde3..e2b451e1a 100644 --- a/web/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php +++ b/web/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php @@ -46,6 +46,7 @@ class OffCanvasDialogTest extends AjaxTestBase { 'draggable' => FALSE, 'drupalAutoButtons' => FALSE, 'buttons' => [], + 'width' => 300, ], 'effect' => 'fade', 'speed' => 1000, diff --git a/web/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig b/web/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig index b224deb93..11c7f5311 100644 --- a/web/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig +++ b/web/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig @@ -5,7 +5,13 @@ * * For consistent wrapping to {{ page }} render in all themes. The * "data-off-canvas-main-canvas" attribute is required by the off-canvas dialog. - * It cannot be removed without breaking the off-canvas dialog functionality. + * This is used by the outside_in/drupal.off_canvas library to select the + * "main canvas" page element as opposed to the "off canvas" which is the tray + * itself. The "main canvas" element must be resized according to the width of + * the "off canvas" tray so that no portion of the "main canvas" is obstructed + * by the tray. The tray can vary in width when opened and can be resized by the + * user. The "data-off-canvas-main-canvas" attribute cannot be removed without + * breaking the off-canvas dialog functionality. * * Available variables: * - children: Contains the child elements of the page. diff --git a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php index 3254ca981..94c18f039 100644 --- a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php +++ b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php @@ -63,7 +63,11 @@ class OffCanvasTest extends OutsideInJavascriptTestBase { $this->assertEquals('', $header_text); $style = $page->find('css', '.ui-dialog-off-canvas')->getAttribute('style'); - self::assertTrue(strstr($style, 'width: 555px;') !== FALSE, 'Dialog width respected.'); + $this->assertTrue(strstr($style, 'width: 555px;') !== FALSE, 'Dialog width respected.'); + $page->clickLink("Click Me 1!"); + $this->waitForOffCanvasToOpen(); + $style = $page->find('css', '.ui-dialog-off-canvas')->getAttribute('style'); + $this->assertTrue(strstr($style, 'width: 555px;') === FALSE, 'Dialog width reset to default.'); } else { // Check that header is correct. diff --git a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php index a5eacc5c5..313e12dc0 100644 --- a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php +++ b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php @@ -16,6 +16,8 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { const TOOLBAR_EDIT_LINK_SELECTOR = '#toolbar-bar div.contextual-toolbar-tab button'; + const LABEL_INPUT_SELECTOR = 'input[data-drupal-selector="edit-settings-label"]'; + /** * {@inheritdoc} */ @@ -83,7 +85,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->waitForNoElement("#toolbar-administration a.is-active"); } $page->find('css', $toolbar_item)->click(); - $web_assert->waitForElementVisible('css', "{$toolbar_item}.is-active"); + $this->assertElementVisibleAfterWait('css', "{$toolbar_item}.is-active"); } $this->enableEditMode(); if (isset($toolbar_item)) { @@ -92,9 +94,15 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->openBlockForm($block_selector); switch ($block_plugin) { case 'system_powered_by_block': + // Confirm "Display Title" is not checked. + $web_assert->checkboxNotChecked('settings[label_display]'); + // Confirm Title is not visible. + $this->assertEquals($this->isLabelInputVisible(), FALSE, 'Label is not visible'); + $page->checkField('settings[label_display]'); + $this->assertEquals($this->isLabelInputVisible(), TRUE, 'Label is visible'); // Fill out form, save the form. $page->fillField('settings[label]', $new_page_text); - $page->checkField('settings[label_display]'); + break; case 'system_branding_block': @@ -195,8 +203,19 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { */ protected function assertOffCanvasBlockFormIsValid() { $web_assert = $this->assertSession(); + // Confirm that Block title display label has been changed. + $web_assert->elementTextContains('css', '.form-item-settings-label-display label', 'Display block title'); + // Confirm Block title label is shown if checkbox is checked. + if ($this->getSession()->getPage()->find('css', 'input[name="settings[label_display]"]')->isChecked()) { + $this->assertEquals($this->isLabelInputVisible(), TRUE, 'Label is visible'); + $web_assert->elementTextContains('css', '.form-item-settings-label label', 'Block title'); + } + else { + $this->assertEquals($this->isLabelInputVisible(), FALSE, 'Label is not visible'); + } + // Check that common block form elements exist. - $web_assert->elementExists('css', 'input[data-drupal-selector="edit-settings-label"]'); + $web_assert->elementExists('css', static::LABEL_INPUT_SELECTOR); $web_assert->elementExists('css', 'input[data-drupal-selector="edit-settings-label-display"]'); // Check that advanced block form elements do not exist. $web_assert->elementNotExists('css', 'input[data-drupal-selector="edit-visibility-request-path-pages"]'); @@ -257,7 +276,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->drupalGet('node/' . $node->id()); // Waiting for Toolbar module. // @todo Remove the hack after https://www.drupal.org/node/2542050. - $web_assert->waitForElementVisible('css', '.toolbar-fixed'); + $this->assertElementVisibleAfterWait('css', '.toolbar-fixed'); // Waiting for Toolbar animation. $web_assert->assertWaitOnAjaxRequest(); // The 2nd page load we should already be in edit mode. @@ -266,7 +285,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { } // In Edit mode clicking field should open QuickEdit toolbar. $page->find('css', $body_selector)->click(); - $web_assert->waitForElementVisible('css', $quick_edit_selector); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); $this->disableEditMode(); // Exiting Edit mode should close QuickEdit toolbar. @@ -277,7 +296,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->enableEditMode(); $this->openBlockForm($block_selector); $page->find('css', $body_selector)->click(); - $web_assert->waitForElementVisible('css', $quick_edit_selector); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); // Off-canvas dialog should be closed when opening QuickEdit toolbar. $this->waitForOffCanvasToClose(); @@ -291,7 +310,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->disableEditMode(); // Open QuickEdit toolbar before going into Edit mode. $this->clickContextualLink($node_selector, "Quick edit"); - $web_assert->waitForElementVisible('css', $quick_edit_selector); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); // Open off-canvas and enter Edit mode via contextual link. $this->clickContextualLink($block_selector, "Quick edit"); $this->waitForOffCanvasToOpen(); @@ -300,7 +319,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { // Open QuickEdit toolbar via contextual link while in Edit mode. $this->clickContextualLink($node_selector, "Quick edit", FALSE); $this->waitForOffCanvasToClose(); - $web_assert->waitForElementVisible('css', $quick_edit_selector); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); $this->disableEditMode(); } } @@ -469,4 +488,14 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { return '#block-' . $block->id(); } + /** + * Determines if the label input is visible. + * + * @return bool + * TRUE if the label is visible, FALSE if it is not. + */ + protected function isLabelInputVisible() { + return $this->getSession()->getPage()->find('css', static::LABEL_INPUT_SELECTOR)->isVisible(); + } + } diff --git a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php index 2dcc40fb4..129aaec7e 100644 --- a/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php +++ b/web/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php @@ -42,7 +42,7 @@ abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { protected function waitForOffCanvasToOpen() { $web_assert = $this->assertSession(); $web_assert->assertWaitOnAjaxRequest(); - $web_assert->waitForElementVisible('css', '#drupal-off-canvas'); + $this->assertElementVisibleAfterWait('css', '#drupal-off-canvas'); } /** @@ -125,7 +125,7 @@ abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { $web_assert = $this->assertSession(); // Waiting for Toolbar module. // @todo Remove the hack after https://www.drupal.org/node/2542050. - $web_assert->waitForElementVisible('css', '.toolbar-fixed'); + $this->assertElementVisibleAfterWait('css', '.toolbar-fixed'); // Waiting for Toolbar animation. $web_assert->assertWaitOnAjaxRequest(); } @@ -140,4 +140,19 @@ abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { return ['bartik', 'stark', 'classy', 'stable']; } + /** + * Asserts the specified selector is visible after a wait. + * + * @param string $selector + * The selector engine name. See ElementInterface::findAll() for the + * supported selectors. + * @param string|array $locator + * The selector locator. + * @param int $timeout + * (Optional) Timeout in milliseconds, defaults to 10000. + */ + protected function assertElementVisibleAfterWait($selector, $locator, $timeout = 10000) { + $this->assertNotEmpty($this->assertSession()->waitForElementVisible($selector, $locator, $timeout)); + } + } diff --git a/web/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php b/web/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php index 92103b401..d822415d6 100644 --- a/web/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php +++ b/web/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php @@ -31,6 +31,7 @@ class OpenOffCanvasDialogCommandTest extends UnitTestCase { 'draggable' => FALSE, 'drupalAutoButtons' => FALSE, 'buttons' => [], + 'width' => 300, ], 'effect' => 'fade', 'speed' => 1000, diff --git a/web/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php b/web/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php index 41a03657a..629c4aa81 100644 --- a/web/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php +++ b/web/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php @@ -3,7 +3,7 @@ namespace Drupal\Tests\rdf\Functional; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\taxonomy\Tests\TaxonomyTestBase; +use Drupal\Tests\taxonomy\Functional\TaxonomyTestBase; /** * Tests RDFa markup generation for taxonomy term fields. diff --git a/web/core/modules/rdf/tests/src/Functional/TaxonomyAttributesTest.php b/web/core/modules/rdf/tests/src/Functional/TaxonomyAttributesTest.php index ea74ce5c2..346ffb7eb 100644 --- a/web/core/modules/rdf/tests/src/Functional/TaxonomyAttributesTest.php +++ b/web/core/modules/rdf/tests/src/Functional/TaxonomyAttributesTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\rdf\Functional; -use Drupal\taxonomy\Tests\TaxonomyTestBase; +use Drupal\Tests\taxonomy\Functional\TaxonomyTestBase; /** * Tests the RDFa markup of Taxonomy terms. diff --git a/web/core/modules/rest/config/schema/rest.schema.yml b/web/core/modules/rest/config/schema/rest.schema.yml index 5f181c9cb..98b35ae6f 100644 --- a/web/core/modules/rest/config/schema/rest.schema.yml +++ b/web/core/modules/rest/config/schema/rest.schema.yml @@ -4,6 +4,7 @@ rest.settings: label: 'REST settings' mapping: # @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. + # @see https://www.drupal.org/node/2830467 link_domain: type: string label: 'Domain of the relation' diff --git a/web/core/modules/rest/rest.api.php b/web/core/modules/rest/rest.api.php index ac601072b..6c09bbff5 100644 --- a/web/core/modules/rest/rest.api.php +++ b/web/core/modules/rest/rest.api.php @@ -34,6 +34,8 @@ function hook_rest_resource_alter(&$definitions) { * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. Use * hook_serialization_type_uri_alter() instead. This exists solely for BC. * + * @see https://www.drupal.org/node/2830467 + * * Modules may wish to alter the type URI generated for a resource based on the * context of the serializer/normalizer operation. * @@ -61,6 +63,8 @@ function hook_rest_type_uri_alter(&$uri, $context = []) { * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. Use * hook_serialization_relation_uri_alter() instead. This exists solely for BC. * + * @see https://www.drupal.org/node/2830467 + * * Modules may wish to alter the relation URI generated for a resource based on * the context of the serializer/normalizer operation. * diff --git a/web/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php b/web/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php index f9343f40c..e52145919 100644 --- a/web/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php +++ b/web/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\ConfigurableLinkManagerInterface as MovedConfigurable /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ interface ConfigurableLinkManagerInterface extends MovedConfigurableLinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/LinkManager.php b/web/core/modules/rest/src/LinkManager/LinkManager.php index 4cb8384f6..4586c62ec 100644 --- a/web/core/modules/rest/src/LinkManager/LinkManager.php +++ b/web/core/modules/rest/src/LinkManager/LinkManager.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\LinkManager as MovedLinkManager; /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ class LinkManager extends MovedLinkManager implements LinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/LinkManagerBase.php b/web/core/modules/rest/src/LinkManager/LinkManagerBase.php index 13f700422..85eb7b70a 100644 --- a/web/core/modules/rest/src/LinkManager/LinkManagerBase.php +++ b/web/core/modules/rest/src/LinkManager/LinkManagerBase.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\LinkManagerBase as MovedLinkManagerBase; /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ abstract class LinkManagerBase extends MovedLinkManagerBase {} diff --git a/web/core/modules/rest/src/LinkManager/LinkManagerInterface.php b/web/core/modules/rest/src/LinkManager/LinkManagerInterface.php index 15852a59d..9f5d2f2d2 100644 --- a/web/core/modules/rest/src/LinkManager/LinkManagerInterface.php +++ b/web/core/modules/rest/src/LinkManager/LinkManagerInterface.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\LinkManagerInterface as MovedLinkManagerInterface; /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ interface LinkManagerInterface extends MovedLinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/RelationLinkManager.php b/web/core/modules/rest/src/LinkManager/RelationLinkManager.php index 8a5d49d5a..6690e2100 100644 --- a/web/core/modules/rest/src/LinkManager/RelationLinkManager.php +++ b/web/core/modules/rest/src/LinkManager/RelationLinkManager.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\RelationLinkManager as MovedLinkRelationManager; /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ class RelationLinkManager extends MovedLinkRelationManager implements RelationLinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php b/web/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php index c9a89388f..c2eec3461 100644 --- a/web/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php +++ b/web/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\RelationLinkManagerInterface as MovedRelationLinkMana /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ interface RelationLinkManagerInterface extends MovedRelationLinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/TypeLinkManager.php b/web/core/modules/rest/src/LinkManager/TypeLinkManager.php index 7c81a2582..6d7ba03ec 100644 --- a/web/core/modules/rest/src/LinkManager/TypeLinkManager.php +++ b/web/core/modules/rest/src/LinkManager/TypeLinkManager.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\TypeLinkManager as MovedTypeLinkManager; /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ class TypeLinkManager extends MovedTypeLinkManager implements TypeLinkManagerInterface {} diff --git a/web/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php b/web/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php index 85407fff6..9a37049e2 100644 --- a/web/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php +++ b/web/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php @@ -7,5 +7,7 @@ use Drupal\hal\LinkManager\TypeLinkManagerInterface as MovedTypeLinkManagerInter /** * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has * been moved to the hal module. This exists solely for BC. + * + * @see https://www.drupal.org/node/2830467 */ interface TypeLinkManagerInterface extends MovedTypeLinkManagerInterface {} diff --git a/web/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php b/web/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php index 4aa46b209..3ba73331e 100644 --- a/web/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php +++ b/web/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php @@ -40,6 +40,8 @@ class ResourcePluginManager extends DefaultPluginManager { * @deprecated in Drupal 8.2.0. * Use Drupal\rest\Plugin\Type\ResourcePluginManager::createInstance() * instead. + * + * @see https://www.drupal.org/node/2874934 */ public function getInstance(array $options){ if (isset($options['id'])) { diff --git a/web/core/modules/rest/src/RestServiceProvider.php b/web/core/modules/rest/src/RestServiceProvider.php index ca6b14b76..e705de417 100644 --- a/web/core/modules/rest/src/RestServiceProvider.php +++ b/web/core/modules/rest/src/RestServiceProvider.php @@ -27,18 +27,21 @@ class RestServiceProvider implements ServiceProviderInterface { if (isset($modules['hal'])) { // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. // Use hal.link_manager instead. + // @see https://www.drupal.org/node/2830467 $service_definition = new DefinitionDecorator(new Reference('hal.link_manager')); $service_definition->setClass(LinkManager::class); $container->setDefinition('rest.link_manager', $service_definition); // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. // Use hal.link_manager.type instead. + // @see https://www.drupal.org/node/2830467 $service_definition = new DefinitionDecorator(new Reference('hal.link_manager.type')); $service_definition->setClass(TypeLinkManager::class); $container->setDefinition('rest.link_manager.type', $service_definition); // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. // Use hal.link_manager.relation instead. + // @see https://www.drupal.org/node/2830467 $service_definition = new DefinitionDecorator(new Reference('hal.link_manager.relation')); $service_definition->setClass(RelationLinkManager::class); $container->setDefinition('rest.link_manager.relation', $service_definition); diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php b/web/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php index 8355f86cc..43a0e3d05 100644 --- a/web/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php @@ -328,4 +328,37 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase { } } + /** + * Tests POSTing a comment with and without 'skip comment approval' + */ + public function testPostSkipCommentApproval() { + $this->initAuthentication(); + $this->provisionEntityResource(); + $this->setUpAuthorization('POST'); + + // Create request. + $request_options = []; + $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('POST')); + $request_options[RequestOptions::BODY] = $this->serializer->encode($this->getNormalizedPostEntity(), static::$format); + + $url = $this->getEntityResourcePostUrl()->setOption('query', ['_format' => static::$format]); + + // Status should be FALSE when posting as anonymous. + $response = $this->request('POST', $url, $request_options); + $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); + $this->assertResourceResponse(201, FALSE, $response); + $this->assertFalse($unserialized->getStatus()); + + // Grant anonymous permission to skip comment approval. + $this->grantPermissionsToTestedRole(['skip comment approval']); + + // Status should be TRUE when posting as anonymous and skip comment approval. + $response = $this->request('POST', $url, $request_options); + $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); + $this->assertResourceResponse(201, FALSE, $response); + $this->assertTrue($unserialized->getStatus()); + } + } diff --git a/web/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php b/web/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php similarity index 97% rename from web/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php rename to web/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php index f36243e3d..88a2aca62 100644 --- a/web/core/modules/simpletest/tests/src/Unit/TestInfoParsingTest.php +++ b/web/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php @@ -1,10 +1,5 @@ 'Drupal\Tests\simpletest\Unit\TestInfoParsingTest', + 'name' => 'Drupal\Tests\simpletest\Unit\TestDiscoveryTest', 'group' => 'simpletest', 'description' => 'Tests \Drupal\simpletest\TestDiscovery.', 'type' => 'PHPUnit-Unit', ], // Classname. - 'Drupal\Tests\simpletest\Unit\TestInfoParsingTest', + 'Drupal\Tests\simpletest\Unit\TestDiscoveryTest', ]; // A core unit test. @@ -366,26 +361,6 @@ EOF; ], $result); } -} - -class TestTestDiscovery extends TestDiscovery { - - /** - * @var \Drupal\Core\Extension\Extension[] - */ - protected $extensions = []; - - public function setExtensions(array $extensions) { - $this->extensions = $extensions; - } - - /** - * {@inheritdoc} - */ - protected function getExtensions() { - return $this->extensions; - } - /** * @covers ::getPhpunitTestSuite * @dataProvider providerTestGetPhpunitTestSuite @@ -413,6 +388,26 @@ class TestTestDiscovery extends TestDiscovery { } +class TestTestDiscovery extends TestDiscovery { + + /** + * @var \Drupal\Core\Extension\Extension[] + */ + protected $extensions = []; + + public function setExtensions(array $extensions) { + $this->extensions = $extensions; + } + + /** + * {@inheritdoc} + */ + protected function getExtensions() { + return $this->extensions; + } + +} + namespace Drupal\simpletest\Tests; use Drupal\simpletest\WebTestBase; diff --git a/web/core/modules/system/src/Tests/Database/DatabaseWebTestBase.php b/web/core/modules/system/src/Tests/Database/DatabaseWebTestBase.php index 8fb369a37..8a250baf3 100644 --- a/web/core/modules/system/src/Tests/Database/DatabaseWebTestBase.php +++ b/web/core/modules/system/src/Tests/Database/DatabaseWebTestBase.php @@ -2,11 +2,16 @@ namespace Drupal\system\Tests\Database; +@trigger_error(__NAMESPACE__ . '\DatabaseWebTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Database\DatabaseTestBase', E_USER_DEPRECATED); + use Drupal\KernelTests\Core\Database\DatabaseTestBase; use Drupal\simpletest\WebTestBase; /** * Base class for databases database tests. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead + * use \Drupal\Tests\system\Functional\Database\DatabaseTestBase. */ abstract class DatabaseWebTestBase extends WebTestBase { diff --git a/web/core/modules/system/src/Tests/Database/FakeRecord.php b/web/core/modules/system/src/Tests/Database/FakeRecord.php index fce136684..cd7486cc7 100644 --- a/web/core/modules/system/src/Tests/Database/FakeRecord.php +++ b/web/core/modules/system/src/Tests/Database/FakeRecord.php @@ -2,11 +2,16 @@ namespace Drupal\system\Tests\Database; +@trigger_error(__NAMESPACE__ . '\FakeRecord is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Database\FakeRecord', E_USER_DEPRECATED); + /** * Fetches into a class. * * PDO supports using a new instance of an arbitrary class for records * rather than just a stdClass or array. This class is for testing that * functionality. (See testQueryFetchClass() below) + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead + * use \Drupal\Tests\system\Functional\Database\FakeRecord. */ class FakeRecord { } diff --git a/web/core/modules/system/src/Tests/Image/ToolkitTestBase.php b/web/core/modules/system/src/Tests/Image/ToolkitTestBase.php index 0051e9411..6c5ce54f2 100644 --- a/web/core/modules/system/src/Tests/Image/ToolkitTestBase.php +++ b/web/core/modules/system/src/Tests/Image/ToolkitTestBase.php @@ -2,11 +2,18 @@ namespace Drupal\system\Tests\Image; +@trigger_error(__FILE__ . ' is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use Drupal\FunctionalTests\Image\ToolkitTestBase instead. See https://www.drupal.org/node/2862641.', E_USER_DEPRECATED); + use Drupal\simpletest\WebTestBase; use Drupal\Component\Utility\SafeMarkup; /** * Base class for image manipulation testing. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. + * Use Drupal\FunctionalTests\Image\ToolkitTestBase instead. + * + * @see https://www.drupal.org/node/2862641 */ abstract class ToolkitTestBase extends WebTestBase { diff --git a/web/core/modules/system/tests/modules/entity_test/entity_test.module b/web/core/modules/system/tests/modules/entity_test/entity_test.module index e5fa873d0..cc9a09ca6 100644 --- a/web/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/web/core/modules/system/tests/modules/entity_test/entity_test.module @@ -160,15 +160,6 @@ function entity_test_entity_base_field_info_alter(&$fields, EntityTypeInterface } } -/** - * Implements hook_entity_field_storage_info(). - */ -function entity_test_entity_field_storage_info(EntityTypeInterface $entity_type) { - if ($entity_type->id() == 'entity_test_update') { - return \Drupal::state()->get('entity_test_update.additional_field_storage_definitions', []); - } -} - /** * Creates a new bundle for entity_test entities. * @@ -756,6 +747,16 @@ function entity_test_entity_access(EntityInterface $entity, $operation, AccountI return AccessResult::allowed(); } + // Create specific labels to allow or deny access based on certain test + // conditions. + // @see \Drupal\KernelTests\Core\Entity\EntityAccessControlHandlerTest + if ($entity->label() == 'Accessible') { + return AccessResult::allowed(); + } + if ($entity->label() == 'Inaccessible') { + return AccessResult::forbidden(); + } + // Uncacheable because the access result depends on a State key-value pair and // might therefore change at any time. $condition = \Drupal::state()->get("entity_test_entity_access.{$operation}." . $entity->id(), FALSE); diff --git a/web/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoUuid.php b/web/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoUuid.php new file mode 100644 index 000000000..8d0ddac48 --- /dev/null +++ b/web/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoUuid.php @@ -0,0 +1,29 @@ +get('entity_test_update.additional_base_field_definitions', []); - return $fields; - } - - /** - * {@inheritdoc} - */ - public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { - $fields = parent::bundleFieldDefinitions($entity_type, $bundle, $base_field_definitions); - $fields += \Drupal::state()->get('entity_test_update.additional_bundle_field_definitions.' . $bundle, []); - return $fields; - } - -} diff --git a/web/core/modules/system/tests/modules/entity_test_update/entity_test_update.module b/web/core/modules/system/tests/modules/entity_test_update/entity_test_update.module index 86ca5a971..5b32eb886 100644 --- a/web/core/modules/system/tests/modules/entity_test_update/entity_test_update.module +++ b/web/core/modules/system/tests/modules/entity_test_update/entity_test_update.module @@ -29,6 +29,15 @@ function entity_test_update_entity_base_field_info(EntityTypeInterface $entity_t } } +/** + * Implements hook_entity_field_storage_info(). + */ +function entity_test_update_entity_field_storage_info(EntityTypeInterface $entity_type) { + if ($entity_type->id() == 'entity_test_update') { + return \Drupal::state()->get('entity_test_update.additional_field_storage_definitions', []); + } +} + /** * Implements hook_entity_type_alter(). */ diff --git a/web/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php b/web/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php index a28c78690..a0f508041 100644 --- a/web/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php +++ b/web/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php @@ -161,8 +161,8 @@ class TestToolkit extends ImageToolkitBase { * @param array $args * Values passed to hook. * - * @see \Drupal\system\Tests\Image\ToolkitTestBase::imageTestReset() - * @see \Drupal\system\Tests\Image\ToolkitTestBase::imageTestGetAllCalls() + * @see \Drupal\Tests\system\Functional\Image\ToolkitTestBase::imageTestReset() + * @see \Drupal\Tests\system\Functional\Image\ToolkitTestBase::imageTestGetAllCalls() */ protected function logCall($op, $args) { $results = $this->state->get('image_test.results') ?: []; diff --git a/web/core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php b/web/core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php new file mode 100644 index 000000000..a28c1dba2 --- /dev/null +++ b/web/core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php @@ -0,0 +1,27 @@ +drupalGet('database_test/pager_query_even/' . $limit, ['query' => ['page' => $page]]); - $data = json_decode($this->getRawContent()); + $data = json_decode($this->getSession()->getPage()->getContent()); if ($page == $num_pages) { $correct_number = $count - ($limit * $page); } - $this->assertEqual(count($data->names), $correct_number, format_string('Correct number of records returned by pager: @number', ['@number' => $correct_number])); + $this->assertCount($correct_number, $data->names, format_string('Correct number of records returned by pager: @number', ['@number' => $correct_number])); } } @@ -68,13 +69,13 @@ class SelectPagerDefaultTest extends DatabaseWebTestBase { for ($page = 0; $page <= $num_pages; ++$page) { $this->drupalGet('database_test/pager_query_odd/' . $limit, ['query' => ['page' => $page]]); - $data = json_decode($this->getRawContent()); + $data = json_decode($this->getSession()->getPage()->getContent()); if ($page == $num_pages) { $correct_number = $count - ($limit * $page); } - $this->assertEqual(count($data->names), $correct_number, format_string('Correct number of records returned by pager: @number', ['@number' => $correct_number])); + $this->assertCount($correct_number, $data->names, format_string('Correct number of records returned by pager: @number', ['@number' => $correct_number])); } } diff --git a/web/core/modules/system/src/Tests/Database/SelectTableSortDefaultTest.php b/web/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php similarity index 85% rename from web/core/modules/system/src/Tests/Database/SelectTableSortDefaultTest.php rename to web/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php index 97a676b16..2904d31fa 100644 --- a/web/core/modules/system/src/Tests/Database/SelectTableSortDefaultTest.php +++ b/web/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php @@ -1,13 +1,13 @@ drupalGet('database_test/tablesort/', ['query' => ['order' => $sort['field'], 'sort' => $sort['sort']]]); - $data = json_decode($this->getRawContent()); + $data = json_decode($this->getSession()->getPage()->getContent()); $first = array_shift($data->tasks); $last = array_pop($data->tasks); @@ -55,7 +55,7 @@ class SelectTableSortDefaultTest extends DatabaseWebTestBase { foreach ($sorts as $sort) { $this->drupalGet('database_test/tablesort_first/', ['query' => ['order' => $sort['field'], 'sort' => $sort['sort']]]); - $data = json_decode($this->getRawContent()); + $data = json_decode($this->getSession()->getPage()->getContent()); $first = array_shift($data->tasks); $last = array_pop($data->tasks); @@ -72,16 +72,18 @@ class SelectTableSortDefaultTest extends DatabaseWebTestBase { * are correct. */ public function testTableSortDefaultSort() { + $assert = $this->assertSession(); + $this->drupalGet('database_test/tablesort_default_sort'); // Verify that the table was displayed. Just the header is checked for // because if there were any fatal errors or exceptions in displaying the // sorted table, it would not print the table. - $this->assertText(t('Username')); + $assert->pageTextContains(t('Username')); // Verify that the header links are built properly. - $this->assertLinkByHref('database_test/tablesort_default_sort'); - $this->assertPattern('/\/'); + $assert->linkByHrefExists('database_test/tablesort_default_sort'); + $assert->responseMatches('/\/'); } } diff --git a/web/core/modules/system/src/Tests/Database/TemporaryQueryTest.php b/web/core/modules/system/tests/src/Functional/Database/TemporaryQueryTest.php similarity index 90% rename from web/core/modules/system/src/Tests/Database/TemporaryQueryTest.php rename to web/core/modules/system/tests/src/Functional/Database/TemporaryQueryTest.php index d0dce74e4..522658579 100644 --- a/web/core/modules/system/src/Tests/Database/TemporaryQueryTest.php +++ b/web/core/modules/system/tests/src/Functional/Database/TemporaryQueryTest.php @@ -1,18 +1,16 @@ drupalGet('database_test/db_query_temporary'); - $data = json_decode($this->getRawContent()); + $data = json_decode($this->getSession()->getPage()->getContent()); if ($data) { $this->assertEqual($this->countTableRows('test'), $data->row_count, 'The temporary table contains the correct amount of rows.'); $this->assertFalse(db_table_exists($data->table_name), 'The temporary table is, indeed, temporary.'); diff --git a/web/core/modules/system/src/Tests/DrupalKernel/ContainerRebuildWebTest.php b/web/core/modules/system/tests/src/Functional/DrupalKernel/ContainerRebuildWebTest.php similarity index 63% rename from web/core/modules/system/src/Tests/DrupalKernel/ContainerRebuildWebTest.php rename to web/core/modules/system/tests/src/Functional/DrupalKernel/ContainerRebuildWebTest.php index c87e3ad8e..828b92f28 100644 --- a/web/core/modules/system/src/Tests/DrupalKernel/ContainerRebuildWebTest.php +++ b/web/core/modules/system/tests/src/Functional/DrupalKernel/ContainerRebuildWebTest.php @@ -1,15 +1,15 @@ assertSession(); + + // Ensure the parameter is not set. $this->drupalGet(''); - $this->assertHeader('container_rebuild_indicator', FALSE); + $assert->responseHeaderEquals('container_rebuild_indicator', NULL); $this->writeSettings(['settings' => ['deployment_identifier' => (object) ['value' => 'new-identifier', 'required' => TRUE]]]); $this->drupalGet(''); - $this->assertHeader('container_rebuild_indicator', 'new-identifier'); + $assert->responseHeaderEquals('container_rebuild_indicator', 'new-identifier'); } /** * Tests container invalidation. */ public function testContainerInvalidation() { + $assert = $this->assertSession(); // Ensure that parameter is not set. $this->drupalGet(''); - $this->assertHeader('container_rebuild_test_parameter', FALSE); + $assert->responseHeaderEquals('container_rebuild_test_parameter', NULL); // Ensure that after setting the parameter, without a container rebuild the // parameter is still not set. $this->writeSettings(['settings' => ['container_rebuild_test_parameter' => (object) ['value' => 'rebuild_me_please', 'required' => TRUE]]]); $this->drupalGet(''); - $this->assertHeader('container_rebuild_test_parameter', FALSE); + $assert->responseHeaderEquals('container_rebuild_test_parameter', NULL); // Ensure that after container invalidation the parameter is set. \Drupal::service('kernel')->invalidateContainer(); $this->drupalGet(''); - $this->assertHeader('container_rebuild_test_parameter', 'rebuild_me_please'); + $assert->responseHeaderEquals('container_rebuild_test_parameter', 'rebuild_me_please'); } } diff --git a/web/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml b/web/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml new file mode 100644 index 000000000..11af8cd47 --- /dev/null +++ b/web/core/modules/taxonomy/migration_templates/d6_taxonomy_term_translation.yml @@ -0,0 +1,39 @@ +id: d6_taxonomy_term_translation +label: Taxonomy terms +migration_tags: + - Drupal 6 +source: + plugin: d6_taxonomy_term + translations: true +process: + # If you are using this file to build a custom migration consider removing + # the tid field to allow incremental migrations. + tid: tid + langcode: language + vid: + plugin: migration + migration: d6_taxonomy_vocabulary + source: vid + name: name + description: description + weight: weight + # Only attempt to stub real (non-zero) parents. + parent_id: + - + plugin: skip_on_empty + method: process + source: parent + - + plugin: migration + migration: d6_taxonomy_term + parent: + plugin: default_value + default_value: 0 + source: '@parent_id' + changed: timestamp +destination: + plugin: entity:taxonomy_term +migration_dependencies: + required: + - d6_taxonomy_vocabulary + - d6_taxonomy_term diff --git a/web/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml b/web/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml new file mode 100644 index 000000000..dbb1793f9 --- /dev/null +++ b/web/core/modules/taxonomy/migration_templates/d6_taxonomy_vocabulary_translation.yml @@ -0,0 +1,27 @@ +id: d6_taxonomy_vocabulary_translation +label: Taxonomy vocabularies +migration_tags: + - Drupal 6 +source: + plugin: d6_taxonomy_vocabulary_translation +process: + vid: + - + plugin: machine_name + source: name + - + plugin: substr + length: 32 + langcode: language + property: + plugin: static_map + source: property + map: + name: name + description: description + translation: translation +destination: + plugin: entity:taxonomy_vocabulary +migration_dependencies: + required: + - d6_taxonomy_vocabulary diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php index b8a603d0f..9170cd8ae 100644 --- a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php @@ -45,6 +45,10 @@ class Term extends DrupalSqlBase { 'weight' => $this->t('Weight'), 'parent' => $this->t("The Drupal term IDs of the term's parents."), ]; + if (isset($this->configuration['translations'])) { + $fields['language'] = $this->t('The term language.'); + $fields['trid'] = $this->t('Translation ID.'); + } return $fields; } diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyTranslation.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyTranslation.php new file mode 100644 index 000000000..a6edd05e9 --- /dev/null +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyTranslation.php @@ -0,0 +1,57 @@ +select('vocabulary', 'v') + ->fields('v', ['vid', 'name', 'description']) + ->fields('i18n', ['lid', 'type', 'property', 'objectid']) + ->fields('lt', ['lid', 'translation']) + ->condition('i18n.type', 'vocabulary'); + $query->addField('lt', 'language', 'language'); + // The i18n_strings table has two columns containing the object ID, objectid + // and objectindex. The objectid column is a text field. Therefore, for the + // join to work in PostgreSQL, use the objectindex field as this is numeric + // like the vid field. + $query->join('i18n_strings', 'i18n', 'v.vid = i18n.objectindex'); + $query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid'); + + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'vid' => $this->t('The vocabulary ID.'), + 'language' => $this->t('Language for this field.'), + 'property' => $this->t('Name of property being translated.'), + 'translation' => $this->t('Translation of either the title or explanation.'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['vid']['type'] = 'integer'; + return $ids; + } + +} diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php b/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php index 838a9b02c..b4f941da5 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php @@ -2,8 +2,11 @@ namespace Drupal\taxonomy\Tests; +@trigger_error(__NAMESPACE__ . '\TaxonomyTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestBase', E_USER_DEPRECATED); + use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\simpletest\WebTestBase; +use Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait; /** * Provides common helper methods for Taxonomy module tests. diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTestTrait.php b/web/core/modules/taxonomy/src/Tests/TaxonomyTestTrait.php index 744ab1b28..8c4a66727 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTestTrait.php +++ b/web/core/modules/taxonomy/src/Tests/TaxonomyTestTrait.php @@ -2,6 +2,8 @@ namespace Drupal\taxonomy\Tests; +@trigger_error(__NAMESPACE__ . '\TaxonomyTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait', E_USER_DEPRECATED); + use Drupal\Component\Utility\Unicode; use Drupal\Core\Language\LanguageInterface; use Drupal\taxonomy\Entity\Vocabulary; @@ -9,6 +11,9 @@ use Drupal\taxonomy\Entity\Term; /** * Provides common helper methods for Taxonomy module tests. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. + * Use \Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait */ trait TaxonomyTestTrait { diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php b/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php index 3607fc6b0..644211714 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php +++ b/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php @@ -2,6 +2,8 @@ namespace Drupal\taxonomy\Tests; +@trigger_error(__NAMESPACE__ . '\TaxonomyTranslationTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait', E_USER_DEPRECATED); + use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldStorageConfig; @@ -9,6 +11,9 @@ use Drupal\language\Entity\ConfigurableLanguage; /** * Provides common testing base for translated taxonomy terms. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. + * Use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait */ trait TaxonomyTranslationTestTrait { diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyImageTest.php similarity index 94% rename from web/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php rename to web/core/modules/taxonomy/tests/src/Functional/TaxonomyImageTest.php index 7d2ee2b63..504c0da6c 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyImageTest.php @@ -1,8 +1,9 @@ $this->randomMachineName(), + 'description' => $this->randomMachineName(), + 'vid' => Unicode::strtolower($this->randomMachineName()), + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + 'weight' => mt_rand(0, 10), + ]); + $vocabulary->save(); + return $vocabulary; + } + + /** + * Returns a new term with random properties 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. + */ + public function createTerm(Vocabulary $vocabulary, $values = []) { + $filter_formats = filter_formats(); + $format = array_pop($filter_formats); + $term = Term::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/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php new file mode 100644 index 000000000..fc3cea75e --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php @@ -0,0 +1,105 @@ +translateToLangcode)->save(); + $this->rebuildContainer(); + } + + /** + * Enables translations where it needed. + */ + protected function enableTranslation() { + // Enable translation for the current entity type and ensure the change is + // picked up. + \Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE); + \Drupal::service('content_translation.manager')->setEnabled('taxonomy_term', $this->vocabulary->id(), TRUE); + drupal_static_reset(); + \Drupal::entityManager()->clearCachedDefinitions(); + \Drupal::service('router.builder')->rebuild(); + \Drupal::service('entity.definition_update_manager')->applyUpdates(); + } + + /** + * Adds term reference field for the article content type. + * + * @param bool $translatable + * (optional) If TRUE, create a translatable term reference field. Defaults + * to FALSE. + */ + protected function setUpTermReferenceField() { + $handler_settings = [ + 'target_bundles' => [ + $this->vocabulary->id() => $this->vocabulary->id(), + ], + 'auto_create' => TRUE, + ]; + $this->createEntityReferenceField('node', 'article', $this->termFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); + $field_storage = FieldStorageConfig::loadByName('node', $this->termFieldName); + $field_storage->setTranslatable(FALSE); + $field_storage->save(); + + entity_get_form_display('node', 'article', 'default') + ->setComponent($this->termFieldName, [ + 'type' => 'entity_reference_autocomplete_tags', + ]) + ->save(); + entity_get_display('node', 'article', 'default') + ->setComponent($this->termFieldName, [ + 'type' => 'entity_reference_label', + ]) + ->save(); + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Functional/TermTranslationFieldViewTest.php b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationFieldViewTest.php index c5df74dad..dfd5e51f0 100644 --- a/web/core/modules/taxonomy/tests/src/Functional/TermTranslationFieldViewTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationFieldViewTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\taxonomy\Functional; use Drupal\node\Entity\Node; -use Drupal\taxonomy\Tests\TaxonomyTranslationTestTrait; /** * Tests the translation of taxonomy terms field on nodes. diff --git a/web/core/modules/taxonomy/src/Tests/TermTranslationUITest.php b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationUITest.php similarity index 97% rename from web/core/modules/taxonomy/src/Tests/TermTranslationUITest.php rename to web/core/modules/taxonomy/tests/src/Functional/TermTranslationUITest.php index 43edc156b..0d24b6990 100644 --- a/web/core/modules/taxonomy/src/Tests/TermTranslationUITest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationUITest.php @@ -1,8 +1,8 @@ xpath('//a[@href="' . $this->term1->url() . '"]'); $this->assertEqual(count($actual), 2, 'Correct number of taxonomy term1 links'); - $this->assertEqual($actual[0]->__toString(), $this->term1->label()); - $this->assertEqual($actual[1]->__toString(), $this->term1->label()); + $this->assertEqual($actual[0]->getText(), $this->term1->label()); + $this->assertEqual($actual[1]->getText(), $this->term1->label()); $this->assertEscaped($this->term1->label()); $actual = $this->xpath('//a[@href="' . $this->term2->url() . '"]'); $this->assertEqual(count($actual), 2, 'Correct number of taxonomy term2 links'); - $this->assertEqual($actual[0]->__toString(), $this->term2->label()); - $this->assertEqual($actual[1]->__toString(), $this->term2->label()); + $this->assertEqual($actual[0]->getText(), $this->term2->label()); + $this->assertEqual($actual[1]->getText(), $this->term2->label()); } /** diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldFilterTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldFilterTest.php similarity index 96% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldFilterTest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldFilterTest.php index 86f67ff3d..1b8bbcaa5 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldFilterTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldFilterTest.php @@ -1,11 +1,11 @@ save(); diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldTidTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldTidTest.php similarity index 94% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldTidTest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldTidTest.php index b068f083a..0a44d4cb2 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldTidTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyFieldTidTest.php @@ -1,6 +1,6 @@ adminUser = $this->drupalCreateUser(['administer taxonomy', 'administer views']); $this->drupalLogin($this->adminUser); @@ -93,10 +93,9 @@ class TaxonomyIndexTidUiTest extends UITestBase { for ($j = 0; $j <= $i; $j++) { $option = $result[$counter++]; $prefix = $this->terms[$i][$j]->parent->target_id ? '-' : ''; - $attributes = $option->attributes(); - $tid = (string) $attributes->value; + $tid = $option->getAttribute('value'); - $this->assertEqual($prefix . $this->terms[$i][$j]->getName(), (string) $option); + $this->assertEqual($prefix . $this->terms[$i][$j]->getName(), $option->getText()); $this->assertEqual($this->terms[$i][$j]->id(), $tid); } } @@ -108,7 +107,7 @@ class TaxonomyIndexTidUiTest extends UITestBase { $display['display_options']['filters']['tid']['type'] = 'textfield'; $view->save(); $this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid'); - $this->assertFieldByXPath('//input[@id="edit-options-value"]'); + $this->assertFieldById('edit-options-value', NULL); // Tests \Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid::calculateDependencies(). $expected = [ diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyParentUITest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyParentUITest.php similarity index 81% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyParentUITest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyParentUITest.php index a57a09a7a..d8ab8ea12 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyParentUITest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyParentUITest.php @@ -1,9 +1,9 @@ term1->set('parent', $this->term2->id()); diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermArgumentDepthTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermArgumentDepthTest.php similarity index 89% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermArgumentDepthTest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermArgumentDepthTest.php index 311118dfe..3505784a0 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermArgumentDepthTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermArgumentDepthTest.php @@ -1,6 +1,6 @@ createTerm(['name' => 'First']); diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermFilterDepthTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermFilterDepthTest.php similarity index 96% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermFilterDepthTest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermFilterDepthTest.php index 10ccad260..4d7a4fdf0 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTermFilterDepthTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermFilterDepthTest.php @@ -1,6 +1,6 @@ adminUser = $this->drupalCreateUser(['administer taxonomy', 'bypass node access']); diff --git a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php similarity index 97% rename from web/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php index 6ff551418..a2d8ec14a 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php @@ -1,11 +1,11 @@ vocabularies[] = $this->vocabulary; diff --git a/web/core/modules/taxonomy/src/Tests/Views/TermNameFieldTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TermNameFieldTest.php similarity index 96% rename from web/core/modules/taxonomy/src/Tests/Views/TermNameFieldTest.php rename to web/core/modules/taxonomy/tests/src/Functional/Views/TermNameFieldTest.php index 98d1ab4b4..6fbe0c0b2 100644 --- a/web/core/modules/taxonomy/src/Tests/Views/TermNameFieldTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TermNameFieldTest.php @@ -1,6 +1,6 @@ config('system.site')->get('name'); $this->assertTitle(t('Don\'t Panic | @site-name', ['@site-name' => $site_name]), 'The page title contains the escaped character.'); - $this->assertNoTitle(t('Don't Panic | @site-name', ['@site-name' => $site_name]), 'The page title does not contain an encoded character.'); } /** diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php index 125283355..12b9a9cd1 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php @@ -36,18 +36,21 @@ class MigrateTaxonomyTermTest extends MigrateDrupal6TestBase { 'vid' => 'vocabulary_1_i_0_', 'weight' => 0, 'parent' => [0], + 'language' => 'zu', ], '2' => [ 'source_vid' => 2, 'vid' => 'vocabulary_2_i_1_', 'weight' => 3, 'parent' => [0], + 'language' => 'fr', ], '3' => [ 'source_vid' => 2, 'vid' => 'vocabulary_2_i_1_', 'weight' => 4, 'parent' => [2], + 'language' => 'fr', ], '4' => [ 'source_vid' => 3, @@ -83,8 +86,9 @@ class MigrateTaxonomyTermTest extends MigrateDrupal6TestBase { foreach ($expected_results as $tid => $values) { /** @var Term $term */ $term = $terms[$tid]; - $this->assertIdentical("term {$tid} of vocabulary {$values['source_vid']}", $term->name->value); - $this->assertIdentical("description of term {$tid} of vocabulary {$values['source_vid']}", $term->description->value); + $language = isset($values['language']) ? $values['language'] . ' - ' : ''; + $this->assertSame("{$language}term {$tid} of vocabulary {$values['source_vid']}", $term->name->value); + $this->assertSame("{$language}description of term {$tid} of vocabulary {$values['source_vid']}", $term->description->value); $this->assertIdentical($values['vid'], $term->vid->target_id); $this->assertIdentical((string) $values['weight'], $term->weight->value); if ($values['parent'] === [0]) { diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php new file mode 100644 index 000000000..d21ad1e58 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php @@ -0,0 +1,124 @@ +installEntitySchema('taxonomy_term'); + $this->installConfig(static::$modules); + $this->executeMigrations([ + 'd6_node_type', + 'd6_field', + 'd6_taxonomy_vocabulary', + 'd6_field_instance', + 'd6_taxonomy_term', + 'd6_taxonomy_term_translation', + ]); + } + + /** + * Validate a migrated term contains the expected values. + * + * @param int $id + * Entity ID to load and check. + * @param string $expected_language + * The language code for this term. + * @param string $expected_label + * The label the migrated entity should have. + * @param string $expected_vid + * The parent vocabulary the migrated entity should have. + * @param string $expected_description + * The description the migrated entity should have. + * @param string $expected_format + * The format the migrated entity should have. + * @param int $expected_weight + * The weight the migrated entity should have. + * @param array $expected_parents + * The parent terms the migrated entity should have. + * @param int $expected_field_integer_value + * The value the migrated entity field should have. + * @param int $expected_term_reference_tid + * The term reference ID the migrated entity field should have. + */ + protected function assertEntity($id, $expected_language, $expected_label, $expected_vid, $expected_description = '', $expected_format = NULL, $expected_weight = 0, $expected_parents = [], $expected_field_integer_value = NULL, $expected_term_reference_tid = NULL) { + /** @var \Drupal\taxonomy\TermInterface $entity */ + $entity = Term::load($id); + $this->assertInstanceOf(TermInterface::class, $entity); + $this->assertSame($expected_language, $entity->language()->getId()); + $this->assertSame($expected_label, $entity->label()); + $this->assertSame($expected_vid, $entity->getVocabularyId()); + $this->assertSame($expected_description, $entity->getDescription()); + $this->assertSame($expected_format, $entity->getFormat()); + $this->assertSame($expected_weight, $entity->getWeight()); + $this->assertHierarchy($expected_vid, $id, $expected_parents); + } + + /** + * Assert that a term is present in the tree storage, with the right parents. + * + * @param string $vid + * Vocabulary ID. + * @param int $tid + * ID of the term to check. + * @param array $parent_ids + * The expected parent term IDs. + */ + protected function assertHierarchy($vid, $tid, array $parent_ids) { + if (!isset($this->treeData[$vid])) { + $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid); + $this->treeData[$vid] = []; + foreach ($tree as $item) { + $this->treeData[$vid][$item->tid] = $item; + } + } + + $this->assertArrayHasKey($tid, $this->treeData[$vid], "Term $tid exists in taxonomy tree"); + $term = $this->treeData[$vid][$tid]; + $this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree"); + } + + /** + * Tests the Drupal 6 i18n taxonomy term to Drupal 8 migration. + */ + public function testTranslatedTaxonomyTerms() { + $this->assertEntity(1, 'zu', 'zu - term 1 of vocabulary 1', 'vocabulary_1_i_0_', 'zu - description of term 1 of vocabulary 1', NULL, '0', []); + $this->assertEntity(2, 'fr', 'fr - term 2 of vocabulary 2', 'vocabulary_2_i_1_', 'fr - description of term 2 of vocabulary 2', NULL, '3', []); + $this->assertEntity(3, 'fr', 'fr - term 3 of vocabulary 2', 'vocabulary_2_i_1_', 'fr - description of term 3 of vocabulary 2', NULL, '4', ['2']); + $this->assertEntity(4, 'en', 'term 4 of vocabulary 3', 'vocabulary_3_i_2_', 'description of term 4 of vocabulary 3', NULL, '6', []); + $this->assertEntity(5, 'en', 'term 5 of vocabulary 3', 'vocabulary_3_i_2_', 'description of term 5 of vocabulary 3', NULL, '7', ['4']); + $this->assertEntity(6, 'en', 'term 6 of vocabulary 3', 'vocabulary_3_i_2_', 'description of term 6 of vocabulary 3', NULL, '8', ['4', '5']); + $this->assertEntity(7, 'fr', 'fr - term 2 of vocabulary 1', 'vocabulary_1_i_0_', 'fr - desc of term 2 vocab 1', NULL, '0', []); + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTranslationTest.php new file mode 100644 index 000000000..3993abb98 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTranslationTest.php @@ -0,0 +1,47 @@ +executeMigrations([ + 'd6_taxonomy_vocabulary', + 'd6_taxonomy_vocabulary_translation', + ]); + } + + /** + * Tests the Drupal 6 i18n taxonomy vocabularies to Drupal 8 migration. + */ + public function testTaxonomyVocabularyTranslation() { + $language_manager = \Drupal::service('language_manager'); + $config = $language_manager->getLanguageConfigOverride('fr', 'taxonomy.vocabulary.vocabulary_1_i_0_'); + $this->assertSame('fr - vocabulary 1 (i=0)', $config->get('name')); + $config = $language_manager->getLanguageConfigOverride('fr', 'taxonomy.vocabulary.vocabulary_2_i_1_'); + $this->assertSame('fr - vocabulary 2 (i=1)', $config->get('name')); + $config = $language_manager->getLanguageConfigOverride('fr', 'taxonomy.vocabulary.vocabulary_3_i_2_'); + $this->assertSame('fr - vocabulary 3 (i=2)', $config->get('name')); + $config = $language_manager->getLanguageConfigOverride('fr', 'taxonomy.vocabulary.vocabulary_name_much_longer_than'); + $this->assertSame('Nom de vocabulaire beaucoup plus long que trente-deux caractères', $config->get('name')); + $config = $language_manager->getLanguageConfigOverride('fr', 'taxonomy.vocabulary.tags'); + $this->assertSame('fr - Tags', $config->get('name')); + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermTranslationTest.php new file mode 100644 index 000000000..af69e30e3 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermTranslationTest.php @@ -0,0 +1,206 @@ + 1, + 'vid' => 5, + 'name' => 'name value 1', + 'description' => 'description value 1', + 'weight' => 0, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 2, + 'vid' => 6, + 'name' => 'name value 2', + 'description' => 'description value 2', + 'weight' => 0, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 3, + 'vid' => 6, + 'name' => 'name value 3', + 'description' => 'description value 3', + 'weight' => 0, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 4, + 'vid' => 5, + 'name' => 'name value 4', + 'description' => 'description value 4', + 'weight' => 1, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 5, + 'vid' => 6, + 'name' => 'name value 5', + 'description' => 'description value 5', + 'weight' => 1, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 6, + 'vid' => 6, + 'name' => 'name value 6', + 'description' => 'description value 6', + 'weight' => 0, + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 10, + 'vid' => 6, + 'name' => 'zu - name value 2', + 'description' => 'zu - description value 2', + 'weight' => 0, + 'language' => 'zu', + 'trid' => 0, + ], + ]; + $tests[0]['source_data']['term_hierarchy'] = [ + [ + 'tid' => 1, + 'parent' => 0, + ], + [ + 'tid' => 2, + 'parent' => 0, + ], + [ + 'tid' => 3, + 'parent' => 0, + ], + [ + 'tid' => 4, + 'parent' => 1, + ], + [ + 'tid' => 5, + 'parent' => 2, + ], + [ + 'tid' => 6, + 'parent' => 3, + ], + [ + 'tid' => 6, + 'parent' => 2, + ], + [ + 'tid' => 10, + 'parent' => 0, + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'tid' => 1, + 'vid' => 5, + 'name' => 'name value 1', + 'description' => 'description value 1', + 'weight' => 0, + 'parent' => [0], + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 10, + 'vid' => 6, + 'name' => 'zu - name value 2', + 'description' => 'zu - description value 2', + 'weight' => 0, + 'parent' => [0], + 'language' => 'zu', + 'trid' => 0, + ], + [ + 'tid' => 2, + 'vid' => 6, + 'name' => 'name value 2', + 'description' => 'description value 2', + 'weight' => 0, + 'parent' => [0], + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 3, + 'vid' => 6, + 'name' => 'name value 3', + 'description' => 'description value 3', + 'weight' => 0, + 'parent' => [0], + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 4, + 'vid' => 5, + 'name' => 'name value 4', + 'description' => 'description value 4', + 'weight' => 1, + 'parent' => [1], + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 5, + 'vid' => 6, + 'name' => 'name value 5', + 'description' => 'description value 5', + 'weight' => 1, + 'parent' => [2], + 'language' => NULL, + 'trid' => 0, + ], + [ + 'tid' => 6, + 'vid' => 6, + 'name' => 'name value 6', + 'description' => 'description value 6', + 'weight' => 0, + 'parent' => [3, 2], + 'language' => NULL, + 'trid' => 0, + ], + ]; + + $tests[0]['expected_count'] = NULL; + + return $tests; + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/VocabularyTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/VocabularyTranslationTest.php new file mode 100644 index 000000000..e54eb6ee3 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/VocabularyTranslationTest.php @@ -0,0 +1,125 @@ + 1, + 'objectid' => 1, + 'type' => 'vocabulary', + 'property' => 'name', + 'objectindex' => 1, + 'format' => 0, + ], + [ + 'lid' => 2, + 'objectid' => 2, + 'type' => 'vocabulary', + 'property' => 'name', + 'objectindex' => 2, + 'format' => 0, + ], + ]; + + $tests[0][0]['locales_target'] = [ + [ + 'lid' => 1, + 'language' => 'fr', + 'translation' => 'fr - vocabulary 1', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 2, + 'language' => 'fr', + 'translation' => 'fr - vocabulary 2', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + + $tests[0][0]['vocabulary'] = [ + [ + 'vid' => 1, + 'name' => 'vocabulary 1', + 'description' => 'description of vocabulary 1', + 'help' => 1, + 'relations' => 1, + 'hierarchy' => 1, + 'multiple' => 0, + 'required' => 0, + 'tags' => 0, + 'module' => 'taxonomy', + 'weight' => 4, + 'language' => '', + ], + [ + 'vid' => 2, + 'name' => 'vocabulary 2', + 'description' => 'description of vocabulary 2', + 'help' => 1, + 'relations' => 1, + 'hierarchy' => 1, + 'multiple' => 0, + 'required' => 0, + 'tags' => 0, + 'module' => 'taxonomy', + 'weight' => 5, + 'language' => '', + ], + ]; + + $tests[0]['expected_results'] = [ + [ + 'vid' => 1, + 'name' => 'vocabulary 1', + 'description' => 'description of vocabulary 1', + 'lid' => '1', + 'type' => 'vocabulary', + 'property' => 'name', + 'objectid' => '1', + 'lt_lid' => '1', + 'translation' => 'fr - vocabulary 1', + 'language' => 'fr', + ], + [ + 'vid' => 2, + 'name' => 'vocabulary 2', + 'description' => 'description of vocabulary 2', + 'lid' => '2', + 'type' => 'vocabulary', + 'property' => 'name', + 'objectid' => '2', + 'lt_lid' => '2', + 'translation' => 'fr - vocabulary 2', + 'language' => 'fr', + ], + ]; + return $tests; + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php b/web/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php index 0d70d840d..832e5111b 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php @@ -4,7 +4,7 @@ namespace Drupal\Tests\taxonomy\Kernel; use Drupal\taxonomy\Entity\Term; use Drupal\KernelTests\KernelTestBase; -use Drupal\taxonomy\Tests\TaxonomyTestTrait; +use Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait; /** * Kernel tests for taxonomy term functions. diff --git a/web/core/modules/update/src/Tests/UpdateTestBase.php b/web/core/modules/update/src/Tests/UpdateTestBase.php index fc39d1a3c..e243d0b86 100644 --- a/web/core/modules/update/src/Tests/UpdateTestBase.php +++ b/web/core/modules/update/src/Tests/UpdateTestBase.php @@ -2,6 +2,8 @@ namespace Drupal\update\Tests; +@trigger_error(__NAMESPACE__ . '\UpdateTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\update\Functional\UpdateTestBase', E_USER_DEPRECATED); + use Drupal\Core\DrupalKernel; use Drupal\Core\Url; use Drupal\simpletest\WebTestBase; @@ -22,6 +24,9 @@ use Drupal\simpletest\WebTestBase; * (via the 'update_test_xml_map' variable), and then performs a series of * assertions that the report matches our expectations given the specific * initial state and availability scenario. + * + * @deprecated Scheduled for removal in Drupal 9.0.0. + * Use \Drupal\Tests\update\Functional\UpdateTestBase instead. */ abstract class UpdateTestBase extends WebTestBase { @@ -58,7 +63,7 @@ abstract class UpdateTestBase extends WebTestBase { * (optional) A string containing the URL to fetch update data from. * Defaults to 'update-test'. * - * @see Drupal\update_test\Controller\UpdateTestController::updateTest() + * @see \Drupal\update_test\Controller\UpdateTestController::updateTest() */ protected function refreshUpdateStatus($xml_map, $url = 'update-test') { // Tell the Update Manager module to fetch from the URL provided by diff --git a/web/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php b/web/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php similarity index 92% rename from web/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php rename to web/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php index 9d1819fca..d768b06d8 100644 --- a/web/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php +++ b/web/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php @@ -1,6 +1,6 @@ standardTests(); $this->drupalGet('admin/reports/updates'); $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); $this->assertNoText(t('Security update required!')); $this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.'); $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.'); @@ -139,6 +143,7 @@ class UpdateCoreTest extends UpdateTestBase { $this->standardTests(); $this->drupalGet('admin/reports/updates'); $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); $this->assertNoText(t('Security update required!')); $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.'); $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.'); @@ -226,6 +231,7 @@ class UpdateCoreTest extends UpdateTestBase { $this->drupalGet('admin/reports/updates'); $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); $this->assertText(t('Checked available update data for one project.')); $this->drupalGet('admin/modules'); $this->assertNoText(t('There are updates available for your version of Drupal.')); @@ -247,6 +253,7 @@ class UpdateCoreTest extends UpdateTestBase { $this->drupalGet('admin/reports/updates'); $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); $this->assertText(t('Checked available update data for one project.')); $this->drupalGet('admin/modules'); $this->assertText(t('There are updates available for your version of Drupal.')); @@ -268,6 +275,7 @@ class UpdateCoreTest extends UpdateTestBase { $this->drupalGet('admin/reports/updates'); $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); $this->assertText(t('Checked available update data for one project.')); $this->drupalGet('admin/modules'); $this->assertNoText(t('There are updates available for your version of Drupal.')); diff --git a/web/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php b/web/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php similarity index 96% rename from web/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php rename to web/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php index 99499d77c..601a6cc2f 100644 --- a/web/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php +++ b/web/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php @@ -1,6 +1,6 @@ container->get('update.root') . '/' . DrupalKernel::findSitePath($request); + $this->container->set('update.root', $update_root); + \Drupal::setContainer($this->container); + + // Create the directories within the root path within which the Update + // Manager will install projects. + foreach (drupal_get_updaters() as $updater_info) { + $updater = $updater_info['class']; + $install_directory = $update_root . '/' . $updater::getRootDirectoryRelativePath(); + if (!is_dir($install_directory)) { + mkdir($install_directory); + } + } + } + + /** + * Refreshes the update status based on the desired available update scenario. + * + * @param $xml_map + * Array that maps project names to availability scenarios to fetch. The key + * '#all' is used if a project-specific mapping is not defined. + * @param $url + * (optional) A string containing the URL to fetch update data from. + * Defaults to 'update-test'. + * + * @see \Drupal\update_test\Controller\UpdateTestController::updateTest() + */ + protected function refreshUpdateStatus($xml_map, $url = 'update-test') { + // Tell the Update Manager module to fetch from the URL provided by + // update_test module. + $this->config('update.settings')->set('fetch.url', Url::fromUri('base:' . $url, ['absolute' => TRUE])->toString())->save(); + // Save the map for UpdateTestController::updateTest() to use. + $this->config('update_test.settings')->set('xml_map', $xml_map)->save(); + // Manually check the update status. + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->checkForMetaRefresh(); + } + + /** + * Runs a series of assertions that are applicable to all update statuses. + */ + protected function standardTests() { + $this->assertRaw('

' . t('Drupal core') . '

'); + $this->assertRaw(\Drupal::l(t('Drupal'), Url::fromUri('http://example.com/project/drupal')), 'Link to the Drupal project appears.'); + $this->assertNoText(t('No available releases found')); + } + +} diff --git a/web/core/modules/update/src/Tests/UpdateUploadTest.php b/web/core/modules/update/tests/src/Functional/UpdateUploadTest.php similarity index 96% rename from web/core/modules/update/src/Tests/UpdateUploadTest.php rename to web/core/modules/update/tests/src/Functional/UpdateUploadTest.php index 80d3f15d2..609662006 100644 --- a/web/core/modules/update/src/Tests/UpdateUploadTest.php +++ b/web/core/modules/update/tests/src/Functional/UpdateUploadTest.php @@ -1,10 +1,11 @@ $validArchiveFile, ]; @@ -63,7 +68,7 @@ class UpdateUploadTest extends UpdateTestBase { $moduleUpdater = $updaters['module']['class']; $installedInfoFilePath = $this->container->get('update.root') . '/' . $moduleUpdater::getRootDirectoryRelativePath() . '/update_test_new_module/update_test_new_module.info.yml'; $this->assertFalse(file_exists($installedInfoFilePath), 'The new module does not exist in the filesystem before it is installed with the Update Manager.'); - $validArchiveFile = __DIR__ . '/../../tests/update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; + $validArchiveFile = __DIR__ . '/../../update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; $edit = [ 'files[project_upload]' => $validArchiveFile, ]; diff --git a/web/core/modules/user/src/UserData.php b/web/core/modules/user/src/UserData.php index 735c3de4e..a5bc10094 100644 --- a/web/core/modules/user/src/UserData.php +++ b/web/core/modules/user/src/UserData.php @@ -40,7 +40,7 @@ class UserData implements UserDataInterface { $query->condition('name', $name); } $result = $query->execute(); - // If $module, $uid, and $name was passed, return the value. + // If $module, $uid, and $name were passed, return the value. if (isset($name) && isset($uid)) { $result = $result->fetchAllAssoc('uid'); if (isset($result[$uid])) { @@ -48,7 +48,7 @@ class UserData implements UserDataInterface { } return NULL; } - // If $module and $uid was passed, return the name/value pairs. + // If $module and $uid were passed, return data keyed by name. elseif (isset($uid)) { $return = []; foreach ($result as $record) { @@ -56,7 +56,7 @@ class UserData implements UserDataInterface { } return $return; } - // If $module and $name was passed, return the uid/value pairs. + // If $module and $name were passed, return data keyed by uid. elseif (isset($name)) { $return = []; foreach ($result as $record) { diff --git a/web/core/modules/user/src/Tests/Views/AccessRoleUITest.php b/web/core/modules/user/tests/src/Functional/AccessRoleUITest.php similarity index 88% rename from web/core/modules/user/src/Tests/Views/AccessRoleUITest.php rename to web/core/modules/user/tests/src/Functional/AccessRoleUITest.php index bea8c53c6..6c1004c9d 100644 --- a/web/core/modules/user/src/Tests/Views/AccessRoleUITest.php +++ b/web/core/modules/user/tests/src/Functional/AccessRoleUITest.php @@ -1,15 +1,15 @@ doTestLogin('json'); + + // Enable serialization so we have access to additional formats. + $this->container->get('module_installer')->install(['serialization']); + $this->doTestLogin('json'); + $this->doTestLogin('xml'); + $this->doTestLogin('hal_json'); + } + + /** + * Do login testing for a given serialization format. + * + * @param string $format + * Serialization format. + */ + protected function doTestLogin($format) { $client = \Drupal::httpClient(); - foreach ([FALSE, TRUE] as $serialization_enabled_option) { - if ($serialization_enabled_option) { - /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ - $module_installer = $this->container->get('module_installer'); - $module_installer->install(['serialization']); - $formats = ['json', 'xml', 'hal_json']; - } - else { - // Without the serialization module only JSON is supported. - $formats = ['json']; - } - foreach ($formats as $format) { - // Create new user for each iteration to reset flood. - // Grant the user administer users permissions to they can see the - // 'roles' field. - $account = $this->drupalCreateUser(['administer users']); - $name = $account->getUsername(); - $pass = $account->passRaw; + // Create new user for each iteration to reset flood. + // Grant the user administer users permissions to they can see the + // 'roles' field. + $account = $this->drupalCreateUser(['administer users']); + $name = $account->getUsername(); + $pass = $account->passRaw; - $login_status_url = $this->getLoginStatusUrlString($format); - $response = $client->get($login_status_url); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); + $login_status_url = $this->getLoginStatusUrlString($format); + $response = $client->get($login_status_url); + $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); - // Flooded. - $this->config('user.flood') - ->set('user_limit', 3) - ->save(); + // Flooded. + $this->config('user.flood') + ->set('user_limit', 3) + ->save(); - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); + $response = $this->loginRequest($name, 'wrong-pass', $format); + $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); + $response = $this->loginRequest($name, 'wrong-pass', $format); + $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); + $response = $this->loginRequest($name, 'wrong-pass', $format); + $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 403, 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.', $format); + $response = $this->loginRequest($name, 'wrong-pass', $format); + $this->assertHttpResponseWithMessage($response, 403, 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.', $format); - // After testing the flood control we can increase the limit. - $this->config('user.flood') - ->set('user_limit', 100) - ->save(); + // After testing the flood control we can increase the limit. + $this->config('user.flood') + ->set('user_limit', 100) + ->save(); - $response = $this->loginRequest(NULL, NULL, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.', $format); + $response = $this->loginRequest(NULL, NULL, $format); + $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.', $format); - $response = $this->loginRequest(NULL, $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.name.', $format); + $response = $this->loginRequest(NULL, $pass, $format); + $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.name.', $format); - $response = $this->loginRequest($name, NULL, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.pass.', $format); + $response = $this->loginRequest($name, NULL, $format); + $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.pass.', $format); - // Blocked. - $account - ->block() - ->save(); + // Blocked. + $account + ->block() + ->save(); - $response = $this->loginRequest($name, $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'The user has not been activated or is blocked.', $format); + $response = $this->loginRequest($name, $pass, $format); + $this->assertHttpResponseWithMessage($response, 400, 'The user has not been activated or is blocked.', $format); - $account - ->activate() - ->save(); + $account + ->activate() + ->save(); - $response = $this->loginRequest($name, 'garbage', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); + $response = $this->loginRequest($name, 'garbage', $format); + $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - $response = $this->loginRequest('garbage', $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); + $response = $this->loginRequest('garbage', $pass, $format); + $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - $response = $this->loginRequest($name, $pass, $format); - $this->assertEquals(200, $response->getStatusCode()); - $result_data = $this->serializer->decode($response->getBody(), $format); - $this->assertEquals($name, $result_data['current_user']['name']); - $this->assertEquals($account->id(), $result_data['current_user']['uid']); - $this->assertEquals($account->getRoles(), $result_data['current_user']['roles']); - $logout_token = $result_data['logout_token']; + $response = $this->loginRequest($name, $pass, $format); + $this->assertEquals(200, $response->getStatusCode()); + $result_data = $this->serializer->decode($response->getBody(), $format); + $this->assertEquals($name, $result_data['current_user']['name']); + $this->assertEquals($account->id(), $result_data['current_user']['uid']); + $this->assertEquals($account->getRoles(), $result_data['current_user']['roles']); + $logout_token = $result_data['logout_token']; - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN); + $response = $client->get($login_status_url, ['cookies' => $this->cookies]); + $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN); - $response = $this->logoutRequest($format, $logout_token); - $this->assertEquals(204, $response->getStatusCode()); + $response = $this->logoutRequest($format, $logout_token); + $this->assertEquals(204, $response->getStatusCode()); - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); + $response = $client->get($login_status_url, ['cookies' => $this->cookies]); + $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); - $this->resetFlood(); - } - } + $this->resetFlood(); } /** diff --git a/web/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php b/web/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php index 5ca694b84..1f460517d 100644 --- a/web/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php +++ b/web/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php @@ -23,9 +23,9 @@ class AddRoleUserTest extends RoleUserTestBase { ->will($this->returnValue(TRUE)); $config = ['rid' => 'test_role_1']; - $remove_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType); + $add_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType); - $remove_role_plugin->execute($this->account); + $add_role_plugin->execute($this->account); } /** @@ -41,9 +41,9 @@ class AddRoleUserTest extends RoleUserTestBase { ->will($this->returnValue(FALSE)); $config = ['rid' => 'test_role_1']; - $remove_role_plugin = new AddRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType); + $add_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType); - $remove_role_plugin->execute($this->account); + $add_role_plugin->execute($this->account); } } diff --git a/web/core/modules/views/src/Controller/ViewAjaxController.php b/web/core/modules/views/src/Controller/ViewAjaxController.php index c40cf8576..d204766f2 100644 --- a/web/core/modules/views/src/Controller/ViewAjaxController.php +++ b/web/core/modules/views/src/Controller/ViewAjaxController.php @@ -142,7 +142,7 @@ class ViewAjaxController implements ContainerInjectionInterface { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); - if ($view && $view->access($display_id)) { + if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->getOption('use_ajax')) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { diff --git a/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index 48c59ef70..fb6b5bfd4 100644 --- a/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -321,9 +321,9 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf * {@inheritdoc} */ public function elementClasses($row_index = NULL) { - $classes = explode(' ', $this->options['element_class']); + $classes = $this->tokenizeValue($this->options['element_class'], $row_index); + $classes = explode(' ', $classes); foreach ($classes as &$class) { - $class = $this->tokenizeValue($class, $row_index); $class = Html::cleanCssIdentifier($class); } return implode(' ', $classes); @@ -368,9 +368,9 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf * {@inheritdoc} */ public function elementLabelClasses($row_index = NULL) { - $classes = explode(' ', $this->options['element_label_class']); + $classes = $this->tokenizeValue($this->options['element_label_class'], $row_index); + $classes = explode(' ', $classes); foreach ($classes as &$class) { - $class = $this->tokenizeValue($class, $row_index); $class = Html::cleanCssIdentifier($class); } return implode(' ', $classes); @@ -380,9 +380,9 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf * {@inheritdoc} */ public function elementWrapperClasses($row_index = NULL) { - $classes = explode(' ', $this->options['element_wrapper_class']); + $classes = $this->tokenizeValue($this->options['element_wrapper_class'], $row_index); + $classes = explode(' ', $classes); foreach ($classes as &$class) { - $class = $this->tokenizeValue($class, $row_index); $class = Html::cleanCssIdentifier($class); } return implode(' ', $classes); diff --git a/web/core/modules/views/src/Plugin/views/style/DefaultStyle.php b/web/core/modules/views/src/Plugin/views/style/DefaultStyle.php index 60aa9bd3b..fe67d9bee 100644 --- a/web/core/modules/views/src/Plugin/views/style/DefaultStyle.php +++ b/web/core/modules/views/src/Plugin/views/style/DefaultStyle.php @@ -19,9 +19,7 @@ namespace Drupal\views\Plugin\views\style; class DefaultStyle extends StylePluginBase { /** - * Does the style plugin allows to use style plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/src/Plugin/views/style/Grid.php b/web/core/modules/views/src/Plugin/views/style/Grid.php index 938c1b523..f33f7f9c4 100644 --- a/web/core/modules/views/src/Plugin/views/style/Grid.php +++ b/web/core/modules/views/src/Plugin/views/style/Grid.php @@ -21,9 +21,7 @@ use Drupal\Core\Form\FormStateInterface; class Grid extends StylePluginBase { /** - * Does the style plugin allows to use style plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/src/Plugin/views/style/HtmlList.php b/web/core/modules/views/src/Plugin/views/style/HtmlList.php index a6df09d2b..519dff64b 100644 --- a/web/core/modules/views/src/Plugin/views/style/HtmlList.php +++ b/web/core/modules/views/src/Plugin/views/style/HtmlList.php @@ -20,9 +20,7 @@ use Drupal\Core\Form\FormStateInterface; class HtmlList extends StylePluginBase { /** - * Does the style plugin allows to use style plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/src/Plugin/views/style/Opml.php b/web/core/modules/views/src/Plugin/views/style/Opml.php index 69679d3ce..016405e4c 100644 --- a/web/core/modules/views/src/Plugin/views/style/Opml.php +++ b/web/core/modules/views/src/Plugin/views/style/Opml.php @@ -20,9 +20,7 @@ use Drupal\Core\Url; class Opml extends StylePluginBase { /** - * Does the style plugin for itself support to add fields to its output. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/src/Plugin/views/style/Rss.php b/web/core/modules/views/src/Plugin/views/style/Rss.php index b7efa578d..96d1deaea 100644 --- a/web/core/modules/views/src/Plugin/views/style/Rss.php +++ b/web/core/modules/views/src/Plugin/views/style/Rss.php @@ -21,9 +21,7 @@ use Drupal\Core\Url; class Rss extends StylePluginBase { /** - * Does the style plugin for itself support to add fields to it's output. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/web/core/modules/views/src/Plugin/views/style/StylePluginBase.php index 8fb5cb5bd..d71db329e 100644 --- a/web/core/modules/views/src/Plugin/views/style/StylePluginBase.php +++ b/web/core/modules/views/src/Plugin/views/style/StylePluginBase.php @@ -50,7 +50,7 @@ abstract class StylePluginBase extends PluginBase { protected $rowTokens = []; /** - * Does the style plugin allows to use style plugins. + * Whether or not this style uses a row plugin. * * @var bool */ diff --git a/web/core/modules/views/src/Plugin/views/style/Table.php b/web/core/modules/views/src/Plugin/views/style/Table.php index 00e28b3c6..9c9fbf1bf 100644 --- a/web/core/modules/views/src/Plugin/views/style/Table.php +++ b/web/core/modules/views/src/Plugin/views/style/Table.php @@ -30,9 +30,7 @@ class Table extends StylePluginBase implements CacheableDependencyInterface { protected $usesFields = TRUE; /** - * Does the style plugin allows to use style plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = FALSE; diff --git a/web/core/modules/views/src/Tests/ViewAjaxTest.php b/web/core/modules/views/src/Tests/ViewAjaxTest.php index b8b2730e6..5a966a8f7 100644 --- a/web/core/modules/views/src/Tests/ViewAjaxTest.php +++ b/web/core/modules/views/src/Tests/ViewAjaxTest.php @@ -17,7 +17,7 @@ class ViewAjaxTest extends ViewTestBase { * * @var array */ - public static $testViews = ['test_ajax_view']; + public static $testViews = ['test_ajax_view', 'test_view']; protected function setUp() { parent::setUp(); @@ -61,4 +61,14 @@ class ViewAjaxTest extends ViewTestBase { $this->assertEqual(count($result), 2, 'Ensure that two items are rendered in the HTML.'); } + /** + * Ensures that non-ajax view cannot be accessed via an ajax HTTP request. + */ + public function testNonAjaxViewViaAjax() { + $this->drupalPost('views/ajax', '', ['view_name' => 'test_ajax_view', 'view_display_id' => 'default'], ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); + $this->assertResponse(200); + $this->drupalPost('views/ajax', '', ['view_name' => 'test_view', 'view_display_id' => 'default'], ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); + $this->assertResponse(403); + } + } diff --git a/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTemplateTest.php b/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTemplateTest.php index d64883c72..b924d90e2 100644 --- a/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTemplateTest.php +++ b/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTemplateTest.php @@ -20,9 +20,7 @@ use Drupal\views\Plugin\views\style\StylePluginBase; class StyleTemplateTest extends StylePluginBase { /** - * Can the style plugin use row plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTest.php b/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTest.php index 9c0c3d707..fa6f57f60 100644 --- a/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTest.php +++ b/web/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/StyleTest.php @@ -29,9 +29,7 @@ class StyleTest extends StylePluginBase { public $output; /** - * Can the style plugin use row plugins. - * - * @var bool + * {@inheritdoc} */ protected $usesRowPlugin = TRUE; diff --git a/web/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php b/web/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php index c34e6f2a0..fbf5f4145 100644 --- a/web/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php +++ b/web/core/modules/views/tests/src/Functional/TaxonomyGlossaryTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\views\Functional; -use Drupal\taxonomy\Tests\TaxonomyTestTrait; +use Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait; /** * Tests glossary functionality of taxonomy views. diff --git a/web/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php b/web/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php index f766975e4..a02f098cd 100644 --- a/web/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php +++ b/web/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php @@ -18,6 +18,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class ViewAjaxControllerTest extends UnitTestCase { + const USE_AJAX = TRUE; + const USE_NO_AJAX = FALSE; + /** * The mocked view entity storage. * @@ -186,23 +189,6 @@ class ViewAjaxControllerTest extends UnitTestCase { list($view, $executable) = $this->setupValidMocks(); - $display_handler = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase') - ->disableOriginalConstructor() - ->getMock(); - // Ensure that the pager element is not set. - $display_handler->expects($this->never()) - ->method('setOption'); - - $display_collection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection') - ->disableOriginalConstructor() - ->getMock(); - $display_collection->expects($this->any()) - ->method('get') - ->with('page_1') - ->will($this->returnValue($display_handler)); - - $executable->displayHandlers = $display_collection; - $this->redirectDestination->expects($this->atLeastOnce()) ->method('set') ->with('/test-page?type=article'); @@ -215,6 +201,24 @@ class ViewAjaxControllerTest extends UnitTestCase { $this->assertViewResultCommand($response); } + /** + * Tests a valid view without ajax enabled. + */ + public function testAjaxViewWithoutAjax() { + $request = new Request(); + $request->request->set('view_name', 'test_view'); + $request->request->set('view_display_id', 'page_1'); + $request->request->set('view_path', '/test-page'); + $request->request->set('_wrapper_format', 'ajax'); + $request->request->set('ajax_page_state', 'drupal.settings[]'); + $request->request->set('type', 'article'); + + $this->setupValidMocks(static::USE_NO_AJAX); + + $this->setExpectedException(AccessDeniedHttpException::class); + $this->viewAjaxController->ajaxView($request); + } + /** * Tests a valid view with arguments. */ @@ -297,8 +301,15 @@ class ViewAjaxControllerTest extends UnitTestCase { /** * Sets up a bunch of valid mocks like the view entity and executable. + * + * @param bool $use_ajax + * Whether the 'use_ajax' option is set on the view display. Defaults to + * using ajax (TRUE). + * + * @return array + * A pair of view storage entity and executable. */ - protected function setupValidMocks() { + protected function setupValidMocks($use_ajax = self::USE_AJAX) { $view = $this->getMockBuilder('Drupal\views\Entity\View') ->disableOriginalConstructor() ->getMock(); @@ -314,7 +325,10 @@ class ViewAjaxControllerTest extends UnitTestCase { $executable->expects($this->once()) ->method('access') ->will($this->returnValue(TRUE)); - $executable->expects($this->once()) + $executable->expects($this->any()) + ->method('setDisplay') + ->willReturn(TRUE); + $executable->expects($this->atMost(1)) ->method('preview') ->will($this->returnValue(['#markup' => 'View result'])); @@ -323,6 +337,28 @@ class ViewAjaxControllerTest extends UnitTestCase { ->with($view) ->will($this->returnValue($executable)); + $display_handler = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase') + ->disableOriginalConstructor() + ->getMock(); + // Ensure that the pager element is not set. + $display_handler->expects($this->never()) + ->method('setOption'); + $display_handler->expects($this->any()) + ->method('getOption') + ->with('use_ajax') + ->willReturn($use_ajax); + + $display_collection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection') + ->disableOriginalConstructor() + ->getMock(); + $display_collection->expects($this->any()) + ->method('get') + ->with('page_1') + ->will($this->returnValue($display_handler)); + + $executable->display_handler = $display_handler; + $executable->displayHandlers = $display_collection; + return [$view, $executable]; } diff --git a/web/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php b/web/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php index 0b33a5891..e8ff8d7d9 100644 --- a/web/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php +++ b/web/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php @@ -717,6 +717,50 @@ class FieldPluginBaseTest extends UnitTestCase { $this->assertEquals($expected, $field->getRenderTokens([])); } + /** + * Ensures proper token replacement when generating CSS classes. + * + * @covers ::elementClasses + * @covers ::elementLabelClasses + * @covers ::elementWrapperClasses + */ + public function testElementClassesWithTokens() { + $functions = [ + 'elementClasses' => 'element_class', + 'elementLabelClasses' => 'element_label_class', + 'elementWrapperClasses' => 'element_wrapper_class', + ]; + + $tokens = ['test_token' => 'foo']; + $test_class = 'test-class-without-token test-class-with-{{ test_token }}-token'; + $expected_result = 'test-class-without-token test-class-with-foo-token'; + + // Inline template to render the tokens. + $build = [ + '#type' => 'inline_template', + '#template' => $test_class, + '#context' => $tokens, + '#post_render' => [function() {}], + ]; + + // We're not testing the token rendering itself, just that the function + // being tested correctly handles tokens when generating the element's class + // attribute. + $this->renderer->expects($this->any()) + ->method('renderPlain') + ->with($build) + ->willReturn($expected_result); + + foreach ($functions as $callable => $option_name) { + $field = $this->setupTestField([$option_name => $test_class]); + $field->view->style_plugin = new \stdClass(); + $field->view->style_plugin->render_tokens[] = $tokens; + + $result = $field->{$callable}(0); + $this->assertEquals($expected_result, $result); + } + } + } class FieldPluginBaseTestField extends FieldPluginBase { diff --git a/web/core/modules/views_ui/src/Tests/PreviewTest.php b/web/core/modules/views_ui/src/Tests/PreviewTest.php index 95fba8c6a..c723cb3b7 100644 --- a/web/core/modules/views_ui/src/Tests/PreviewTest.php +++ b/web/core/modules/views_ui/src/Tests/PreviewTest.php @@ -114,6 +114,12 @@ class PreviewTest extends UITestBase { $settings->set('ui.show.sql_query.where', 'below')->save(); $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); $this->assertTrue(strpos($this->getRawContent(), 'view-test-preview') < strpos($this->getRawContent(), 'views-query-info'), 'Statistics shown below the preview.'); + + // Test that the preview title isn't double escaped. + $this->drupalPostForm("admin/structure/views/nojs/display/test_preview/default/title", $edit = ['title' => 'Double & escaped'], t('Apply')); + $this->drupalPostForm(NULL, [], t('Update preview')); + $elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => t('Double & escaped')]); + $this->assertEqual(1, count($elements)); } /** diff --git a/web/core/modules/views_ui/src/Tests/UITestBase.php b/web/core/modules/views_ui/src/Tests/UITestBase.php index 0b90e04d1..83f2f8598 100644 --- a/web/core/modules/views_ui/src/Tests/UITestBase.php +++ b/web/core/modules/views_ui/src/Tests/UITestBase.php @@ -6,6 +6,9 @@ use Drupal\views\Tests\ViewTestBase; /** * Provides a base class for testing the Views UI. + * + * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.x. + * Use \Drupal\Tests\views_ui\Functional\UITestBase. */ abstract class UITestBase extends ViewTestBase { @@ -48,6 +51,8 @@ abstract class UITestBase extends ViewTestBase { 'administer permissions', ]); $this->drupalLogin($this->fullAdminUser); + + @trigger_error('\Drupal\views_ui\Tests\UITestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.x. Instead, use \Drupal\Tests\views_ui\Functional\UITestBase', E_USER_DEPRECATED); } /** diff --git a/web/core/modules/views_ui/src/Tests/ViewEditTest.php b/web/core/modules/views_ui/src/Tests/ViewEditTest.php index 08c5cfe86..819a4391b 100644 --- a/web/core/modules/views_ui/src/Tests/ViewEditTest.php +++ b/web/core/modules/views_ui/src/Tests/ViewEditTest.php @@ -64,6 +64,12 @@ class ViewEditTest extends UITestBase { $this->assertIdentical($displays['test_1']['id'], 'test_1', 'New display ID matches the display ID key.'); $this->assertFalse(array_key_exists('attachment_1', $displays), 'Old display ID not found.'); + // Set to the same machine name and save the View. + $edit = ['display_id' => 'test_1']; + $this->drupalPostForm('admin/structure/views/nojs/display/test_view/test_1/display_id', $edit, 'Apply'); + $this->drupalPostForm(NULL, [], 'Save'); + $this->assertLink(t('test_1')); + // Test the form validation with invalid IDs. $machine_name_edit_url = 'admin/structure/views/nojs/display/test_view/test_1/display_id'; $error_text = t('Display name must be letters, numbers, or underscores only.'); diff --git a/web/core/modules/views_ui/src/ViewEditForm.php b/web/core/modules/views_ui/src/ViewEditForm.php index 67d122955..75b518fdc 100644 --- a/web/core/modules/views_ui/src/ViewEditForm.php +++ b/web/core/modules/views_ui/src/ViewEditForm.php @@ -275,7 +275,7 @@ class ViewEditForm extends ViewFormBase { // Rename display ids if needed. foreach ($executable->displayHandlers as $id => $display) { - if (!empty($display->display['new_id']) && empty($display->display['deleted'])) { + if (!empty($display->display['new_id']) && $display->display['new_id'] !== $display->display['id'] && empty($display->display['deleted'])) { $new_id = $display->display['new_id']; $display->display['id'] = $new_id; unset($display->display['new_id']); @@ -290,6 +290,9 @@ class ViewEditForm extends ViewFormBase { 'display_id' => $new_id, ]); } + elseif (isset($display->display['new_id'])) { + unset($display->display['new_id']); + } } $view->set('display', $displays); diff --git a/web/core/modules/views_ui/src/ViewUI.php b/web/core/modules/views_ui/src/ViewUI.php index b6841a84b..2e7fabd62 100644 --- a/web/core/modules/views_ui/src/ViewUI.php +++ b/web/core/modules/views_ui/src/ViewUI.php @@ -4,7 +4,6 @@ namespace Drupal\views_ui; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Timer; -use Drupal\Component\Utility\Xss; use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Views; @@ -688,7 +687,11 @@ class ViewUI implements ViewEntityInterface { '#template' => "{% trans 'Title' %}", ], ], - Xss::filterAdmin($executable->getTitle()), + [ + 'data' => [ + '#markup' => $executable->getTitle(), + ], + ], ]; if (isset($path)) { // @todo Views should expect and store a leading /. See: diff --git a/web/core/modules/views_ui/src/Tests/AnalyzeTest.php b/web/core/modules/views_ui/tests/src/Functional/AnalyzeTest.php similarity index 70% rename from web/core/modules/views_ui/src/Tests/AnalyzeTest.php rename to web/core/modules/views_ui/tests/src/Functional/AnalyzeTest.php index 83e25313d..32d1ae980 100644 --- a/web/core/modules/views_ui/src/Tests/AnalyzeTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/AnalyzeTest.php @@ -1,15 +1,13 @@ enableViewsTestModule(); - - // Add an admin user will full rights; - $this->admin = $this->drupalCreateUser(['administer views']); - } - /** * Tests that analyze works in general. */ public function testAnalyzeBasic() { - $this->drupalLogin($this->admin); + $this->drupalLogin($this->adminUser); $this->drupalGet('admin/structure/views/view/test_view/edit'); $this->assertLink(t('Analyze view')); // This redirects the user to the analyze form. $this->clickLink(t('Analyze view')); - $this->assertText(t('View analysis')); + $this->assertSession()->titleEquals('View analysis | Drupal'); foreach (['ok', 'warning', 'error'] as $type) { $xpath = $this->xpath('//div[contains(@class, :class)]', [':class' => $type]); diff --git a/web/core/modules/views_ui/src/Tests/AreaEntityUITest.php b/web/core/modules/views_ui/tests/src/Functional/AreaEntityUITest.php similarity index 93% rename from web/core/modules/views_ui/src/Tests/AreaEntityUITest.php rename to web/core/modules/views_ui/tests/src/Functional/AreaEntityUITest.php index ffe895ab0..d74575fd4 100644 --- a/web/core/modules/views_ui/src/Tests/AreaEntityUITest.php +++ b/web/core/modules/views_ui/tests/src/Functional/AreaEntityUITest.php @@ -1,6 +1,6 @@ drupalGet($view->urlInfo('edit-form')); // Add a global NULL argument to the view for testing argument placeholders. - $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/argument", ['name[views.null]' => 1], 'Add and configure contextual filters'); + $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/argument", ['name[views.null]' => TRUE], 'Add and configure contextual filters'); $this->drupalPostForm(NULL, [], 'Apply'); // Configure both the entity_test area header and the block header to // reference the given entities. - $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_block]' => 1], 'Add and configure header'); + $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_block]' => TRUE], 'Add and configure header'); $this->drupalPostForm(NULL, ['options[target]' => $block->id()], 'Apply'); - $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_entity_test]' => 1], 'Add and configure header'); + $this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_entity_test]' => TRUE], 'Add and configure header'); $this->drupalPostForm(NULL, ['options[target]' => $entity_test->id()], 'Apply'); $this->drupalPostForm(NULL, [], 'Save'); diff --git a/web/core/modules/views_ui/src/Tests/ArgumentValidatorTest.php b/web/core/modules/views_ui/tests/src/Functional/ArgumentValidatorTest.php similarity index 97% rename from web/core/modules/views_ui/src/Tests/ArgumentValidatorTest.php rename to web/core/modules/views_ui/tests/src/Functional/ArgumentValidatorTest.php index d94e682fb..5a33970f7 100644 --- a/web/core/modules/views_ui/src/Tests/ArgumentValidatorTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/ArgumentValidatorTest.php @@ -1,6 +1,6 @@ {$values['test']}(strpos($output, $values['false']), SafeMarkup::format('Expected custom boolean FALSE value %value in output for %type', ['%value' => $values['false'], '%type' => $type])); // Assert that we are using the correct template. - $this->setRawContent($output); - $this->assertText('llama', 'Loaded the correct views-view-field.html.twig template'); + $this->assertContains('llama', (string) $output); } } diff --git a/web/core/modules/views_ui/src/Tests/DefaultViewsTest.php b/web/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php similarity index 96% rename from web/core/modules/views_ui/src/Tests/DefaultViewsTest.php rename to web/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php index a709d1f41..91ee05be0 100644 --- a/web/core/modules/views_ui/src/Tests/DefaultViewsTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php @@ -1,6 +1,6 @@ drupalPlaceBlock('page_title_block'); + $this->placeBlock('page_title_block'); } /** @@ -228,9 +227,9 @@ class DefaultViewsTest extends UITestBase { * failure. Failure also results in a failed assertion. */ public function clickViewsOperationLink($label, $unique_href_part) { - $links = $this->xpath('//a[normalize-space(text())=:label]', [':label' => $label]); + $links = $this->xpath('//a[normalize-space(text())=:label]', [':label' => (string) $label]); foreach ($links as $link_index => $link) { - $position = strpos($link['href'], $unique_href_part); + $position = strpos($link->getAttribute('href'), $unique_href_part); if ($position !== FALSE) { $index = $link_index; break; @@ -238,7 +237,7 @@ class DefaultViewsTest extends UITestBase { } $this->assertTrue(isset($index), format_string('Link to "@label" containing @part found.', ['@label' => $label, '@part' => $unique_href_part])); if (isset($index)) { - return $this->clickLink($label, $index); + return $this->clickLink((string) $label, $index); } else { return FALSE; diff --git a/web/core/modules/views_ui/src/Tests/DisplayAttachmentTest.php b/web/core/modules/views_ui/tests/src/Functional/DisplayAttachmentTest.php similarity index 95% rename from web/core/modules/views_ui/src/Tests/DisplayAttachmentTest.php rename to web/core/modules/views_ui/tests/src/Functional/DisplayAttachmentTest.php index 480172bb3..057a785c2 100644 --- a/web/core/modules/views_ui/src/Tests/DisplayAttachmentTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DisplayAttachmentTest.php @@ -1,6 +1,6 @@ assertEscaped('Page'); $this->assertNoRaw('Page'); $result = $this->xpath('//a[@id = :id]', [':id' => 'views-attachment-1-displays']); - $this->assertEqual($result[0]->attributes()->title, t('Page')); + $this->assertEqual($result[0]->getAttribute('title'), t('Page')); $this->drupalPostForm(NULL, [], t('Save')); $view = Views::getView('test_attachment_ui'); @@ -50,7 +51,7 @@ class DisplayAttachmentTest extends UITestBase { $this->drupalPostForm($attachment_display_url, ['displays[default]' => 1, 'displays[page_1]' => 1], t('Apply')); $result = $this->xpath('//a[@id = :id]', [':id' => 'views-attachment-1-displays']); - $this->assertEqual($result[0]->attributes()->title, t('Multiple displays')); + $this->assertEqual($result[0]->getAttribute('title'), t('Multiple displays')); $this->drupalPostForm(NULL, [], t('Save')); $view = Views::getView('test_attachment_ui'); diff --git a/web/core/modules/views_ui/src/Tests/DisplayCRUDTest.php b/web/core/modules/views_ui/tests/src/Functional/DisplayCRUDTest.php similarity index 99% rename from web/core/modules/views_ui/src/Tests/DisplayCRUDTest.php rename to web/core/modules/views_ui/tests/src/Functional/DisplayCRUDTest.php index e29f0a94e..1e53c7110 100644 --- a/web/core/modules/views_ui/src/Tests/DisplayCRUDTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DisplayCRUDTest.php @@ -1,6 +1,6 @@ xpath('//div[@id="edit-displays"]/div'); $options = []; foreach ($result as $item) { - foreach ($item->input->attributes() as $attribute => $value) { - if ($attribute == 'value') { - $options[] = (string) $value; - } + $input_node = $item->find('css', 'input'); + if ($input_node->hasAttribute('value')) { + $options[] = $input_node->getAttribute('value'); } } diff --git a/web/core/modules/views_ui/src/Tests/DisplayPathTest.php b/web/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php similarity index 94% rename from web/core/modules/views_ui/src/Tests/DisplayPathTest.php rename to web/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php index d1d1732ba..f8e58e719 100644 --- a/web/core/modules/views_ui/src/Tests/DisplayPathTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php @@ -1,8 +1,10 @@ drupalPlaceBlock('page_title_block'); + $this->placeBlock('page_title_block'); } /** @@ -158,9 +161,14 @@ class DisplayPathTest extends UITestBase { $this->drupalGet('admin/structure/views/nojs/display/test_page_display_menu/page_5/menu'); $this->assertResponse(200); $menu_parent = $this->xpath('//select[@id="edit-menu-parent"]'); - $menu_options = (array) $menu_parent[0]->option; + $menu_options = (array) $menu_parent[0]->findAll('css', 'option'); unset($menu_options['@attributes']); + // Convert array to make the next assertion possible. + $menu_options = array_map(function($element) { + return $element->getText(); + }, $menu_options); + $this->assertEqual([ '', '-- My account', diff --git a/web/core/modules/views_ui/src/Tests/DisplayTest.php b/web/core/modules/views_ui/tests/src/Functional/DisplayTest.php similarity index 77% rename from web/core/modules/views_ui/src/Tests/DisplayTest.php rename to web/core/modules/views_ui/tests/src/Functional/DisplayTest.php index afb2c7ff0..44724b421 100644 --- a/web/core/modules/views_ui/src/Tests/DisplayTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DisplayTest.php @@ -1,10 +1,8 @@ drupalPostForm(NULL, [], t('Add @display', ['@display' => 'Block'])); $this->assertText('Block'); $this->assertNoText('Block 2'); - - // Views has special form handling in views_ui_form_button_was_clicked() - // to be able to change the submit button text via JS, this simulates what - // the JS is doing. - $this->drupalPostForm(NULL, [], NULL, [], [], NULL, '&op=Block'); - $this->assertText('Block'); - $this->assertText('Block 2'); } /** @@ -94,13 +85,13 @@ class DisplayTest extends UITestBase { $this->drupalGet($path_prefix); $this->assertFalse($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class does not appear after initial adding of a view.'); - $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', '', 'Make sure the disable button is visible.'); - $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', '', 'Make sure the enable button is not visible.'); + $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', NULL, 'Make sure the disable button is visible.'); + $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', NULL, 'Make sure the enable button is not visible.'); $this->drupalPostForm(NULL, [], 'Disable Page'); $this->assertTrue($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class appears once the display is marked as such.'); - $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', '', 'Make sure the disable button is not visible.'); - $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', '', 'Make sure the enable button is visible.'); + $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', NULL, 'Make sure the disable button is not visible.'); + $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', NULL, 'Make sure the enable button is visible.'); $this->drupalPostForm(NULL, [], 'Enable Page'); $this->assertFalse($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class does not appears once the display is enabled again.'); } @@ -145,7 +136,7 @@ class DisplayTest extends UITestBase { // Assert that the expected text is found in each area category. foreach ($areas as $type) { $element = $this->xpath('//div[contains(@class, :class)]/div', [':class' => $type]); - $this->assertEqual((string) $element[0], SafeMarkup::format('The selected display type does not use @type plugins', ['@type' => $type])); + $this->assertEqual($element[0]->getHtml(), SafeMarkup::format('The selected display type does not use @type plugins', ['@type' => $type])); } } @@ -160,7 +151,7 @@ class DisplayTest extends UITestBase { // Test the link text displays 'None' and not 'Block 1' $this->drupalGet($path); $result = $this->xpath("//a[contains(@href, :path)]", [':path' => $link_display_path]); - $this->assertEqual($result[0], t('None'), 'Make sure that the link option summary shows "None" by default.'); + $this->assertEqual($result[0]->getHtml(), t('None'), 'Make sure that the link option summary shows "None" by default.'); $this->drupalGet($link_display_path); $this->assertFieldChecked('edit-link-display-0'); @@ -171,7 +162,7 @@ class DisplayTest extends UITestBase { $this->drupalGet($path); $result = $this->xpath("//a[contains(@href, :path)]", [':path' => $link_display_path]); - $this->assertEqual($result[0], 'Page', 'Make sure that the link option summary shows the right linked display.'); + $this->assertEqual($result[0]->getHtml(), 'Page', 'Make sure that the link option summary shows the right linked display.'); $this->drupalPostForm($link_display_path, ['link_display' => 'custom_url', 'link_url' => 'a-custom-url'], t('Apply')); // The form redirects to the master display. @@ -186,40 +177,6 @@ class DisplayTest extends UITestBase { $this->assertFieldByName('link_url', 'a-custom-url'); } - /** - * Tests contextual links on Views page displays. - */ - public function testPageContextualLinks() { - $this->drupalLogin($this->drupalCreateUser(['administer views', 'access contextual links'])); - $view = View::load('test_display'); - $view->enable()->save(); - $this->container->get('router.builder')->rebuildIfNeeded(); - - // When no "main content" block is placed, we find a contextual link - // placeholder for editing just the view. - $this->drupalGet('test-display'); - $id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en'; - // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() - $this->assertRaw(' $id]) . '>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id])); - - // Get server-rendered contextual links. - // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks() - $post = ['ids[0]' => $id]; - $response = $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => 'test-display']]); - $this->assertResponse(200); - $json = Json::decode($response); - $this->assertIdentical($json[$id], ''); - - // When a "main content" is placed, we still find a contextual link - // placeholder for editing just the view (not the main content block). - // @see system_block_view_system_main_block_alter() - $this->drupalPlaceBlock('system_main_block', ['id' => 'main_content']); - $this->drupalGet('test-display'); - $id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en'; - // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() - $this->assertRaw(' $id]) . '>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id])); - } - /** * Tests that the view status is correctly reflected on the edit form. */ diff --git a/web/core/modules/views_ui/src/Tests/DuplicateTest.php b/web/core/modules/views_ui/tests/src/Functional/DuplicateTest.php similarity index 84% rename from web/core/modules/views_ui/src/Tests/DuplicateTest.php rename to web/core/modules/views_ui/tests/src/Functional/DuplicateTest.php index 1096ab431..91d88fa60 100644 --- a/web/core/modules/views_ui/src/Tests/DuplicateTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/DuplicateTest.php @@ -1,6 +1,6 @@ drupalPlaceBlock('page_title_block'); + $this->placeBlock('page_title_block'); } /** diff --git a/web/core/modules/views_ui/src/Tests/FieldUITest.php b/web/core/modules/views_ui/tests/src/Functional/FieldUITest.php similarity index 87% rename from web/core/modules/views_ui/src/Tests/FieldUITest.php rename to web/core/modules/views_ui/tests/src/Functional/FieldUITest.php index 4e8732369..dc3081f65 100644 --- a/web/core/modules/views_ui/src/Tests/FieldUITest.php +++ b/web/core/modules/views_ui/tests/src/Functional/FieldUITest.php @@ -1,6 +1,6 @@ drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); - $this->assertEqual((string) $result[0], '{{ age }} == Age'); + $this->assertEqual($result[0]->getHtml(), '{{ age }} == Age'); $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/id'; $this->drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); - $this->assertEqual((string) $result[0], '{{ age }} == Age'); - $this->assertEqual((string) $result[1], '{{ id }} == ID'); + $this->assertEqual(trim($result[0]->getHtml()), '{{ age }} == Age'); + $this->assertEqual(trim($result[1]->getHtml()), '{{ id }} == ID'); $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/name'; $this->drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); - $this->assertEqual((string) $result[0], '{{ age }} == Age'); - $this->assertEqual((string) $result[1], '{{ id }} == ID'); - $this->assertEqual((string) $result[2], '{{ name }} == Name'); + $this->assertEqual(trim($result[0]->getHtml()), '{{ age }} == Age'); + $this->assertEqual(trim($result[1]->getHtml()), '{{ id }} == ID'); + $this->assertEqual(trim($result[2]->getHtml()), '{{ name }} == Name'); $result = $this->xpath('//details[@id="edit-options-more"]'); $this->assertEqual(empty($result), TRUE, "Container 'more' is empty and should not be displayed."); @@ -71,7 +71,7 @@ class FieldUITest extends UITestBase { $edit_handler_url = '/admin/structure/views/ajax/handler-group/test_view/default/field/name'; $this->drupalGet($edit_handler_url); - $data = Json::decode($this->getRawContent()); + $data = Json::decode($this->getSession()->getPage()->getContent()); $this->assertEqual($data[3]['dialogOptions']['title'], 'Configure aggregation settings for field Views test: Name'); } diff --git a/web/core/modules/views_ui/src/Tests/FilterBooleanWebTest.php b/web/core/modules/views_ui/tests/src/Functional/FilterBooleanWebTest.php similarity index 89% rename from web/core/modules/views_ui/src/Tests/FilterBooleanWebTest.php rename to web/core/modules/views_ui/tests/src/Functional/FilterBooleanWebTest.php index a3e58d755..e6adfeea7 100644 --- a/web/core/modules/views_ui/src/Tests/FilterBooleanWebTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/FilterBooleanWebTest.php @@ -1,6 +1,6 @@ cssSelect('#edit-options-value--wrapper legend span'); - $this->assertEqual((string) $result[0], 'Status'); + $this->assertEqual($result[0]->getHtml(), 'Status'); $this->drupalPostForm(NULL, [], t('Expose filter')); $this->drupalPostForm(NULL, [], t('Grouped filters')); @@ -46,11 +46,11 @@ class FilterBooleanWebTest extends UITestBase { $this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/status'); $result = $this->xpath('//input[@name="options[group_info][group_items][1][value]"]'); - $this->assertEqual((int) $result[1]->attributes()->checked, 'checked'); + $this->assertEqual($result[1]->getAttribute('checked'), 'checked'); $result = $this->xpath('//input[@name="options[group_info][group_items][2][value]"]'); - $this->assertEqual((int) $result[2]->attributes()->checked, 'checked'); + $this->assertEqual($result[2]->getAttribute('checked'), 'checked'); $result = $this->xpath('//input[@name="options[group_info][group_items][3][value]"]'); - $this->assertEqual((int) $result[1]->attributes()->checked, 'checked'); + $this->assertEqual($result[1]->getAttribute('checked'), 'checked'); // Test that there is a remove link for each group. $this->assertEqual(count($this->cssSelect('a.views-remove-link')), 3); diff --git a/web/core/modules/views_ui/src/Tests/FilterNumericWebTest.php b/web/core/modules/views_ui/tests/src/Functional/FilterNumericWebTest.php similarity index 86% rename from web/core/modules/views_ui/src/Tests/FilterNumericWebTest.php rename to web/core/modules/views_ui/tests/src/Functional/FilterNumericWebTest.php index 104d62f54..8dc568de9 100644 --- a/web/core/modules/views_ui/src/Tests/FilterNumericWebTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/FilterNumericWebTest.php @@ -1,6 +1,6 @@ drupalPostForm('admin/structure/views/view/test_view/edit', [], 'Add Page'); + $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => $path], 'Apply'); + $this->drupalPostForm(NULL, [], t('Save')); + $this->drupalPostForm('admin/structure/views/nojs/add-handler/test_view/default/filter', ['name[views_test_data.age]' => TRUE], t('Add and configure @handler', ['@handler' => t('filter criteria')])); $this->drupalPostForm(NULL, [], t('Expose filter')); @@ -52,13 +58,13 @@ class FilterNumericWebTest extends UITestBase { $this->assertConfigSchemaByName('views.view.test_view'); // Test that the exposed filter works as expected. - $this->drupalPostForm(NULL, [], t('Update preview')); + $this->drupalGet('test_view-path'); $this->assertText('John'); $this->assertText('Paul'); $this->assertText('Ringo'); $this->assertText('George'); $this->assertText('Meredith'); - $this->drupalPostForm(NULL, ['age' => '2'], t('Update preview')); + $this->drupalPostForm(NULL, ['age' => '2'], 'Apply'); $this->assertText('John'); $this->assertText('Paul'); $this->assertNoText('Ringo'); @@ -75,13 +81,13 @@ class FilterNumericWebTest extends UITestBase { $this->assertConfigSchemaByName('views.view.test_view'); // Test that the filter works as expected. - $this->drupalPostForm(NULL, [], t('Update preview')); + $this->drupalGet('test_view-path'); $this->assertText('John'); $this->assertNoText('Paul'); $this->assertNoText('Ringo'); $this->assertNoText('George'); $this->assertNoText('Meredith'); - $this->drupalPostForm(NULL, ['age' => '26'], t('Update preview')); + $this->drupalPostForm(NULL, ['age' => '26'], t('Apply')); $this->assertNoText('John'); $this->assertText('Paul'); $this->assertNoText('Ringo'); @@ -106,7 +112,7 @@ class FilterNumericWebTest extends UITestBase { $this->assertRaw('', 'Max field label found'); $this->assertRaw('', 'Min field label found'); // Check that the description is shown in the right place. - $this->assertEqual(trim($this->cssSelect('.form-item-age-min .description')[0]), 'Description of the exposed filter'); + $this->assertEqual(trim($this->cssSelect('.form-item-age-min .description')[0]->getText()), 'Description of the exposed filter'); } } diff --git a/web/core/modules/views_ui/src/Tests/FilterUITest.php b/web/core/modules/views_ui/tests/src/Functional/FilterUITest.php similarity index 94% rename from web/core/modules/views_ui/src/Tests/FilterUITest.php rename to web/core/modules/views_ui/tests/src/Functional/FilterUITest.php index 1197fc6e0..18ada1bca 100644 --- a/web/core/modules/views_ui/src/Tests/FilterUITest.php +++ b/web/core/modules/views_ui/tests/src/Functional/FilterUITest.php @@ -1,15 +1,13 @@ drupalCreateContentType(['type' => 'page']); - $this->enableViewsTestModule(); } /** diff --git a/web/core/modules/views_ui/src/Tests/GroupByTest.php b/web/core/modules/views_ui/tests/src/Functional/GroupByTest.php similarity index 97% rename from web/core/modules/views_ui/src/Tests/GroupByTest.php rename to web/core/modules/views_ui/tests/src/Functional/GroupByTest.php index 4b564c518..4a45d85fe 100644 --- a/web/core/modules/views_ui/src/Tests/GroupByTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/GroupByTest.php @@ -1,6 +1,6 @@ drupalPlaceBlock('page_title_block'); + $this->placeBlock('page_title_block'); ViewTestData::createTestViews(get_class($this), ['node_test_views']); } @@ -208,11 +208,11 @@ class HandlerTest extends UITestBase { $text = 'Broken/missing handler'; - $this->assertIdentical((string) $result[0], $text, 'Ensure the broken handler text was found.'); + $this->assertIdentical($result[0]->getText(), $text, 'Ensure the broken handler text was found.'); $this->drupalGet($href); $result = $this->xpath('//h1[@class="page-title"]'); - $this->assertTrue(strpos((string) $result[0], $text) !== FALSE, 'Ensure the broken handler text was found.'); + $this->assertContains($text, $result[0]->getText(), 'Ensure the broken handler text was found.'); $original_configuration = [ 'field' => 'id_broken', diff --git a/web/core/modules/views_ui/src/Tests/NewViewConfigSchemaTest.php b/web/core/modules/views_ui/tests/src/Functional/NewViewConfigSchemaTest.php similarity index 90% rename from web/core/modules/views_ui/src/Tests/NewViewConfigSchemaTest.php rename to web/core/modules/views_ui/tests/src/Functional/NewViewConfigSchemaTest.php index 3318f0b64..ef493ff8c 100644 --- a/web/core/modules/views_ui/src/Tests/NewViewConfigSchemaTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/NewViewConfigSchemaTest.php @@ -1,15 +1,13 @@ drupalPlaceBlock('page_title_block'); } @@ -51,7 +51,7 @@ class OverrideDisplaysTest extends UITestBase { // Confirm that the view block is available in the block administration UI. $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); - $this->clickLinkPartialName('Place block'); + $this->clickLink('Place block'); $this->assertText($view['label']); // Place the block. @@ -111,7 +111,7 @@ class OverrideDisplaysTest extends UITestBase { // Confirm that the block is available in the block administration UI. $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); - $this->clickLinkPartialName('Place block'); + $this->clickLink('Place block'); $this->assertText($view['label']); // Put the block into the first sidebar region, and make sure it will not diff --git a/web/core/modules/views_ui/src/Tests/QueryTest.php b/web/core/modules/views_ui/tests/src/Functional/QueryTest.php similarity index 96% rename from web/core/modules/views_ui/src/Tests/QueryTest.php rename to web/core/modules/views_ui/tests/src/Functional/QueryTest.php index 066be3e56..0eb58ce71 100644 --- a/web/core/modules/views_ui/src/Tests/QueryTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/QueryTest.php @@ -1,6 +1,6 @@ adminUser = $this->drupalCreateUser(['administer views']); - } - /** * Tests the existence of the views plugin report. */ diff --git a/web/core/modules/views_ui/src/Tests/SettingsTest.php b/web/core/modules/views_ui/tests/src/Functional/SettingsTest.php similarity index 91% rename from web/core/modules/views_ui/src/Tests/SettingsTest.php rename to web/core/modules/views_ui/tests/src/Functional/SettingsTest.php index f583185cd..1ac98c6e6 100644 --- a/web/core/modules/views_ui/src/Tests/SettingsTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/SettingsTest.php @@ -1,6 +1,6 @@ drupalPlaceBlock('local_tasks_block'); } @@ -82,7 +82,7 @@ class SettingsTest extends UITestBase { $view['id'] = strtolower($this->randomMachineName()); $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); - $this->assertFieldById('edit-displays-top-add-display-embed'); + $this->assertFieldById('edit-displays-top-add-display-embed', NULL); $edit = [ 'ui_show_display_embed' => FALSE, @@ -116,8 +116,8 @@ class SettingsTest extends UITestBase { $this->drupalPostForm(NULL, [], t('Update preview')); $xpath = $this->xpath('//div[@class="views-query-info"]//pre'); $this->assertEqual(count($xpath), 1, 'The views sql is shown.'); - $this->assertFalse(strpos($xpath[0], 'db_condition_placeholder') !== FALSE, 'No placeholders are shown in the views sql.'); - $this->assertTrue(strpos($xpath[0], "node_field_data.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.'); + $this->assertFalse(strpos($xpath[0]->getText(), 'db_condition_placeholder') !== FALSE, 'No placeholders are shown in the views sql.'); + $this->assertTrue(strpos($xpath[0]->getText(), "node_field_data.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.'); // Test the advanced settings form. diff --git a/web/core/modules/views_ui/src/Tests/StorageTest.php b/web/core/modules/views_ui/tests/src/Functional/StorageTest.php similarity index 96% rename from web/core/modules/views_ui/src/Tests/StorageTest.php rename to web/core/modules/views_ui/tests/src/Functional/StorageTest.php index fa33b8f00..df3d030e7 100644 --- a/web/core/modules/views_ui/src/Tests/StorageTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/StorageTest.php @@ -1,6 +1,6 @@ enableViewsTestModule(); + + $this->adminUser = $this->drupalCreateUser(['administer views']); + + $this->fullAdminUser = $this->drupalCreateUser(['administer views', + 'administer blocks', + 'bypass node access', + 'access user profiles', + 'view all revisions', + 'administer permissions', + ]); + $this->drupalLogin($this->fullAdminUser); + } + + /** + * A helper method which creates a random view. + */ + public function randomView(array $view = []) { + // Create a new view in the UI. + $default = []; + $default['label'] = $this->randomMachineName(16); + $default['id'] = strtolower($this->randomMachineName(16)); + $default['description'] = $this->randomMachineName(16); + $default['page[create]'] = TRUE; + $default['page[path]'] = $default['id']; + + $view += $default; + + $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); + + return $default; + } + + /** + * {@inheritdoc} + */ + protected function drupalGet($path, array $options = [], array $headers = []) { + $url = $this->buildUrl($path, $options); + + // Ensure that each nojs page is accessible via ajax as well. + if (strpos($url, 'nojs') !== FALSE) { + $url = str_replace('nojs', 'ajax', $url); + $result = $this->drupalGet($url, $options); + $this->assertSession()->statusCodeEquals(200); + $this->assertEquals('application/json', $this->getSession()->getResponseHeader('Content-Type')); + $this->assertTrue(json_decode($result), 'Ensure that the AJAX request returned valid content.'); + } + + return parent::drupalGet($path, $options, $headers); + } + +} diff --git a/web/core/modules/views_ui/src/Tests/UnsavedPreviewTest.php b/web/core/modules/views_ui/tests/src/Functional/UnsavedPreviewTest.php similarity index 92% rename from web/core/modules/views_ui/src/Tests/UnsavedPreviewTest.php rename to web/core/modules/views_ui/tests/src/Functional/UnsavedPreviewTest.php index 6418fc086..3265e1a2f 100644 --- a/web/core/modules/views_ui/src/Tests/UnsavedPreviewTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/UnsavedPreviewTest.php @@ -1,15 +1,13 @@ adminUser = $this->drupalCreateUser(['administer views']); diff --git a/web/core/modules/views_ui/src/Tests/ViewsListTest.php b/web/core/modules/views_ui/tests/src/Functional/ViewsListTest.php similarity index 89% rename from web/core/modules/views_ui/src/Tests/ViewsListTest.php rename to web/core/modules/views_ui/tests/src/Functional/ViewsListTest.php index 51786746c..956ab9bc0 100644 --- a/web/core/modules/views_ui/src/Tests/ViewsListTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/ViewsListTest.php @@ -1,8 +1,7 @@ drupalPlaceBlock('local_tasks_block'); $this->drupalPlaceBlock('local_actions_block'); diff --git a/web/core/modules/views_ui/src/Tests/WizardTest.php b/web/core/modules/views_ui/tests/src/Functional/WizardTest.php similarity index 96% rename from web/core/modules/views_ui/src/Tests/WizardTest.php rename to web/core/modules/views_ui/tests/src/Functional/WizardTest.php index 4e57e8f7b..81154817e 100644 --- a/web/core/modules/views_ui/src/Tests/WizardTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/WizardTest.php @@ -1,8 +1,8 @@ drupalCreateUser([ + 'administer site configuration', + 'administer views', + 'administer nodes', + 'access content overview', + 'access contextual links', + ]); + + // Disable automatic live preview to make the sequence of calls clearer. + \Drupal::configFactory()->getEditable('views.settings')->set('ui.always_live_preview', FALSE)->save(); + $this->drupalLogin($admin_user); + } + + /** + * Tests adding a display. + */ + public function testAddDisplay() { + $this->drupalGet('admin/structure/views/view/test_content_ajax'); + $page = $this->getSession()->getPage(); + + $page->find('css', '#views-display-menu-tabs .add')->click(); + + // Wait for the animation to complete. + $this->assertSession()->assertWaitOnAjaxRequest(); + + // Add the diplay. + $page->find('css', '#edit-displays-top-add-display-block')->click(); + + $element = $page->findById('views-display-menu-tabs')->findLink('Block'); + $this->assertNotEmpty($element); + } + + /** + * Tests contextual links on Views page displays. + */ + public function testPageContextualLinks() { + $view = View::load('test_display'); + $view->enable()->save(); + $this->container->get('router.builder')->rebuildIfNeeded(); + + // Create node so the view has content and the contextual area is higher + // than 0 pixels. + $this->drupalCreateContentType(['type' => 'page']); + $this->createNode(); + + // When no "main content" block is placed, we find a contextual link + // placeholder for editing just the view. + $this->drupalGet('test-display'); + $page = $this->getSession()->getPage(); + $this->assertSession()->assertWaitOnAjaxRequest(); + + $selector = '.view-test-display'; + $this->toggleContextualTriggerVisibility($selector); + + $element = $this->getSession()->getPage()->find('css', $selector); + $element->find('css', '.contextual button')->press(); + + $contextual_container_id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en'; + $contextual_container = $page->find('css', '[data-contextual-id="' . $contextual_container_id . '"]'); + $this->assertNotEmpty($contextual_container); + + $edit_link = $contextual_container->findLink('Edit view'); + $this->assertNotEmpty($edit_link); + + // When a "main content" is placed, we still find a contextual link + // placeholder for editing just the view (not the main content block). + // @see system_block_view_system_main_block_alter() + $this->drupalPlaceBlock('system_main_block', ['id' => 'main_content']); + $contextual_container = $page->find('css', '[data-contextual-id="' . $contextual_container_id . '"]'); + $this->assertNotEmpty($contextual_container); + } + + /** + * Toggles the visibility of a contextual trigger. + * + * @param string $selector + * The selector for the element that contains the contextual Rink. + */ + protected function toggleContextualTriggerVisibility($selector) { + // Hovering over the element itself with should be enough, but does not + // work. Manually remove the visually-hidden class. + $this->getSession()->executeScript("jQuery('{$selector} .contextual .trigger').toggleClass('visually-hidden');"); + } + +} diff --git a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index 3689dddbc..3a0750113 100644 --- a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -503,4 +503,18 @@ class BrowserTestBaseTest extends BrowserTestBase { $this->assertTrue(file_exists($htaccess_filename), "$htaccess_filename exists"); } + /** + * Tests the assumption that local time is in 'Australia/Sydney'. + */ + public function testLocalTimeZone() { + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + $this->assertEquals('Australia/Sydney', date_default_timezone_get()); + + // The 'Australia/Sydney' time zone is also set in + // FunctionalTestSetupTrait::initConfig(). + $config_factory = $this->container->get('config.factory'); + $value = $config_factory->get('system.date')->get('timezone.default'); + $this->assertEquals('Australia/Sydney', $value); + } + } diff --git a/web/core/modules/system/src/Tests/Image/ToolkitSetupFormTest.php b/web/core/tests/Drupal/FunctionalTests/Image/ToolkitSetupFormTest.php similarity index 94% rename from web/core/modules/system/src/Tests/Image/ToolkitSetupFormTest.php rename to web/core/tests/Drupal/FunctionalTests/Image/ToolkitSetupFormTest.php index 7dc9d3387..d501f1d98 100644 --- a/web/core/modules/system/src/Tests/Image/ToolkitSetupFormTest.php +++ b/web/core/tests/Drupal/FunctionalTests/Image/ToolkitSetupFormTest.php @@ -1,15 +1,15 @@ imageFactory = $this->container->get('image.factory'); + + // Pick a file for testing. + $file = current($this->drupalGetTestFiles('image')); + $this->file = $file->uri; + + // Setup a dummy image to work with. + $this->image = $this->getImage(); + + // Clear out any hook calls. + $this->imageTestReset(); + } + + /** + * Sets up an image with the custom toolkit. + * + * @return \Drupal\Core\Image\ImageInterface + * The image object. + */ + protected function getImage() { + $image = $this->imageFactory->get($this->file, 'test'); + $this->assertTrue($image->isValid(), 'Image file was parsed.'); + return $image; + } + + /** + * Assert that all of the specified image toolkit operations were called + * exactly once once, other values result in failure. + * + * @param $expected + * Array with string containing with the operation name, e.g. 'load', + * 'save', 'crop', etc. + */ + public function assertToolkitOperationsCalled(array $expected) { + // If one of the image operations is expected, apply should be expected as + // well. + $operations = [ + 'resize', + 'rotate', + 'crop', + 'desaturate', + 'create_new', + 'scale', + 'scale_and_crop', + 'my_operation', + 'convert', + ]; + if (count(array_intersect($expected, $operations)) > 0 && !in_array('apply', $expected)) { + $expected[] = 'apply'; + } + + // Determine which operations were called. + $actual = array_keys(array_filter($this->imageTestGetAllCalls())); + + // Determine if there were any expected that were not called. + $uncalled = array_diff($expected, $actual); + if (count($uncalled)) { + $this->assertTrue(FALSE, SafeMarkup::format('Expected operations %expected to be called but %uncalled was not called.', ['%expected' => implode(', ', $expected), '%uncalled' => implode(', ', $uncalled)])); + } + else { + $this->assertTrue(TRUE, SafeMarkup::format('All the expected operations were called: %expected', ['%expected' => implode(', ', $expected)])); + } + + // Determine if there were any unexpected calls. + // If all unexpected calls are operations and apply was expected, we do not + // count it as an error. + $unexpected = array_diff($actual, $expected); + if (count($unexpected) && (!in_array('apply', $expected) || count(array_intersect($unexpected, $operations)) !== count($unexpected))) { + $this->assertTrue(FALSE, SafeMarkup::format('Unexpected operations were called: %unexpected.', ['%unexpected' => implode(', ', $unexpected)])); + } + else { + $this->assertTrue(TRUE, 'No unexpected operations were called.'); + } + } + + /** + * Resets/initializes the history of calls to the test toolkit functions. + */ + protected function imageTestReset() { + // Keep track of calls to these operations + $results = [ + 'parseFile' => [], + 'save' => [], + 'settings' => [], + 'apply' => [], + 'resize' => [], + 'rotate' => [], + 'crop' => [], + 'desaturate' => [], + 'create_new' => [], + 'scale' => [], + 'scale_and_crop' => [], + 'convert' => [], + ]; + \Drupal::state()->set('image_test.results', $results); + } + + /** + * Gets an array of calls to the test toolkit. + * + * @return array + * An array keyed by operation name ('parseFile', 'save', 'settings', + * 'resize', 'rotate', 'crop', 'desaturate') with values being arrays of + * parameters passed to each call. + */ + protected function imageTestGetAllCalls() { + return \Drupal::state()->get('image_test.results') ?: []; + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php b/web/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php index e55590e7e..d0439c5f1 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php @@ -4,7 +4,7 @@ namespace Drupal\KernelTests\Core\Database; use Drupal\Core\Database\RowCountException; use Drupal\Core\Database\StatementInterface; -use Drupal\system\Tests\Database\FakeRecord; +use Drupal\Tests\system\Functional\Database\FakeRecord; /** * Tests the Database system's various fetch capabilities. @@ -69,7 +69,7 @@ class FetchTest extends DatabaseTestBase { */ public function testQueryFetchClass() { $records = []; - $result = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 25], ['fetch' => 'Drupal\system\Tests\Database\FakeRecord']); + $result = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 25], ['fetch' => FakeRecord::class]); foreach ($result as $record) { $records[] = $record; if ($this->assertTrue($record instanceof FakeRecord, 'Record is an object of class FakeRecord.')) { diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityAccessControlHandlerTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityAccessControlHandlerTest.php index d7644b205..b3af27fba 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityAccessControlHandlerTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityAccessControlHandlerTest.php @@ -9,7 +9,9 @@ use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Session\AnonymousUserSession; use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestDefaultAccess; +use Drupal\entity_test\Entity\EntityTestNoUuid; use Drupal\entity_test\Entity\EntityTestLabel; +use Drupal\entity_test\Entity\EntityTestRev; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\user\Entity\User; @@ -20,6 +22,16 @@ use Drupal\user\Entity\User; */ class EntityAccessControlHandlerTest extends EntityLanguageTestBase { + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + $this->installEntitySchema('entity_test_no_uuid'); + $this->installEntitySchema('entity_test_rev'); + } + /** * Asserts entity access correctly grants or denies access. */ @@ -199,6 +211,64 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase { ], $translation); } + /** + * Ensures the static access cache works correctly in the absence of an UUID. + * + * @see entity_test_entity_access() + */ + public function testEntityWithoutUuidAccessCache() { + $account = $this->createUser(); + + $entity1 = EntityTestNoUuid::create([ + 'name' => 'Accessible', + ]); + $entity1->save(); + + $entity2 = EntityTestNoUuid::create([ + 'name' => 'Inaccessible', + ]); + $entity2->save(); + + $this->assertTrue($entity1->access('delete', $account), 'Entity 1 can be deleted.'); + $this->assertFalse($entity2->access('delete', $account), 'Entity 2 CANNOT be deleted.'); + + $entity1 + ->setName('Inaccessible') + ->setNewRevision(); + $entity1->save(); + + $this->assertFalse($entity1->access('delete', $account), 'Entity 1 revision 2 CANNOT be deleted.'); + } + + /** + * Ensures the static access cache works correctly with a UUID and revisions. + * + * @see entity_test_entity_access() + */ + public function testEntityWithUuidAccessCache() { + $account = $this->createUser(); + + $entity1 = EntityTestRev::create([ + 'name' => 'Accessible', + ]); + $entity1->save(); + + $entity2 = EntityTestRev::create([ + 'name' => 'Inaccessible', + ]); + $entity2->save(); + + $this->assertTrue($entity1->access('delete', $account), 'Entity 1 can be deleted.'); + $this->assertFalse($entity2->access('delete', $account), 'Entity 2 CANNOT be deleted.'); + + $entity1 + ->setName('Inaccessible') + ->setNewRevision(); + $entity1->save(); + + $this->assertFalse($entity1->access('delete', $account), 'Entity 1 revision 2 CANNOT be deleted.'); + } + /** * Tests hook invocations. */ diff --git a/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php b/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php index 9436115ff..704863279 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php @@ -216,4 +216,62 @@ class AliasTest extends PathUnitTestBase { $this->assertEqual($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 0); } + /** + * Tests situation where the whitelist cache is deleted mid-request. + */ + public function testWhitelistCacheDeletionMidRequest() { + // Prepare database table. + $connection = Database::getConnection(); + $this->fixtures->createTables($connection); + + $memoryCounterBackend = new MemoryCounterBackend(); + + // Create AliasManager and Path object. + $aliasStorage = new AliasStorage($connection, $this->container->get('module_handler')); + $whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $aliasStorage); + $aliasManager = new AliasManager($aliasStorage, $whitelist, $this->container->get('language_manager'), $memoryCounterBackend); + + // Whitelist cache should not exist at all yet. + $this->assertFalse($memoryCounterBackend->get('path_alias_whitelist')); + + // Add some aliases for both menu routes we have. + $aliasStorage->save('/admin/something', '/' . $this->randomMachineName()); + $aliasStorage->save('/user/something', '/' . $this->randomMachineName()); + $aliasManager->cacheClear(); + + // Lookup admin path in whitelist. It will query the DB and figure out + // that it indeed has an alias, and add it to the internal whitelist and + // flag it to be peristed to cache. + $this->assertTrue($whitelist->get('admin')); + + // Destruct the whitelist so it persists its cache. + $whitelist->destruct(); + $this->assertEquals($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 1); + // Cache data should have data for 'user' and 'admin', even though just + // 'admin' was looked up. This is because the cache is primed with all + // menu router base paths. + $this->assertEquals(['user' => FALSE, 'admin' => TRUE], $memoryCounterBackend->get('path_alias_whitelist')->data); + $memoryCounterBackend->resetCounter(); + + // Re-initialize the the whitelist and lookup an alias for the 'user' path. + // Whitelist should load data from its cache, see that it hasn't done a + // check for 'user' yet, perform the check, then mark the result to be + // persisted to cache. + $whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $aliasStorage); + $this->assertTrue($whitelist->get('user')); + + // Delete the whitelist cache. This could happen from an outside process, + // like a code deployment that performs a cache rebuild. + $memoryCounterBackend->delete('path_alias_whitelist'); + + // Destruct whitelist so it attempts to save the whitelist data to cache. + // However it should recognize that the previous cache entry was deleted + // from underneath it and not save anything to cache, to protect from + // cache corruption. + $whitelist->destruct(); + $this->assertEquals($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 0); + $this->assertFalse($memoryCounterBackend->get('path_alias_whitelist')); + $memoryCounterBackend->resetCounter(); + } + } diff --git a/web/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/web/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 8ec7c5497..817d894d4 100644 --- a/web/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/web/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -214,6 +214,14 @@ class KernelTestBaseTest extends KernelTestBase { $this->assertEquals('public', \Drupal::config('system.file')->get('default_scheme')); } + /** + * Tests the assumption that local time is in 'Australia/Sydney'. + */ + public function testLocalTimeZone() { + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + $this->assertEquals('Australia/Sydney', date_default_timezone_get()); + } + /** * {@inheritdoc} */ diff --git a/web/core/tests/Drupal/Tests/Core/Block/BlockManagerTest.php b/web/core/tests/Drupal/Tests/Core/Block/BlockManagerTest.php new file mode 100644 index 000000000..1e9bb436d --- /dev/null +++ b/web/core/tests/Drupal/Tests/Core/Block/BlockManagerTest.php @@ -0,0 +1,89 @@ +prophesize(CacheBackendInterface::class); + $module_handler = $this->prophesize(ModuleHandlerInterface::class); + $this->blockManager = new BlockManager(new \ArrayObject(), $cache_backend->reveal(), $module_handler->reveal()); + $this->blockManager->setStringTranslation($this->getStringTranslationStub()); + + $discovery = $this->prophesize(DiscoveryInterface::class); + // Specify the 'broken' block, as well as 3 other blocks with admin labels + // that are purposefully not in alphabetical order. + $discovery->getDefinitions()->willReturn([ + 'broken' => [ + 'admin_label' => 'Broken/Missing', + 'category' => 'Block', + ], + 'block1' => [ + 'admin_label' => 'Coconut', + 'category' => 'Group 2', + ], + 'block2' => [ + 'admin_label' => 'Apple', + 'category' => 'Group 1', + ], + 'block3' => [ + 'admin_label' => 'Banana', + 'category' => 'Group 2', + ], + ]); + // Force the discovery object onto the block manager. + $property = new \ReflectionProperty(BlockManager::class, 'discovery'); + $property->setAccessible(TRUE); + $property->setValue($this->blockManager, $discovery->reveal()); + } + + /** + * @covers ::getDefinitions + */ + public function testDefinitions() { + $definitions = $this->blockManager->getDefinitions(); + $this->assertSame(['broken', 'block1', 'block2', 'block3'], array_keys($definitions)); + } + + /** + * @covers ::getSortedDefinitions + */ + public function testSortedDefinitions() { + $definitions = $this->blockManager->getSortedDefinitions(); + $this->assertSame(['block2', 'block3', 'block1'], array_keys($definitions)); + } + + /** + * @covers ::getGroupedDefinitions + */ + public function testGroupedDefinitions() { + $definitions = $this->blockManager->getGroupedDefinitions(); + $this->assertSame(['Group 1', 'Group 2'], array_keys($definitions)); + $this->assertSame(['block2'], array_keys($definitions['Group 1'])); + $this->assertSame(['block3', 'block1'], array_keys($definitions['Group 2'])); + } + +} diff --git a/web/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php b/web/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php index 1ff662939..0c06a4b86 100644 --- a/web/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php +++ b/web/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php @@ -327,7 +327,8 @@ class CacheCollectorTest extends UnitTestCase { // invalidation. $this->cacheBackend->expects($this->at(0)) ->method('get') - ->with($this->cid, TRUE); + ->with($this->cid, TRUE) + ->will($this->returnValue($cache)); $this->cacheBackend->expects($this->once()) ->method('set') ->with($this->cid, [], Cache::PERMANENT, []); diff --git a/web/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php b/web/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php index 0ba814342..fa50e45d5 100644 --- a/web/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php +++ b/web/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php @@ -94,6 +94,14 @@ class TestSuiteBaseTest extends \PHPUnit_Framework_TestCase { $this->assertEmpty(array_diff_assoc($expected_tests, $stub->testFiles)); } + /** + * Tests the assumption that local time is in 'Australia/Sydney'. + */ + public function testLocalTimeZone() { + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + $this->assertEquals('Australia/Sydney', date_default_timezone_get()); + } + } /** -- 2.30.2