From da9ac824c9a65a218cc7a35cfb4cc5f12d3a1dd6 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Thu, 15 Jun 2023 21:57:23 +0200 Subject: [PATCH 1/8] #23: Ogrodje za endpoint za dodajanje konceptov. --- .../src/Plugin/rest/resource/AddConcept.php | 163 ++++++++++++++++++ .../yufu_concept/tests/local-emacs-test.rest | 12 ++ .../custom/yufu_concept/yufu_concept.info.yml | 7 + .../custom/yufu_concept/yufu_concept.module | 6 + 4 files changed, 188 insertions(+) create mode 100644 web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php create mode 100644 web/modules/custom/yufu_concept/tests/local-emacs-test.rest create mode 100644 web/modules/custom/yufu_concept/yufu_concept.info.yml create mode 100644 web/modules/custom/yufu_concept/yufu_concept.module diff --git a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php new file mode 100644 index 0000000..1d8800d --- /dev/null +++ b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php @@ -0,0 +1,163 @@ +currentUser = $current_user; + $this->mailManager = $mailManager; + $this->config = $configFactory->get('system.site'); + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->getParameter('serializer.formats'), + $container->get('logger.factory')->get('custom_rest'), + $container->get('current_user'), + $container->get('plugin.manager.mail'), + $container->get('config.factory'), + $container->get('entity_type.manager') + ); + } + + /** + * Send a test email. + * + * @param $data + * Post date. + * + * @return \Drupal\rest\ResourceResponse + * Returns rest resource. + */ + public function post($data) { + $response_status['status'] = FALSE; + // You must to implement the logic of your REST Resource here. + // Use current user after pass authentication to validate access. + if (!$this->currentUser->hasPermission('access content')) { + throw new AccessDeniedHttpException(); + } + // Fields: naslov, text, povezani pojmi, email + // Optional fields: language, related concept. + if (!empty($data['title']) && !empty($data['text'])) { + throw new MissingDataException('Title or text missing.'); + } + $concept = [ + 'type' => 'concept', + 'title' => $data['title'], + 'body' => $data['text'], + ]; + // @TODO Check if related concepts are set and add them to the concept. + // @TODO Check language and add set it on concept if exists. + $concept = $this->entityTypeManger->getStorage('node')->create($concept); + $concept->save(); + + if (!empty($data['email'])) { + // @TODO Poslji mail uporabniku, da se lahko registrira. + $site_email = $this->config->get('mail'); + $module = 'yufu_concept'; + $key = 'notice'; + $to = $site_email; + // Send email to user to make him register to the website. + $params['message'] = $data['message']['value']; + $params['title'] = $data['subject']['value']; + $params['from'] = $data['email']['value']; + $langcode = $data['lang']['value']; + $send = TRUE; + + $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send); + $response_status['status'] = $result['result']; + } + $response = new ResourceResponse($response_status); + return $response; + } + +} diff --git a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest new file mode 100644 index 0000000..daaa1c3 --- /dev/null +++ b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest @@ -0,0 +1,12 @@ +# _*_ restclient _*_ + +# Makes post http request to a resource from yufu_concept module. + +POST https://yufu-manifest.ddev.site/api/pojem/dodaj +User-Agent: Emacs Restclient +Content-Type: application/json + +{ +"title": "Emacs restclient test", +"body": "O wau. Emacs restclient. How nice." +} \ No newline at end of file diff --git a/web/modules/custom/yufu_concept/yufu_concept.info.yml b/web/modules/custom/yufu_concept/yufu_concept.info.yml new file mode 100644 index 0000000..cfc664a --- /dev/null +++ b/web/modules/custom/yufu_concept/yufu_concept.info.yml @@ -0,0 +1,7 @@ +name: Yufu Concept +type: module +description: Provides concept content type related functionality. +package: Yufu +core_version_requirement: ^9 || ^10 +dependencies: + - drupal:rest diff --git a/web/modules/custom/yufu_concept/yufu_concept.module b/web/modules/custom/yufu_concept/yufu_concept.module new file mode 100644 index 0000000..0a8a750 --- /dev/null +++ b/web/modules/custom/yufu_concept/yufu_concept.module @@ -0,0 +1,6 @@ + Date: Sat, 30 Sep 2023 20:02:02 +0200 Subject: [PATCH 2/8] Endpoint dodaj pojem deluje. --- README.md | 9 + composer.json | 11 +- composer.lock | 218 ++++++++++++++++-- ...tity_form_display.node.concept.default.yml | 32 ++- .../core.entity_view_mode.block.token.yml | 10 + ...e.entity_view_mode.block_content.token.yml | 10 + .../core.entity_view_mode.comment.token.yml | 10 + ...ew_mode.content_moderation_state.token.yml | 10 + .../sync/core.entity_view_mode.file.token.yml | 10 + .../core.entity_view_mode.media.token.yml | 10 + ...tity_view_mode.menu_link_content.token.yml | 10 + .../sync/core.entity_view_mode.node.token.yml | 10 + ...core.entity_view_mode.path_alias.token.yml | 10 + ...e.entity_view_mode.taxonomy_term.token.yml | 10 + .../sync/core.entity_view_mode.user.token.yml | 10 + config/sync/core.extension.yml | 4 + config/sync/dblog.settings.yml | 2 +- .../hr/views.view.moderated_content.yml | 29 +++ .../sl/views.view.moderated_content.yml | 29 +++ .../sr/views.view.moderated_content.yml | 29 +++ ...est.resource.add_concept_rest_resource.yml | 18 ++ config/sync/system.logging.yml | 2 +- config/sync/user.role.anonymous.yml | 4 + config/sync/user.role.authenticated.yml | 4 + config/sync/user.role.editor.yml | 3 + config/sync/views.view.moderated_content.yml | 21 +- web/modules/custom/yufu_concept/README.md | 15 ++ .../src/Plugin/rest/resource/AddConcept.php | 67 ++++-- .../yufu_concept/tests/local-emacs-test.rest | 8 +- .../custom/yufu_concept/yufu_concept.module | 18 ++ 30 files changed, 567 insertions(+), 66 deletions(-) create mode 100644 config/sync/core.entity_view_mode.block.token.yml create mode 100644 config/sync/core.entity_view_mode.block_content.token.yml create mode 100644 config/sync/core.entity_view_mode.comment.token.yml create mode 100644 config/sync/core.entity_view_mode.content_moderation_state.token.yml create mode 100644 config/sync/core.entity_view_mode.file.token.yml create mode 100644 config/sync/core.entity_view_mode.media.token.yml create mode 100644 config/sync/core.entity_view_mode.menu_link_content.token.yml create mode 100644 config/sync/core.entity_view_mode.node.token.yml create mode 100644 config/sync/core.entity_view_mode.path_alias.token.yml create mode 100644 config/sync/core.entity_view_mode.taxonomy_term.token.yml create mode 100644 config/sync/core.entity_view_mode.user.token.yml create mode 100644 config/sync/language/hr/views.view.moderated_content.yml create mode 100644 config/sync/language/sl/views.view.moderated_content.yml create mode 100644 config/sync/language/sr/views.view.moderated_content.yml create mode 100644 config/sync/rest.resource.add_concept_rest_resource.yml create mode 100644 web/modules/custom/yufu_concept/README.md diff --git a/README.md b/README.md index f3204a7..f6b72f5 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,12 @@ Nato poženemo izgrajevalnik / strežnik: Dodatne testne vsebine lahko definiramo v modulu `yufu_data`, v poddirektoriju `content`. Pazit moramo na ime - vsak fajl se mora končati s `.content.yml`. Navodila za konstruiranje fajlov pa so tukaj: https://www.drupal.org/docs/contributed-modules/yaml-content/examples + + +# Dokumentacija + +## Backend + +### Endpoint za dodajanje pojmov + +V modulu [yufu_concept](web/modules/custom/yufu_concept/yufu_concept.info.yml "yufu_concept"). diff --git a/composer.json b/composer.json index 3d20ec8..f2c9cf1 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ ], "require": { "composer/installers": "^2.0", + "cweagans/composer-patches": "^1.7", "drupal/cer": "^5.0@beta", "drupal/content_as_config": "^1.0", "drupal/core-composer-scaffold": "^10.0", @@ -24,7 +25,9 @@ "drupal/gin": "^3.0@RC", "drupal/gin_toolbar": "^1.0@RC", "drupal/jsonapi_menu_items": "^1.2", + "drupal/restui": "^1.21", "drupal/single_content_sync": "^1.3", + "drupal/token": "^1.12", "drupal/yaml_content": "^1.0@dev", "drush/drush": "^11.4" }, @@ -39,11 +42,17 @@ "drupal/core-composer-scaffold": true, "drupal/core-project-message": true, "phpstan/extension-installer": true, - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "cweagans/composer-patches": true }, "sort-packages": true }, "extra": { + "patches": { + "drupal/restui": { + "#3337894: Get class methods wrong argument.": "https://www.drupal.org/files/issues/2023-06-23/type-error-class-3337894-10.patch" + } + }, "drupal-scaffold": { "locations": { "web-root": "web/" diff --git a/composer.lock b/composer.lock index fd09943..72bcee7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f739ff77797412cd5de7292408a1d098", + "content-hash": "d5d4122da2b7a3502081e8d79d06641a", "packages": [ { "name": "asm89/stack-cors", @@ -870,6 +870,54 @@ }, "time": "2022-12-06T17:57:16+00:00" }, + { + "name": "cweagans/composer-patches", + "version": "1.7.3", + "source": { + "type": "git", + "url": "https://github.com/cweagans/composer-patches.git", + "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db", + "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3.0" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "phpunit/phpunit": "~4.6" + }, + "type": "composer-plugin", + "extra": { + "class": "cweagans\\Composer\\Patches" + }, + "autoload": { + "psr-4": { + "cweagans\\Composer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Cameron Eagans", + "email": "me@cweagans.net" + } + ], + "description": "Provides a way to patch Composer packages.", + "support": { + "issues": "https://github.com/cweagans/composer-patches/issues", + "source": "https://github.com/cweagans/composer-patches/tree/1.7.3" + }, + "time": "2022-12-20T22:53:13+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.2", @@ -1348,6 +1396,9 @@ } }, "autoload": { + "files": [ + "includes/bootstrap.inc" + ], "psr-4": { "Drupal\\Core\\": "lib/Drupal/Core", "Drupal\\Component\\": "lib/Drupal/Component" @@ -1374,20 +1425,17 @@ "lib/Drupal/Core/DrupalKernelInterface.php", "lib/Drupal/Core/Installer/InstallerRedirectTrait.php", "lib/Drupal/Core/Site/Settings.php" - ], - "files": [ - "includes/bootstrap.inc" - ] - }, - "scripts": { - "pre-autoload-dump": [ - "Drupal\\Core\\Composer\\Composer::preAutoloadDump" ] }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], - "description": "Drupal is an open source content management platform powering millions of websites and applications." + "description": "Drupal is an open source content management platform powering millions of websites and applications.", + "support": { + "source": "https://github.com/drupal/core/tree/10.0.3" + }, + "time": "2023-02-01T18:23:27+00:00" }, { "name": "drupal/core-composer-scaffold", @@ -1425,6 +1473,7 @@ "Drupal\\Composer\\Plugin\\Scaffold\\": "" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], @@ -1432,7 +1481,11 @@ "homepage": "https://www.drupal.org/project/drupal", "keywords": [ "drupal" - ] + ], + "support": { + "source": "https://github.com/drupal/core-composer-scaffold/tree/10.0.3" + }, + "time": "2022-07-01T08:33:05+00:00" }, { "name": "drupal/core-project-message", @@ -1461,6 +1514,7 @@ "Drupal\\Composer\\Plugin\\ProjectMessage\\": "." } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], @@ -1468,7 +1522,11 @@ "homepage": "https://www.drupal.org/project/drupal", "keywords": [ "drupal" - ] + ], + "support": { + "source": "https://github.com/drupal/core-project-message/tree/10.0.3" + }, + "time": "2022-07-01T08:33:05+00:00" }, { "name": "drupal/core-recommended", @@ -1539,10 +1597,15 @@ "webflo/drupal-core-strict": "*" }, "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], - "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core." + "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.", + "support": { + "source": "https://github.com/drupal/core-recommended/tree/10.0.3" + }, + "time": "2023-02-01T18:23:27+00:00" }, { "name": "drupal/gin", @@ -1785,6 +1848,62 @@ "source": "https://git.drupalcode.org/project/jsonapi_resources" } }, + { + "name": "drupal/restui", + "version": "1.21.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/restui.git", + "reference": "8.x-1.21" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/restui-8.x-1.21.zip", + "reference": "8.x-1.21", + "shasum": "2a67dc2c1953dced0bddaff25e5c60784ee0178c" + }, + "require": { + "drupal/core": "^8.7.7 || ^9 || ^10" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.21", + "datestamp": "1659086914", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "-enzo-", + "homepage": "https://www.drupal.org/user/294937" + }, + { + "name": "clemens.tolboom", + "homepage": "https://www.drupal.org/user/125814" + }, + { + "name": "juampynr", + "homepage": "https://www.drupal.org/user/682736" + }, + { + "name": "klausi", + "homepage": "https://www.drupal.org/user/262198" + } + ], + "description": "Provides a user interface to manage REST resources.", + "homepage": "https://www.drupal.org/project/restui", + "support": { + "source": "https://git.drupalcode.org/project/restui" + } + }, { "name": "drupal/single_content_sync", "version": "1.3.13", @@ -1838,6 +1957,75 @@ "issues": "https://drupal.org/project/issues/single_content_sync" } }, + { + "name": "drupal/token", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/token.git", + "reference": "8.x-1.12" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/token-8.x-1.12.zip", + "reference": "8.x-1.12", + "shasum": "cefe1b203b793682f74ea43e18d0a814cf768763" + }, + "require": { + "drupal/core": "^9.2 || ^10" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.12", + "datestamp": "1688015262", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + }, + "drush": { + "services": { + "drush.services.yml": "^9 || ^10" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Berdir", + "homepage": "https://www.drupal.org/user/214652" + }, + { + "name": "Dave Reid", + "homepage": "https://www.drupal.org/user/53892" + }, + { + "name": "eaton", + "homepage": "https://www.drupal.org/user/16496" + }, + { + "name": "fago", + "homepage": "https://www.drupal.org/user/16747" + }, + { + "name": "greggles", + "homepage": "https://www.drupal.org/user/36762" + }, + { + "name": "mikeryan", + "homepage": "https://www.drupal.org/user/4420" + } + ], + "description": "Provides a user interface for the Token API, some missing core tokens.", + "homepage": "https://www.drupal.org/project/token", + "support": { + "source": "https://git.drupalcode.org/project/token" + } + }, { "name": "drupal/yaml_content", "version": "dev-1.x", @@ -1858,8 +2046,8 @@ "dev-1.x": "1.x-dev" }, "drupal": { - "version": "8.x-1.0-alpha8+1-dev", - "datestamp": "1666891400", + "version": "8.x-1.0-alpha8+4-dev", + "datestamp": "1690395239", "security-coverage": { "status": "not-covered", "message": "Project has not opted into security advisory coverage!" diff --git a/config/sync/core.entity_form_display.node.concept.default.yml b/config/sync/core.entity_form_display.node.concept.default.yml index ddc33ca..72a0ef6 100644 --- a/config/sync/core.entity_form_display.node.concept.default.yml +++ b/config/sync/core.entity_form_display.node.concept.default.yml @@ -8,7 +8,9 @@ dependencies: - field.field.node.concept.field_related_concept - field.field.node.concept.field_tags - node.type.concept + - workflows.workflow.concept_workflow module: + - content_moderation - media_library - path - text @@ -19,7 +21,7 @@ mode: default content: body: type: text_textarea_with_summary - weight: 121 + weight: 1 region: content settings: rows: 9 @@ -29,20 +31,20 @@ content: third_party_settings: { } created: type: datetime_timestamp - weight: 10 + weight: 9 region: content settings: { } third_party_settings: { } field_media: type: media_library_widget - weight: 122 + weight: 5 region: content settings: media_types: { } third_party_settings: { } field_related_concept: type: entity_reference_autocomplete - weight: 123 + weight: 2 region: content settings: match_operator: CONTAINS @@ -52,7 +54,7 @@ content: third_party_settings: { } field_tags: type: entity_reference_autocomplete - weight: 124 + weight: 4 region: content settings: match_operator: CONTAINS @@ -62,41 +64,47 @@ content: third_party_settings: { } langcode: type: language_select - weight: 2 + weight: 3 region: content settings: include_locked: true third_party_settings: { } + moderation_state: + type: moderation_state_default + weight: 6 + region: content + settings: { } + third_party_settings: { } path: type: path - weight: 30 + weight: 13 region: content settings: { } third_party_settings: { } promote: type: boolean_checkbox - weight: 15 + weight: 11 region: content settings: display_label: true third_party_settings: { } status: type: boolean_checkbox - weight: 120 + weight: 7 region: content settings: display_label: true third_party_settings: { } sticky: type: boolean_checkbox - weight: 16 + weight: 12 region: content settings: display_label: true third_party_settings: { } title: type: string_textfield - weight: -5 + weight: 0 region: content settings: size: 60 @@ -109,7 +117,7 @@ content: third_party_settings: { } uid: type: entity_reference_autocomplete - weight: 5 + weight: 8 region: content settings: match_operator: CONTAINS diff --git a/config/sync/core.entity_view_mode.block.token.yml b/config/sync/core.entity_view_mode.block.token.yml new file mode 100644 index 0000000..e99e4d9 --- /dev/null +++ b/config/sync/core.entity_view_mode.block.token.yml @@ -0,0 +1,10 @@ +uuid: be4c3be6-4cc3-4c4a-9c5e-d58e55903e85 +langcode: en +status: true +dependencies: + module: + - block +id: block.token +label: Token +targetEntityType: block +cache: true diff --git a/config/sync/core.entity_view_mode.block_content.token.yml b/config/sync/core.entity_view_mode.block_content.token.yml new file mode 100644 index 0000000..c3ce211 --- /dev/null +++ b/config/sync/core.entity_view_mode.block_content.token.yml @@ -0,0 +1,10 @@ +uuid: b57556dc-3181-40a4-83b6-ee55e3c2f942 +langcode: en +status: true +dependencies: + module: + - block_content +id: block_content.token +label: Token +targetEntityType: block_content +cache: true diff --git a/config/sync/core.entity_view_mode.comment.token.yml b/config/sync/core.entity_view_mode.comment.token.yml new file mode 100644 index 0000000..9f1d65f --- /dev/null +++ b/config/sync/core.entity_view_mode.comment.token.yml @@ -0,0 +1,10 @@ +uuid: 45f19d69-ef2b-4758-a9f8-e31279d31317 +langcode: en +status: true +dependencies: + module: + - comment +id: comment.token +label: Token +targetEntityType: comment +cache: true diff --git a/config/sync/core.entity_view_mode.content_moderation_state.token.yml b/config/sync/core.entity_view_mode.content_moderation_state.token.yml new file mode 100644 index 0000000..36902ae --- /dev/null +++ b/config/sync/core.entity_view_mode.content_moderation_state.token.yml @@ -0,0 +1,10 @@ +uuid: 655d18e2-71f8-49bf-ac6c-e0526bdd049e +langcode: en +status: true +dependencies: + module: + - content_moderation +id: content_moderation_state.token +label: Token +targetEntityType: content_moderation_state +cache: true diff --git a/config/sync/core.entity_view_mode.file.token.yml b/config/sync/core.entity_view_mode.file.token.yml new file mode 100644 index 0000000..5b0d61b --- /dev/null +++ b/config/sync/core.entity_view_mode.file.token.yml @@ -0,0 +1,10 @@ +uuid: 6f5ca935-a97f-41ba-ad0e-3f284cf5e536 +langcode: en +status: true +dependencies: + module: + - file +id: file.token +label: Token +targetEntityType: file +cache: true diff --git a/config/sync/core.entity_view_mode.media.token.yml b/config/sync/core.entity_view_mode.media.token.yml new file mode 100644 index 0000000..8f3c5ec --- /dev/null +++ b/config/sync/core.entity_view_mode.media.token.yml @@ -0,0 +1,10 @@ +uuid: 194fc976-a674-4d3f-b70f-087e97ab7e25 +langcode: en +status: true +dependencies: + module: + - media +id: media.token +label: Token +targetEntityType: media +cache: true diff --git a/config/sync/core.entity_view_mode.menu_link_content.token.yml b/config/sync/core.entity_view_mode.menu_link_content.token.yml new file mode 100644 index 0000000..9f138bd --- /dev/null +++ b/config/sync/core.entity_view_mode.menu_link_content.token.yml @@ -0,0 +1,10 @@ +uuid: 984fe3ef-e532-4bd9-8937-af7001e7a3bd +langcode: en +status: true +dependencies: + module: + - menu_link_content +id: menu_link_content.token +label: Token +targetEntityType: menu_link_content +cache: true diff --git a/config/sync/core.entity_view_mode.node.token.yml b/config/sync/core.entity_view_mode.node.token.yml new file mode 100644 index 0000000..e4d5b00 --- /dev/null +++ b/config/sync/core.entity_view_mode.node.token.yml @@ -0,0 +1,10 @@ +uuid: f9b3366d-d376-41b1-8c3f-06edb76a96fb +langcode: en +status: true +dependencies: + module: + - node +id: node.token +label: Token +targetEntityType: node +cache: true diff --git a/config/sync/core.entity_view_mode.path_alias.token.yml b/config/sync/core.entity_view_mode.path_alias.token.yml new file mode 100644 index 0000000..244e9e9 --- /dev/null +++ b/config/sync/core.entity_view_mode.path_alias.token.yml @@ -0,0 +1,10 @@ +uuid: 600d4fed-e248-4be2-818a-4442c5f9e07a +langcode: en +status: true +dependencies: + module: + - path_alias +id: path_alias.token +label: Token +targetEntityType: path_alias +cache: true diff --git a/config/sync/core.entity_view_mode.taxonomy_term.token.yml b/config/sync/core.entity_view_mode.taxonomy_term.token.yml new file mode 100644 index 0000000..7219212 --- /dev/null +++ b/config/sync/core.entity_view_mode.taxonomy_term.token.yml @@ -0,0 +1,10 @@ +uuid: 5e3cc117-bf76-406a-ba35-cf9b5cfbe4b9 +langcode: en +status: true +dependencies: + module: + - taxonomy +id: taxonomy_term.token +label: Token +targetEntityType: taxonomy_term +cache: true diff --git a/config/sync/core.entity_view_mode.user.token.yml b/config/sync/core.entity_view_mode.user.token.yml new file mode 100644 index 0000000..128fc71 --- /dev/null +++ b/config/sync/core.entity_view_mode.user.token.yml @@ -0,0 +1,10 @@ +uuid: d8e3dde9-87a9-4209-ac1d-8961ff0a3ceb +langcode: en +status: true +dependencies: + module: + - user +id: user.token +label: Token +targetEntityType: user +cache: true diff --git a/config/sync/core.extension.yml b/config/sync/core.extension.yml index 747e02b..a42ca64 100644 --- a/config/sync/core.extension.yml +++ b/config/sync/core.extension.yml @@ -42,12 +42,15 @@ module: page_cache: 0 path: 0 path_alias: 0 + rest: 0 + restui: 0 search: 0 serialization: 0 single_content_sync: 0 system: 0 taxonomy: 0 text: 0 + token: 0 toolbar: 0 update: 0 user: 0 @@ -55,6 +58,7 @@ module: workflows: 0 yaml_content: 0 yufu_admin: 0 + yufu_concept: 0 yufu_data: 0 content_translation: 10 views: 10 diff --git a/config/sync/dblog.settings.yml b/config/sync/dblog.settings.yml index fbd17ea..ed40eb0 100644 --- a/config/sync/dblog.settings.yml +++ b/config/sync/dblog.settings.yml @@ -1,3 +1,3 @@ _core: default_config_hash: e883aGsrt1wFrsydlYU584PZONCSfRy0DtkZ9KzHb58 -row_limit: 1000 +row_limit: 100000 diff --git a/config/sync/language/hr/views.view.moderated_content.yml b/config/sync/language/hr/views.view.moderated_content.yml new file mode 100644 index 0000000..67eaa8e --- /dev/null +++ b/config/sync/language/hr/views.view.moderated_content.yml @@ -0,0 +1,29 @@ +display: + default: + display_title: Default + display_options: + fields: + title: + label: Naslov + type: + label: 'Tip vsebine' + name: + label: Author + changed: + label: Updated + operations: + label: Operations + exposed_form: + options: + submit_button: Filter + reset_button_label: Reset + filters: + title: + expose: + label: Naslov + type: + expose: + label: 'Tip vsebine' + langcode: + expose: + label: Language diff --git a/config/sync/language/sl/views.view.moderated_content.yml b/config/sync/language/sl/views.view.moderated_content.yml new file mode 100644 index 0000000..67eaa8e --- /dev/null +++ b/config/sync/language/sl/views.view.moderated_content.yml @@ -0,0 +1,29 @@ +display: + default: + display_title: Default + display_options: + fields: + title: + label: Naslov + type: + label: 'Tip vsebine' + name: + label: Author + changed: + label: Updated + operations: + label: Operations + exposed_form: + options: + submit_button: Filter + reset_button_label: Reset + filters: + title: + expose: + label: Naslov + type: + expose: + label: 'Tip vsebine' + langcode: + expose: + label: Language diff --git a/config/sync/language/sr/views.view.moderated_content.yml b/config/sync/language/sr/views.view.moderated_content.yml new file mode 100644 index 0000000..67eaa8e --- /dev/null +++ b/config/sync/language/sr/views.view.moderated_content.yml @@ -0,0 +1,29 @@ +display: + default: + display_title: Default + display_options: + fields: + title: + label: Naslov + type: + label: 'Tip vsebine' + name: + label: Author + changed: + label: Updated + operations: + label: Operations + exposed_form: + options: + submit_button: Filter + reset_button_label: Reset + filters: + title: + expose: + label: Naslov + type: + expose: + label: 'Tip vsebine' + langcode: + expose: + label: Language diff --git a/config/sync/rest.resource.add_concept_rest_resource.yml b/config/sync/rest.resource.add_concept_rest_resource.yml new file mode 100644 index 0000000..888e462 --- /dev/null +++ b/config/sync/rest.resource.add_concept_rest_resource.yml @@ -0,0 +1,18 @@ +uuid: 589ee957-7efd-45d3-979b-93b5b1018761 +langcode: en +status: true +dependencies: + module: + - serialization + - user + - yufu_concept +id: add_concept_rest_resource +plugin_id: add_concept_rest_resource +granularity: resource +configuration: + methods: + - POST + formats: + - json + authentication: + - cookie diff --git a/config/sync/system.logging.yml b/config/sync/system.logging.yml index d6164de..135cce7 100644 --- a/config/sync/system.logging.yml +++ b/config/sync/system.logging.yml @@ -1,3 +1,3 @@ _core: default_config_hash: u3-njszl92FaxjrCMiq0yDcjAfcdx72w1zT1O9dx6aA -error_level: hide +error_level: some diff --git a/config/sync/user.role.anonymous.yml b/config/sync/user.role.anonymous.yml index 7c52d43..3d919db 100644 --- a/config/sync/user.role.anonymous.yml +++ b/config/sync/user.role.anonymous.yml @@ -4,11 +4,13 @@ status: true dependencies: config: - node.type.concept + - rest.resource.add_concept_rest_resource - workflows.workflow.concept_workflow module: - content_moderation - media - node + - rest - system _core: default_config_hash: j5zLMOdJBqC0bMvSdth5UebkprJB8g_2FXHqhfpJzow @@ -19,5 +21,7 @@ is_admin: false permissions: - 'access content' - 'create concept content' + - 'edit any concept content' + - 'restful post add_concept_rest_resource' - 'use concept_workflow transition create_new_draft' - 'view media' diff --git a/config/sync/user.role.authenticated.yml b/config/sync/user.role.authenticated.yml index d5f6112..fc5a6c7 100644 --- a/config/sync/user.role.authenticated.yml +++ b/config/sync/user.role.authenticated.yml @@ -5,12 +5,14 @@ dependencies: config: - node.type.article - node.type.concept + - rest.resource.add_concept_rest_resource - taxonomy.vocabulary.tags - workflows.workflow.concept_workflow module: - content_moderation - media - node + - rest - system - taxonomy - yufu_admin @@ -26,6 +28,8 @@ permissions: - 'create concept content' - 'create media' - 'create terms in tags' + - 'edit any concept content' + - 'restful post add_concept_rest_resource' - 'use concept_workflow transition create_new_draft' - 'use jsonapi operation link' - 'view any unpublished content' diff --git a/config/sync/user.role.editor.yml b/config/sync/user.role.editor.yml index c014288..faa7b66 100644 --- a/config/sync/user.role.editor.yml +++ b/config/sync/user.role.editor.yml @@ -11,6 +11,7 @@ dependencies: - node.type.article - node.type.concept - node.type.page + - rest.resource.add_concept_rest_resource - taxonomy.vocabulary.tags - workflows.workflow.concept_workflow module: @@ -23,6 +24,7 @@ dependencies: - media - node - path + - rest - taxonomy - toolbar id: editor @@ -85,6 +87,7 @@ permissions: - 'edit terms in tags' - 'export configuration' - 'import configuration' + - 'restful post add_concept_rest_resource' - 'revert article revisions' - 'revert concept revisions' - 'revert page revisions' diff --git a/config/sync/views.view.moderated_content.yml b/config/sync/views.view.moderated_content.yml index 7a4010e..228b536 100644 --- a/config/sync/views.view.moderated_content.yml +++ b/config/sync/views.view.moderated_content.yml @@ -2,7 +2,10 @@ uuid: 8347c43e-4379-4de8-9577-a481a608a372 langcode: en status: true dependencies: + config: + - workflows.workflow.concept_workflow module: + - content_moderation - node - user enforced: @@ -677,18 +680,18 @@ display: plugin_id: moderation_state_filter operator: 'not in' value: - editorial-published: editorial-published + concept_workflow-published: concept_workflow-published group: 1 exposed: false expose: - operator_id: '' - label: '' - description: '' + operator_id: moderation_state_1_op + label: 'Moderation state' + description: null use_operator: false - operator: '' + operator: moderation_state_1_op operator_limit_selection: false operator_list: { } - identifier: '' + identifier: moderation_state_1 required: false remember: false multiple: false @@ -811,7 +814,8 @@ display: - url.query_args - 'user.node_grants:view' - user.permissions - tags: { } + tags: + - 'config:workflow_list' moderated_content: id: moderated_content display_title: 'Moderated content' @@ -830,4 +834,5 @@ display: - url.query_args - 'user.node_grants:view' - user.permissions - tags: { } + tags: + - 'config:workflow_list' diff --git a/web/modules/custom/yufu_concept/README.md b/web/modules/custom/yufu_concept/README.md new file mode 100644 index 0000000..cd86f25 --- /dev/null +++ b/web/modules/custom/yufu_concept/README.md @@ -0,0 +1,15 @@ +# Yufu Concept + +Vsebuje funkcionalnosti povezane s pojmi - osnovnimi gradniki manifesta. + +## Endpoint /api/pojem/dodaj + +Post request endpoint za dodajanje pojmov. + +## Autocomplete za (povezane) pojme + +@TODO: To be implemented. + +## Posiljanje emailov + +https://drupal.stackexchange.com/questions/235157/message-not-being-sent-in-the-body-of-the-mail diff --git a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php index 1d8800d..44f77e5 100644 --- a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php +++ b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php @@ -1,20 +1,21 @@ currentUser = $current_user; $this->mailManager = $mailManager; - $this->config = $configFactory->get('system.site'); + $this->config = $configFactory; $this->entityTypeManager = $entity_type_manager; } @@ -101,7 +106,7 @@ class AddConcept extends ResourceBase { $plugin_id, $plugin_definition, $container->getParameter('serializer.formats'), - $container->get('logger.factory')->get('custom_rest'), + $container->get('logger.factory')->get('yufu_concept'), $container->get('current_user'), $container->get('plugin.manager.mail'), $container->get('config.factory'), @@ -110,16 +115,17 @@ class AddConcept extends ResourceBase { } /** - * Send a test email. + * Ustvari nov koncept. * - * @param $data - * Post date. + * @param \Symfony\Component\HttpFoundation\Request; + * Post request. * * @return \Drupal\rest\ResourceResponse * Returns rest resource. */ - public function post($data) { + public function post(Request $request) { $response_status['status'] = FALSE; + $data = json_decode($request->getContent(), TRUE); // You must to implement the logic of your REST Resource here. // Use current user after pass authentication to validate access. if (!$this->currentUser->hasPermission('access content')) { @@ -133,26 +139,37 @@ class AddConcept extends ResourceBase { $concept = [ 'type' => 'concept', 'title' => $data['title'], - 'body' => $data['text'], + 'body' => $data['body'], ]; + $this->logger->log(LogLevel::NOTICE, $this->t('Creating concept: @title', [ + '@title' => $concept['title'], + ])); // @TODO Check if related concepts are set and add them to the concept. // @TODO Check language and add set it on concept if exists. - $concept = $this->entityTypeManger->getStorage('node')->create($concept); + /** @var \Drupal\node\Entity\NodeInterface $concept */ + $concept = $this->entityTypeManager->getStorage('node')->create($concept); $concept->save(); + $response_status['concept'] = [ + 'title' => $concept->label(), + 'id' => $concept->id(), + 'uuid' => $concept->uuid(), + ]; if (!empty($data['email'])) { // @TODO Poslji mail uporabniku, da se lahko registrira. - $site_email = $this->config->get('mail'); + $site_email = $this->config->get('system.site')->get('mail'); $module = 'yufu_concept'; - $key = 'notice'; + $key = 'add_concept_rest_resource'; $to = $site_email; // Send email to user to make him register to the website. - $params['message'] = $data['message']['value']; - $params['title'] = $data['subject']['value']; - $params['from'] = $data['email']['value']; - $langcode = $data['lang']['value']; + $params['message'] = $this->t('Creating concept: @title', [ + '@title' => $concept->label(), + ]); + $params['subject'] = $data['title']; + $params['from'] = $data['email']; + // @TODO Add validation for langode (must be from system configured endpoints). + $langcode = $data['lang'] ?? 'en'; $send = TRUE; - $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send); $response_status['status'] = $result['result']; } diff --git a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest index daaa1c3..25e3397 100644 --- a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest +++ b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest @@ -5,8 +5,10 @@ POST https://yufu-manifest.ddev.site/api/pojem/dodaj User-Agent: Emacs Restclient Content-Type: application/json +Cookies: "SSESSb6f5da6ef565138b872e3e58509d8150=0z6Zk4tRwTF4WAR%2CSO6rH0K5F7hqKpbe28XRRHwvTxo%2CUnpC" { -"title": "Emacs restclient test", -"body": "O wau. Emacs restclient. How nice." -} \ No newline at end of file +"title": "Emacs restclient test 102", +"body": "O wau. Emacs restclient. How nice.", +"email": "lio.novelli@radiostudent.si" +} diff --git a/web/modules/custom/yufu_concept/yufu_concept.module b/web/modules/custom/yufu_concept/yufu_concept.module index 0a8a750..70c7b22 100644 --- a/web/modules/custom/yufu_concept/yufu_concept.module +++ b/web/modules/custom/yufu_concept/yufu_concept.module @@ -4,3 +4,21 @@ * @file * Primary module hooks for Yufu Concept module. */ + +/** + * Implements hook_mail(). + */ +function yufu_concept_mail($key, &$message, $params) { + $options = [ + 'langcode' => $message['langcode'], + ]; + + switch ($key) { + case 'add_concept_rest_resource': + // This is just a test implementation for sending emails. + $message['from'] = $params['from']; + $message['subject'] = $params['subject']; + $message['body'][] = $params['message']; + break; + } +} -- 2.30.2 From 7c4a51e8eb22d5b6f865fca91d8bef1463bd38c6 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Sun, 12 Nov 2023 18:43:54 +0100 Subject: [PATCH 3/8] wip --- web/modules/custom/yufu_concept/yufu_concept.module | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/modules/custom/yufu_concept/yufu_concept.module b/web/modules/custom/yufu_concept/yufu_concept.module index 70c7b22..32304d1 100644 --- a/web/modules/custom/yufu_concept/yufu_concept.module +++ b/web/modules/custom/yufu_concept/yufu_concept.module @@ -7,6 +7,8 @@ /** * Implements hook_mail(). + * + * @TODO this should go into hook presave. */ function yufu_concept_mail($key, &$message, $params) { $options = [ -- 2.30.2 From 6559793714951e1ac3eb9a156349c3f9f5f1a7c1 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Sun, 12 Nov 2023 23:42:52 +0100 Subject: [PATCH 4/8] Endpoint deluje in vraca veliko o novi reviziji. --- .../src/Plugin/rest/resource/AddConcept.php | 161 +++++++++++------- .../yufu_concept/tests/local-emacs-test.rest | 8 +- .../custom/yufu_concept/yufu_concept.module | 20 --- 3 files changed, 106 insertions(+), 83 deletions(-) diff --git a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php index 44f77e5..258d09d 100644 --- a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php +++ b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/AddConcept.php @@ -4,10 +4,10 @@ namespace Drupal\yufu_concept\Plugin\rest\resource; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Mail\MailManagerInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\TypedData\Exception\MissingDataException; +use Drupal\node\NodeInterface; use Drupal\rest\Plugin\ResourceBase; use Drupal\rest\ResourceResponse; use Psr\Log\LogLevel; @@ -39,20 +39,6 @@ class AddConcept extends ResourceBase { */ protected $currentUser; - /** - * Mail manager service. - * - * @var \Drupal\Core\Mail\MailManagerInterface - */ - protected $mailManager; - - /** - * Site configs. - * - * @var \Drupal\Core\Config\ImmutableConfig - */ - protected $config; - /** * Entity type manager service. * @@ -75,10 +61,6 @@ class AddConcept extends ResourceBase { * A logger instance. * @param \Drupal\Core\Session\AccountProxyInterface $current_user * A current user instance. - * @param \Drupal\Core\Mail\MailManagerInterface $mailManager - * Mail manager service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * Config factory service. */ public function __construct( array $configuration, @@ -87,13 +69,9 @@ class AddConcept extends ResourceBase { array $serializer_formats, LoggerInterface $logger, AccountProxyInterface $current_user, - MailManagerInterface $mailManager, - ConfigFactoryInterface $configFactory, EntityTypeManagerInterface $entity_type_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger); $this->currentUser = $current_user; - $this->mailManager = $mailManager; - $this->config = $configFactory; $this->entityTypeManager = $entity_type_manager; } @@ -106,10 +84,8 @@ class AddConcept extends ResourceBase { $plugin_id, $plugin_definition, $container->getParameter('serializer.formats'), - $container->get('logger.factory')->get('yufu_concept'), + $container->get('logger.channel.yufu_concept'), $container->get('current_user'), - $container->get('plugin.manager.mail'), - $container->get('config.factory'), $container->get('entity_type.manager') ); } @@ -117,6 +93,11 @@ class AddConcept extends ResourceBase { /** * Ustvari nov koncept. * + * Logika: + * 1. Zloadamo uporabnika preko emaila, ce ne obstaja, ga ustvarimo. + * 2. Zloadamo koncept prek uuid, ce ne obstaja, da ustvarimo. + * - avtor je zloadan prek maila + * * @param \Symfony\Component\HttpFoundation\Request; * Post request. * @@ -133,48 +114,108 @@ class AddConcept extends ResourceBase { } // Fields: naslov, text, povezani pojmi, email // Optional fields: language, related concept. - if (!empty($data['title']) && !empty($data['text'])) { - throw new MissingDataException('Title or text missing.'); + if (empty($data['title']) || empty($data['text']) || empty($data['uuid'])) { + throw new MissingDataException('Title, uuid or text missing.'); + } + $uid = $this->getUserIdByEmail($data['email'] ?? null); + if ($concept = $this->getConceptFromUuid($data['uuid'])) { + // Concept exists - create a new revision. + $concept->setNewRevision(TRUE); + $concept->setRevisionUserId($uid); + $concept->set('title', $data['title']); + $concept->set('body', $data['text'] ?? $concept->body->value); + $concept->isDefaultRevision(FALSE); + $concept->setRevisionLogMessage('New revision by concept endpoint.'); + $concept->moderation_state->target_id = 'draft'; + $concept->save(); + $this->logger->notice('New concept @title revision @revid created by uid @uid.', [ + '@title' => $concept->getTitle(), + '@revid' => $concept->getRevisionId(), + '@uid' => $uid, + ]); + } + else { + // Concept does not exist - create a new node. + $concept = [ + 'type' => 'concept', + 'title' => $data['title'], + 'body' => $data['text'], + 'uuid' => $data['uuid'], + 'uid' => $uid, + 'moderation_state' => 'draft', + ]; + // @TODO Check if related concepts are set and add them to the concept. + // @TODO Check language and add set it on concept if exists. + /** @var \Drupal\node\Entity\NodeInterface $concept */ + $concept = $this->entityTypeManager->getStorage('node')->create($concept); + $concept->save(); + $this->logger->log(LogLevel::NOTICE, $this->t('Creating concept: @title', [ + '@title' => $concept->getTitle(), + ])); } - $concept = [ - 'type' => 'concept', - 'title' => $data['title'], - 'body' => $data['body'], - ]; - $this->logger->log(LogLevel::NOTICE, $this->t('Creating concept: @title', [ - '@title' => $concept['title'], - ])); - // @TODO Check if related concepts are set and add them to the concept. - // @TODO Check language and add set it on concept if exists. - /** @var \Drupal\node\Entity\NodeInterface $concept */ - $concept = $this->entityTypeManager->getStorage('node')->create($concept); - $concept->save(); $response_status['concept'] = [ 'title' => $concept->label(), 'id' => $concept->id(), 'uuid' => $concept->uuid(), + 'revision_id' => $concept->getRevisionId(), + 'revision_create_time' => $concept->getRevisionCreationTime(), + 'revision_uid' => $concept->getRevisionUserId(), + 'uid' => $concept->uid->target_id, ]; - - if (!empty($data['email'])) { - // @TODO Poslji mail uporabniku, da se lahko registrira. - $site_email = $this->config->get('system.site')->get('mail'); - $module = 'yufu_concept'; - $key = 'add_concept_rest_resource'; - $to = $site_email; - // Send email to user to make him register to the website. - $params['message'] = $this->t('Creating concept: @title', [ - '@title' => $concept->label(), - ]); - $params['subject'] = $data['title']; - $params['from'] = $data['email']; - // @TODO Add validation for langode (must be from system configured endpoints). - $langcode = $data['lang'] ?? 'en'; - $send = TRUE; - $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send); - $response_status['status'] = $result['result']; - } $response = new ResourceResponse($response_status); return $response; } + /** + * Get concept from uuid. + * + * If concept is new, return null. + * + * @param string|null $uuid + * Uuid of the node. + * + * @return \Drupal\node\NodeInterface|null + */ + protected function getConceptFromUuid(?string $uuid): ?NodeInterface { + if (!$uuid) { + return NULL; + } + $node_storage = $this->entityTypeManager->getStorage('node'); + if ($concept = end($node_storage->loadByProperties(['uuid' => $uuid]))) { + return $concept; + } + return NULL; + } + + /** + * Loads user from email or creates a new blocked user. + * + * Side effect is to create a new user. + * + * @param string|null $email + * Email provided by the fe call to endpoint. + * + * @return int + * Id of the user. + * + */ + protected function getUserIdByEmail(?string $email): int { + if (!$email) { + return 0; + } + // Load user by email. If it doesn't exist, create one. + $user_storage = $this->entityTypeManager->getStorage('user'); + if ($user = end($user_storage->loadByProperties(['mail' => $email]))) { + return $user->id(); + } + $user = [ + 'mail' => $email, + 'name' => $email, + 'status' => 0, + ]; + $new_user = $user_storage->create($user); + $new_user->save(); + return $new_user->id(); + } + } diff --git a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest index 25e3397..f024295 100644 --- a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest +++ b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest @@ -1,6 +1,7 @@ # _*_ restclient _*_ # Makes post http request to a resource from yufu_concept module. +# Make sure uuid is uniq or it will create new revision. POST https://yufu-manifest.ddev.site/api/pojem/dodaj User-Agent: Emacs Restclient @@ -8,7 +9,8 @@ Content-Type: application/json Cookies: "SSESSb6f5da6ef565138b872e3e58509d8150=0z6Zk4tRwTF4WAR%2CSO6rH0K5F7hqKpbe28XRRHwvTxo%2CUnpC" { -"title": "Emacs restclient test 102", -"body": "O wau. Emacs restclient. How nice.", -"email": "lio.novelli@radiostudent.si" +"title": "888 Emacs restclient test 888", +"text": "O wau. Emacs restclient. How nice. Dodam text. Spet.", +"email": "lio.novelli@radiostudent.si", +"uuid": "70c1ace2-aaaa-4dc5-84ed-3f21b83cb23a" } diff --git a/web/modules/custom/yufu_concept/yufu_concept.module b/web/modules/custom/yufu_concept/yufu_concept.module index 32304d1..0a8a750 100644 --- a/web/modules/custom/yufu_concept/yufu_concept.module +++ b/web/modules/custom/yufu_concept/yufu_concept.module @@ -4,23 +4,3 @@ * @file * Primary module hooks for Yufu Concept module. */ - -/** - * Implements hook_mail(). - * - * @TODO this should go into hook presave. - */ -function yufu_concept_mail($key, &$message, $params) { - $options = [ - 'langcode' => $message['langcode'], - ]; - - switch ($key) { - case 'add_concept_rest_resource': - // This is just a test implementation for sending emails. - $message['from'] = $params['from']; - $message['subject'] = $params['subject']; - $message['body'][] = $params['message']; - break; - } -} -- 2.30.2 From aa8f762816aa39cc0884440832bfa3242920168a Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Mon, 13 Nov 2023 00:01:20 +0100 Subject: [PATCH 5/8] 25: Add missing services yaml file. --- web/modules/custom/yufu_concept/yufu_concept.services.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 web/modules/custom/yufu_concept/yufu_concept.services.yml diff --git a/web/modules/custom/yufu_concept/yufu_concept.services.yml b/web/modules/custom/yufu_concept/yufu_concept.services.yml new file mode 100644 index 0000000..5ccd085 --- /dev/null +++ b/web/modules/custom/yufu_concept/yufu_concept.services.yml @@ -0,0 +1,5 @@ +services: + logger.channel.yufu_concept: + class: Drupal\Core\Logger\LoggerChannel + factory: logger.factory:get + arguments: [ 'yufu_concept' ] -- 2.30.2 From 7749fbaf2094a4705c464d8d262caa98302b88be Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Mon, 13 Nov 2023 13:12:08 +0100 Subject: [PATCH 6/8] 25: Add concept autocomplete endpoint. --- ...rce.concept_autocomplete_rest_resource.yml | 18 +++ config/sync/user.role.anonymous.yml | 2 + config/sync/user.role.authenticated.yml | 4 + ...est.resource.add_concept_rest_resource.yml | 18 +++ ...rce.concept_autocomplete_rest_resource.yml | 18 +++ .../rest/resource/ConceptAutocomplete.php | 116 ++++++++++++++++++ 6 files changed, 176 insertions(+) create mode 100644 config/sync/rest.resource.concept_autocomplete_rest_resource.yml create mode 100644 web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml create mode 100644 web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml create mode 100644 web/modules/custom/yufu_concept/src/Plugin/rest/resource/ConceptAutocomplete.php diff --git a/config/sync/rest.resource.concept_autocomplete_rest_resource.yml b/config/sync/rest.resource.concept_autocomplete_rest_resource.yml new file mode 100644 index 0000000..b10bc21 --- /dev/null +++ b/config/sync/rest.resource.concept_autocomplete_rest_resource.yml @@ -0,0 +1,18 @@ +uuid: 96dd83b8-5a29-43d5-a87e-a3be17c8b96c +langcode: en +status: true +dependencies: + module: + - serialization + - user + - yufu_concept +id: concept_autocomplete_rest_resource +plugin_id: concept_autocomplete_rest_resource +granularity: resource +configuration: + methods: + - GET + formats: + - json + authentication: + - cookie diff --git a/config/sync/user.role.anonymous.yml b/config/sync/user.role.anonymous.yml index 3d919db..6ba9c02 100644 --- a/config/sync/user.role.anonymous.yml +++ b/config/sync/user.role.anonymous.yml @@ -5,6 +5,7 @@ dependencies: config: - node.type.concept - rest.resource.add_concept_rest_resource + - rest.resource.concept_autocomplete_rest_resource - workflows.workflow.concept_workflow module: - content_moderation @@ -22,6 +23,7 @@ permissions: - 'access content' - 'create concept content' - 'edit any concept content' + - 'restful get concept_autocomplete_rest_resource' - 'restful post add_concept_rest_resource' - 'use concept_workflow transition create_new_draft' - 'view media' diff --git a/config/sync/user.role.authenticated.yml b/config/sync/user.role.authenticated.yml index fc5a6c7..5adfc21 100644 --- a/config/sync/user.role.authenticated.yml +++ b/config/sync/user.role.authenticated.yml @@ -6,10 +6,12 @@ dependencies: - node.type.article - node.type.concept - rest.resource.add_concept_rest_resource + - rest.resource.concept_autocomplete_rest_resource - taxonomy.vocabulary.tags - workflows.workflow.concept_workflow module: - content_moderation + - file - media - node - rest @@ -28,7 +30,9 @@ permissions: - 'create concept content' - 'create media' - 'create terms in tags' + - 'delete own files' - 'edit any concept content' + - 'restful get concept_autocomplete_rest_resource' - 'restful post add_concept_rest_resource' - 'use concept_workflow transition create_new_draft' - 'use jsonapi operation link' diff --git a/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml b/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml new file mode 100644 index 0000000..888e462 --- /dev/null +++ b/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml @@ -0,0 +1,18 @@ +uuid: 589ee957-7efd-45d3-979b-93b5b1018761 +langcode: en +status: true +dependencies: + module: + - serialization + - user + - yufu_concept +id: add_concept_rest_resource +plugin_id: add_concept_rest_resource +granularity: resource +configuration: + methods: + - POST + formats: + - json + authentication: + - cookie diff --git a/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml b/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml new file mode 100644 index 0000000..b10bc21 --- /dev/null +++ b/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml @@ -0,0 +1,18 @@ +uuid: 96dd83b8-5a29-43d5-a87e-a3be17c8b96c +langcode: en +status: true +dependencies: + module: + - serialization + - user + - yufu_concept +id: concept_autocomplete_rest_resource +plugin_id: concept_autocomplete_rest_resource +granularity: resource +configuration: + methods: + - GET + formats: + - json + authentication: + - cookie diff --git a/web/modules/custom/yufu_concept/src/Plugin/rest/resource/ConceptAutocomplete.php b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/ConceptAutocomplete.php new file mode 100644 index 0000000..ca8086a --- /dev/null +++ b/web/modules/custom/yufu_concept/src/Plugin/rest/resource/ConceptAutocomplete.php @@ -0,0 +1,116 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->getParameter('serializer.formats'), + $container->get('logger.channel.yufu_concept'), + $container->get('entity_type.manager') + ); + } + + public function get(Request $request) { + $results = []; + $input = $request->query->get('q');// Get the typed string from the URL, if + // it exists. + $num = $request->query->get('num') ?? 10; + $start = $request->query->get('start') ?? 0; + if (!$input) { + return new JsonResponse($results); + } + $input = Xss::filter($input); + $node_storage = $this->entityTypeManager->getStorage('node'); + $query = $node_storage->getQuery() + ->condition('type', 'concept') + ->condition('title', $input, 'CONTAINS') + ->groupBy('nid') + ->sort('created', 'DESC') + ->accessCheck(TRUE) + ->range($start, $num); + $ids = $query->execute(); + $nodes = $ids ? $node_storage->loadMultiple($ids) : []; + foreach ($nodes as $id => $node) { + $results[$id] = [ + 'title' => $node->getTitle(), + 'id' => $node->id(), + 'revision_id' => $node->getRevisionId(), + 'revision_uid' => $node->getRevisionUserId(), + 'uuid' => $node->uuid(), + 'uid' => $node->uid->target_id, + ]; + } + return new JsonResponse($results); + } + +} -- 2.30.2 From 44fba60a76e5c86eab51e427562719dd90c29d11 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Mon, 13 Nov 2023 18:19:05 +0100 Subject: [PATCH 7/8] 25: Remove uuid from config install configs. --- .../config/install/rest.resource.add_concept_rest_resource.yml | 1 - .../install/rest.resource.concept_autocomplete_rest_resource.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml b/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml index 888e462..282f31e 100644 --- a/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml +++ b/web/modules/custom/yufu_concept/config/install/rest.resource.add_concept_rest_resource.yml @@ -1,4 +1,3 @@ -uuid: 589ee957-7efd-45d3-979b-93b5b1018761 langcode: en status: true dependencies: diff --git a/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml b/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml index b10bc21..5495447 100644 --- a/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml +++ b/web/modules/custom/yufu_concept/config/install/rest.resource.concept_autocomplete_rest_resource.yml @@ -1,4 +1,3 @@ -uuid: 96dd83b8-5a29-43d5-a87e-a3be17c8b96c langcode: en status: true dependencies: -- 2.30.2 From 93fa35caec094f1365d417a6c2594b94442f344c Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Sat, 2 Dec 2023 22:24:18 +0100 Subject: [PATCH 8/8] Add small test of concept endpoint. --- .../custom/yufu_concept/tests/local-emacs-test.rest | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest index f024295..d83459e 100644 --- a/web/modules/custom/yufu_concept/tests/local-emacs-test.rest +++ b/web/modules/custom/yufu_concept/tests/local-emacs-test.rest @@ -14,3 +14,10 @@ Cookies: "SSESSb6f5da6ef565138b872e3e58509d8150=0z6Zk4tRwTF4WAR%2CSO6rH0K5F7hqKp "email": "lio.novelli@radiostudent.si", "uuid": "70c1ace2-aaaa-4dc5-84ed-3f21b83cb23a" } + +# Testiramo autocomplete + +GET https://yufu-manifest.ddev.site/api/pojem/autocomplete?q=jadr +User-Agent: Emacs Restclient +Content-Type: application/json +Cookies: "SSESSb6f5da6ef565138b872e3e58509d8150=0z6Zk4tRwTF4WAR%2CSO6rH0K5F7hqKpbe28XRRHwvTxo%2CUnpC" -- 2.30.2