Commit 9a418fb3 authored by Gorodkov Denis's avatar Gorodkov Denis

refactor swapi

parent 6a003656
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
"drupal/media_library_form_element": "^2.0", "drupal/media_library_form_element": "^2.0",
"drupal/metatag": "^1.19", "drupal/metatag": "^1.19",
"drupal/module_filter": "^3.2", "drupal/module_filter": "^3.2",
"drupal/multivalue_form_element": "^1.0@beta",
"drupal/paragraphs": "^1.14", "drupal/paragraphs": "^1.14",
"drupal/pathauto": "^1.10", "drupal/pathauto": "^1.10",
"drupal/queue_ui": "^3.0", "drupal/queue_ui": "^3.0",
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "d57ba08c5cb54e2299992757b090cecc", "content-hash": "c7ef5cfad65afbf520d105d6b4e18906",
"packages": [ "packages": [
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
...@@ -4677,6 +4677,108 @@ ...@@ -4677,6 +4677,108 @@
"issues": "https://www.drupal.org/project/issues/module_filter" "issues": "https://www.drupal.org/project/issues/module_filter"
} }
}, },
{
"name": "drupal/multivalue_form_element",
"version": "1.0.0-beta3",
"source": {
"type": "git",
"url": "https://git.drupalcode.org/project/multivalue_form_element.git",
"reference": "1.0.0-beta3"
},
"dist": {
"type": "zip",
"url": "https://ftp.drupal.org/files/projects/multivalue_form_element-1.0.0-beta3.zip",
"reference": "1.0.0-beta3",
"shasum": "8e0e46a0bcebdcc09108362598c760adfaecd00a"
},
"require": {
"drupal/core": "^9.2",
"php": ">=7.4"
},
"require-dev": {
"composer/installers": "^1.11",
"drupal/core-composer-scaffold": "^9.2",
"drupal/core-dev": "^9.2",
"drupal/drupal-extension": "^4.1",
"drush/drush": "^10.3",
"egulias/email-validator": "^2.1.22 || ^3.0",
"openeuropa/code-review": "^2.0",
"openeuropa/task-runner-drupal-project-symlink": "^1.0.0-beta5",
"phpspec/prophecy-phpunit": "^2"
},
"type": "drupal-module",
"extra": {
"drupal": {
"version": "1.0.0-beta3",
"datestamp": "1644318395",
"security-coverage": {
"status": "not-covered",
"message": "Project has not opted into security advisory coverage!"
}
},
"composer-exit-on-patch-failure": true,
"enable-patching": true,
"drupal-scaffold": {
"locations": {
"web-root": "./build"
}
},
"installer-paths": {
"build/core": [
"type:drupal-core"
],
"build/profiles/contrib/{$name}": [
"type:drupal-profile"
],
"build/modules/contrib/{$name}": [
"type:drupal-module"
],
"build/themes/contrib/{$name}": [
"type:drupal-theme"
]
},
"_readme": [
"Explicit requirement for egulias/email-validator due to https://www.drupal.org/project/drupal/issues/3061074#comment-14300579. It can be removed when Drupal core 9.2 support is droppped."
]
},
"autoload": {
"psr-4": {
"Drupal\\multivalue_form_element\\": "./src/"
}
},
"autoload-dev": {
"psr-4": {
"Drupal\\Tests\\multivalue_form_element\\": "./tests/src/"
}
},
"notification-url": "https://packages.drupal.org/8/downloads",
"scripts": {
"post-install-cmd": [
"./vendor/bin/run drupal:site-setup"
],
"post-update-cmd": [
"./vendor/bin/run drupal:site-setup"
]
},
"license": [
"EUPL-1.2"
],
"authors": [
{
"name": "hernani",
"homepage": "https://www.drupal.org/user/448086"
},
{
"name": "sardara",
"homepage": "https://www.drupal.org/user/2353864"
}
],
"description": "Provides a form element that wraps existing form elements, making them multi-value.",
"homepage": "https://www.drupal.org/project/multivalue_form_element",
"support": {
"source": "https://git.drupalcode.org/project/multivalue_form_element"
}
},
{ {
"name": "drupal/paragraphs", "name": "drupal/paragraphs",
"version": "1.14.0", "version": "1.14.0",
...@@ -11212,6 +11314,7 @@ ...@@ -11212,6 +11314,7 @@
"aliases": [], "aliases": [],
"minimum-stability": "dev", "minimum-stability": "dev",
"stability-flags": { "stability-flags": {
"drupal/multivalue_form_element": 10,
"drupal/rabbit_hole": 10, "drupal/rabbit_hole": 10,
"drupal/schema": 15, "drupal/schema": 15,
"drupal/ultimate_cron": 15 "drupal/ultimate_cron": 15
......
...@@ -4,6 +4,7 @@ use Drupal\Core\Ajax\AjaxResponse; ...@@ -4,6 +4,7 @@ use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
/** /**
* Implements hook_form_alter(). * Implements hook_form_alter().
*/ */
......
...@@ -9,6 +9,7 @@ use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderItemPercentage ...@@ -9,6 +9,7 @@ use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderItemPercentage
use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderPromotionOfferBase; use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderPromotionOfferBase;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\multivalue_form_element\Element\MultiValue;
/** /**
* @CommercePromotionOffer( * @CommercePromotionOffer(
...@@ -19,34 +20,65 @@ use Drupal\Core\Form\FormStateInterface; ...@@ -19,34 +20,65 @@ use Drupal\Core\Form\FormStateInterface;
*/ */
class CustomPromotion extends OrderPromotionOfferBase { class CustomPromotion extends OrderPromotionOfferBase {
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { public function getIdsFromForm($form_state) {
$form = parent::buildConfigurationForm($form, $form_state); $info = $form_state->getUserInput();
$items = $info['offer'][0]["target_plugin_configuration"]["custom_commerce_custom_promotion"]["items"][0][0];
$default_first_item = \Drupal::entityTypeManager()->getStorage('commerce_product')->load($this->configuration['first_item']); #$values = $form_state->getValue($form['items']);
$default_second_item = \Drupal::entityTypeManager()->getStorage('commerce_product')->load($this->configuration['second_item']); foreach ($items as $item) {
if (!empty($item)) {
$form['first_item'] = [ $item_id = explode('(', $item);
$item_id = end($item_id);
$item_id = explode(')', $item_id);
$id = $item_id[0];
$ids[] = $id;
}
}
return $ids;
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$ids = $this->getIdsFromForm($form_state);
/*if (!empty($ids)) {
foreach ($ids as $id_product_item) {
$default_value = \Drupal::entityTypeManager()->getStorage('commerce_product')->load($id_product_item);
$items[] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'commerce_product',
'#title' => 'Выберите товар',
'#default_value' => !empty($default_value) ? $default_value : '',
];
}
} else {
$items[] = [
'#type' => 'entity_autocomplete', '#type' => 'entity_autocomplete',
'#target_type' => 'commerce_product', '#target_type' => 'commerce_product',
'#title' => 'Выберите первый продукт', '#title' => 'Выберите товар',
'#default_value' => !empty($default_first_item) ? $default_first_item : '',
]; ];
}*/
$items[] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'commerce_product',
'#title' => 'Выберите товар',
];
$form['second_item'] = [ $form['items'] = [
'#type' => 'multivalue',
'#title' => $this->t('Items'),
'#cardinality' => MultiValue::CARDINALITY_UNLIMITED,
'item' => [
'#type' => 'entity_autocomplete', '#type' => 'entity_autocomplete',
'#target_type' => 'commerce_product', '#target_type' => 'commerce_product',
'#title' => 'Выберите второй продукт', '#title' => 'Выберите товар',
'#default_value' => !empty($default_second_item) ? $default_second_item : '', ],
]; ];
return $form; return $form;
} }
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
if (!$form_state->getErrors()) { if (!$form_state->getErrors()) {
$values = $form_state->getValue($form['#parents']); $this->configuration['items'] = $this->getIdsFromForm($form_state);
$this->configuration['first_item'] = $values['first_item'];
$this->configuration['second_item'] = $values['second_item'];
} }
} }
......
...@@ -70,6 +70,7 @@ class API { ...@@ -70,6 +70,7 @@ class API {
'type' => $bundle, 'type' => $bundle,
'field_swapi_id' => $swapi_id, 'field_swapi_id' => $swapi_id,
]); ]);
foreach ($nodes as $value) { foreach ($nodes as $value) {
$node = $value; $node = $value;
} }
......
<?php
namespace Drupal\swapi\Plugin\QueueWorker;
use Drupal\Core\Queue\QueueWorkerBase;
/**
* QueueueWorker
*
* @QueueWorker (
* id = "swapi",
* title = "Queue swapi",
* cron = {"time" = 60}
* )
*/
class QueueSwapi extends QueueWorkerBase {
public function processItem($data) {
/**
* @var Drupal\swapi\Service\swapi
*/
$swapi = \Drupal::service('swapi.service_swapi');
$node = $swapi->getNodeFromUrl($data['url']);
$swapi->update($data, $node);
}
}
<?php
namespace Drupal\swapi\Service;
use GuzzleHttp\ClientInterface;
class swapi {
private $http_client;
private $url;
private $queue;
public function __construct(ClientInterface $http_client) {
$this->http_client = $http_client;
$this->url = 'https://swapi.dev/api/';
$this->queue = \Drupal::queue('swapi');
$this->queue->createQueue();
}
public function getResponse() {
$response = $this->http_client->request('GET', $this->url);
$response = json_decode($response->getBody()->getContents(), TRUE);
return $response;
}
public function setUrl($url) {
$this->url = $url;
return $this;
}
public function getUrl() {
return $this->url;
}
public function addQueue($items, $gmt_time_cron) {
$queue = $this->queue;
foreach ($items as $item) {
$node = $this->getNodeFromUrl($item['url']);
if ($node) {
if ($node->isPublished()) {
$gmp_time_update_node = $node->getChangedTime();
if ($gmp_time_update_node > $gmt_time_cron) {
$queue->createItem($item);
}
} else {
$queue->createItem($item);
}
} else {
$this->createNode($item);
$queue->createItem($item);
}
}
}
public function getNodeFromUrl($url) {
$bundle = $this->getBundle($url);
$swapi_id = $this->getSwapiId($url);
$nodes = \Drupal::entityTypeManager()
->getStorage('node')
->loadByProperties([
'type' => $bundle,
'field_swapi_id' => $swapi_id,
]);
$node = current($nodes);
return isset($node) ? $node : null;
}
public function update($data, $node) {
$title = $data[array_keys($data)[0]];
$node->setTitle($title);
foreach ($data as $key => $value) {
$field_name = "field_" . strtolower($key);
unset($node_add);
if ($node->hasField($field_name) and isset($value)) {
if (is_array($value)) {
foreach ($value as $url) {
$node_add[] = $this->getNodeFromUrl($url);
}
$node->set($field_name, $node_add);
continue;
}
if ($key == 'homeworld') {
$node_add = $this->getNodeFromUrl($value);
$node->set($field_name, $node_add);
continue;
}
$node->set($field_name, $value);
}
}
$node->setPublished();
$node->save();
}
public function createNode($item) {
$title = $item[array_keys($item)[0]];
$bundle = $this->getBundle($item['url']);
$swapi_id = $this->getSwapiId($item['url']);
$node = \Drupal::entityTypeManager()
->getStorage('node')
->create([
'type' => $bundle,
'title' => $title,
'field_swapi_id' => $swapi_id
]);
$node->setUnpublished();
$node->save();
}
public function getSwapiId($url) {
$swapi_id = explode('/', stristr($url, 'api/'));
return $swapi_id[2];
}
public function getBundle($url) {
$type_node = explode('/', stristr($url, 'api/'));
return $type_node[1];
}
}
name: swapi
description: Custom task
package: Tasks
type: module
core: 8.x
core_version_requirement: ^8 || ^9
<?php
/**
* @file
* Main file for hooks and custom functions.
*/
/**
* Implements hook_cron().
*/
function swapi_cron() {
/**
* @var Drupal\swapi\Service\swapi
*/
$swapi = \Drupal::service('swapi.service_swapi');
$gmt_time_cron = \Drupal::state()->get('cron_time_swapi');
$urls = $swapi->getResponse();
$items = [];
foreach ($urls as $url) {
$result = $swapi->setUrl($url)
->getResponse();
$items = array_merge($items, $result['results']);
while ($result['next']) {
$result = $swapi->setUrl($result['next'])
->getResponse();
$items = array_merge($items, $result['results']);
}
}
$swapi->addQueue($items, $gmt_time_cron);
$gmt_time_cron = \Drupal::time()->getCurrentTime();
Drupal::state()->set('cron_time_swapi', $gmt_time_cron);
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function swapi_form_contact_message_feedback_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
$uid = \Drupal::currentUser()->id();
if ($uid) {
$user = \Drupal::entityTypeManager()->getStorage('user')->load($uid);
$name = $user->get('field_name')->getValue();
$surname = $user->get('field_surname')->getValue();
if (!empty($name[0]['value'])) {
$form['field_name']['widget'][0]['value']['#value'] = $name[0]['value'];
}
if (!empty($surname[0]['value'])) {
$form['field_surname']['widget'][0]['value']['#value'] = $surname[0]['value'];
}
}
}
function swapi_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form['#id'], 'views-exposed-form-index-films') !== false) {
$form["actions"]["reset"]["#access"] = true;
}
}
services:
swapi.service_swapi:
class: Drupal\swapi\Service\swapi
arguments: [ '@http_client' ]
1) Создать на сайте Content Types, перечисленные ниже и соответствующие
поля(fields) для них:
- People
- Films
- Starships
- Vehicles
- Species
- Planets
2) Сделать сервис(Service) для общения с API (https://swapi.dev), реализовать
методы для получения данных для каждого типа контента из списка из п.1.
3) Получить все данные с помощью сервиса из п.2, обработать данные с
помощью очереди(Queue) и крона(Cron) и создать ноды(Nodes) для каждого
типа контента в процессе обработки очереди. Для работы с кроном потребуется
установить модуль Ultimate Cron(https://www.drupal.org/project/ultimate_cron),
установить его нужно через Composer.
4) После того, как все нужные ноды будут созданы, необходимо вывести на
отдельную страницу в административном интерфейсе список всех нод с типом
People с фильтрами по полям - name, homeworld, gender, height. Должна быть
возможность отсортировать по колонке name.
5) Создать страницу с контактной формой, добавить в нее поля “Имя” и
“Фамилия”(предварительно создать такие же поля в сущности User). Если юзер
авторизован и эти поля заполнены, в форме они должны подставляться
автоматически. При сабмите формы отправляется письмо на указанный адрес.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment