From 98976d12c81e1659d6e745f86fac1a2104e84343 Mon Sep 17 00:00:00 2001 From: Dimitris Spachos Date: Wed, 18 Dec 2024 16:40:21 +0200 Subject: [PATCH] fix(slb-495): add standalone page drop functionality for web pages --- .../silverback_ai_import.module | 18 +--- .../src/ContentImportAiService.php | 65 +++++++++++++ .../src/Form/PageDropForm.php | 96 +++++++------------ 3 files changed, 100 insertions(+), 79 deletions(-) diff --git a/packages/drupal/silverback_ai/modules/silverback_ai_import/silverback_ai_import.module b/packages/drupal/silverback_ai/modules/silverback_ai_import/silverback_ai_import.module index 1400b47b7..121772908 100644 --- a/packages/drupal/silverback_ai/modules/silverback_ai_import/silverback_ai_import.module +++ b/packages/drupal/silverback_ai/modules/silverback_ai_import/silverback_ai_import.module @@ -5,9 +5,7 @@ * Primary module hooks for silverback_ai_import module. */ -use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\file\Entity\File; /** * {@inheritdoc} @@ -115,21 +113,7 @@ function _silverback_ai_import_form_submit(array $form, FormStateInterface $form return; } - $filepath = $file['uploaded_files'][0]['path']; - $directory = 'public://converted'; - $file_system = \Drupal::service('file_system'); - $file_system->prepareDirectory($directory, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); - $file_system->copy($filepath, $directory . '/' . basename($filepath), FileSystemInterface::EXISTS_REPLACE); - - $file = File::create([ - 'filename' => basename($filepath), - 'uri' => "{$directory}/" . basename($filepath), - 'status' => 1, - 'uid' => \Drupal::currentUser()->id() ?? 1, - ]); - - $file->setPermanent(); - $file->save(); + $file = $service->createFileEntityFromDropzoneData($file); if ($file) { $ast = $service->getAstFromFilePath($file); diff --git a/packages/drupal/silverback_ai/modules/silverback_ai_import/src/ContentImportAiService.php b/packages/drupal/silverback_ai/modules/silverback_ai_import/src/ContentImportAiService.php index c867c2706..98f57c61c 100644 --- a/packages/drupal/silverback_ai/modules/silverback_ai_import/src/ContentImportAiService.php +++ b/packages/drupal/silverback_ai/modules/silverback_ai_import/src/ContentImportAiService.php @@ -6,10 +6,14 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\file\Entity\File; use Drupal\file\FileInterface; +use Drupal\node\Entity\Node; +use Drupal\node\NodeInterface; use Drupal\silverback_ai\HttpClient\OpenAiHttpClient; use GuzzleHttp\Exception\RequestException; @@ -19,6 +23,7 @@ final class ContentImportAiService { private const DEFAULT_AI_MODEL = 'gpt-4o-mini'; + private const ADMINISTRATOR_ID = 1; /** * Constructs a ContentImportAiService object. @@ -506,4 +511,64 @@ public function extractPageDataFromUrl($url) { return $data; } + /** + * + */ + public function createEntityFromDocxAst($ast) { + $markdown = file_get_contents($ast->outputDirectory . '/content.md'); + $data = $this->extractBaseDataFromMarkdown($markdown); + // @todo Surround with try-catch + if (isset($data['choices'][0]['message']['content'])) { + $data = json_decode($data['choices'][0]['message']['content'], TRUE); + $entity = Node::create([ + 'type' => 'page', + 'title' => $data['title'], + 'langcode' => strtolower($data['language']), + ]); + $entity->save(); + return $entity; + } + return NULL; + } + + /** + * + */ + public function createEntityFromUrl($url) { + $data = $this->extractPageDataFromUrl($url); + // @todo Handle exceptions + if (!empty($data['title']) && !empty($data['language'])) { + $entity = Node::create([ + 'type' => 'page', + 'title' => $data['title'], + 'langcode' => strtolower($data['language']), + ]); + $entity->save(); + return $entity; + } + return NULL; + } + + /** + * + */ + public function createFileEntityFromDropzoneData($file_data) { + // @todo Handle exceptions + $filepath = $file_data['uploaded_files'][0]['path']; + $directory = 'public://converted'; + $file_system = \Drupal::service('file_system'); + $file_system->prepareDirectory($directory, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); + $file_system->copy($filepath, $directory . '/' . basename($filepath), FileSystemInterface::EXISTS_REPLACE); + + $file = File::create([ + 'filename' => basename($filepath), + 'uri' => "{$directory}/" . basename($filepath), + 'status' => NodeInterface::PUBLISHED, + 'uid' => $this->currentUser->id() ?? self::ADMINISTRATOR_ID, + ]); + $file->setPermanent(); + $file->save(); + return $file; + } + } diff --git a/packages/drupal/silverback_ai/modules/silverback_ai_import/src/Form/PageDropForm.php b/packages/drupal/silverback_ai/modules/silverback_ai_import/src/Form/PageDropForm.php index ee92c1462..0132d3b75 100644 --- a/packages/drupal/silverback_ai/modules/silverback_ai_import/src/Form/PageDropForm.php +++ b/packages/drupal/silverback_ai/modules/silverback_ai_import/src/Form/PageDropForm.php @@ -4,16 +4,10 @@ namespace Drupal\silverback_ai_import\Form; -use Drupal\Core\Ajax\AjaxResponse; -use Drupal\Core\Ajax\ReplaceCommand; -use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Markup; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\file\Entity\File; -use Drupal\node\Entity\Node; -use Drupal\node\NodeInterface; /** * Provides a Silverback Import AI form. @@ -114,7 +108,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#suffix' => '', ]; - // $form['actions']['submit']['#submit'][] = '_silverback_ai_import_form_submit'; $form['actions'] = [ '#type' => 'actions', '#states' => [ @@ -124,37 +117,26 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ], 'submit' => [ '#type' => 'submit', - '#value' => $this->t('Process document'), - /* '#attributes' => [ - 'class' => [ - 'use-ajax-submit', - ], + '#value' => $this->t('Import document'), + ], + ]; + + $form['actions_url'] = [ + '#type' => 'actions', + '#states' => [ + 'visible' => [ + 'input[name="import_type"]' => ['value' => 'url'], ], - '#ajax' => [ - '#progress_indicator' => 'throbber', - '#progress_message' => $this->t('Validating input'), - 'callback' => '::myAjaxCallbackDocx', - 'event' => 'click', - 'wrapper' => 'edit-output', - ], */ + ], + 'submit' => [ + '#type' => 'submit', + '#value' => $this->t('Import web page'), ], ]; return $form; } - /** - * The textbox with the selected text. - */ - public function myAjaxCallbackDocx(array &$form, FormStateInterface $form_state) { - $file = $form_state->getValue('file'); - - $response = new AjaxResponse(); - - $response->addCommand(new ReplaceCommand('#edit-output', '
' . $this->t('Please upload a file') . '
')); - return $response; - } - /** * {@inheritdoc} */ @@ -171,47 +153,37 @@ public function validateForm(array &$form, FormStateInterface $form_state): void */ public function submitForm(array &$form, FormStateInterface $form_state): void { $type = $form_state->getValue('import_type'); + $url_value = $form_state->getValue('url_value'); + + // @todo Add DI + $service = \Drupal::service('silverback_ai_import.content'); + $content = \Drupal::service('silverback_ai_import.batch.import'); + if ($type == 'docx') { - $file = $form_state->getValue('file'); - $filepath = $file['uploaded_files'][0]['path']; - $directory = 'public://converted'; - $file_system = \Drupal::service('file_system'); - $file_system->prepareDirectory($directory, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); - $file_system->copy($filepath, $directory . '/' . basename($filepath), FileSystemInterface::EXISTS_REPLACE); - - $file = File::create([ - 'filename' => basename($filepath), - 'uri' => "{$directory}/" . basename($filepath), - 'status' => NodeInterface::PUBLISHED, - 'uid' => \Drupal::currentUser()->id() ?? 1, - ]); - - $file->setPermanent(); - $file->save(); + $file_data = $form_state->getValue('file'); + $file = $service->createFileEntityFromDropzoneData($file_data); if ($file) { - $service = \Drupal::service('silverback_ai_import.content'); $ast = $service->getAstFromFilePath($file); + $entity = $service->createEntityFromDocxAst($ast); - $markdown = file_get_contents($ast->outputDirectory . '/content.md'); - $openai = \Drupal::service('silverback_ai_import.content'); - $data = $openai->extractBaseDataFromMarkdown($markdown); - if (isset($data['choices'][0]['message']['content'])) { - $content = \Drupal::service('silverback_ai_import.batch.import'); - $data = json_decode($data['choices'][0]['message']['content'], TRUE); - $entity = Node::create([ - 'type' => 'page', - 'title' => $data['title'], - 'langcode' => strtolower($data['language']), - ]); - $entity->save(); - $ast = $service->getAstFromFilePath($file); + if ($entity) { + // @todo Add DI $flatten = $service->flattenAst($ast->content); $content->create($flatten, $entity); - $form_state->setRedirectUrl($entity->toUrl()); + $form_state->setRedirectUrl($entity->toUrl('edit-form')); } } } + elseif (!empty($url_value) && $type == 'url') { + $entity = $service->createEntityFromUrl($url_value); + if ($entity) { + $ast = $service->getAstFromUrl($url_value); + $flatten = $service->flattenAst($ast->content); + $content->create($flatten, $entity); + $form_state->setRedirectUrl($entity->toUrl('edit-form')); + } + } }