Commit 3aa2fe23 authored by szato's avatar szato
Browse files

Issue #3272121 by dianacastillo, szato: Json api should allow the field type to be a remote stream

parent 728e4640
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -38,5 +38,8 @@ filefield_sources_jsonapi.filefield_sources_jsonapi.*:
    basicAuthentication:
      type: boolean
      label: 'Basic authentication'
    remoteStream:
      type: boolean
      label: 'Store as remote stream'
    uuid:
      type: string
+11 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ use Drupal\filefield_sources_jsonapi\FileFieldSourcesJSONAPIInterface;
 *     "sortOptionList",
 *     "searchFilter",
 *     "itemsPerPage",
 *     "remoteStream",
 *     "uuid"
 *   },
 *   links = {
@@ -87,6 +88,8 @@ class FileFieldSourcesJSONAPI extends ConfigEntityBase implements FileFieldSourc

  protected $basicAuthentication = FALSE;

  protected $remoteStream = FALSE;

  /**
   * {@inheritdoc}
   */
@@ -148,6 +151,7 @@ class FileFieldSourcesJSONAPI extends ConfigEntityBase implements FileFieldSourc
   */
  public function getItemsPerPage() {
    return $this->itemsPerPage;

  }

  /**
@@ -157,6 +161,13 @@ class FileFieldSourcesJSONAPI extends ConfigEntityBase implements FileFieldSourc
    return $this->basicAuthentication;
  }

 /**
   * {@inheritdoc}
   */
  public function getRemoteStream() {
    return \Drupal::moduleHandler()->moduleExists('remote_stream_wrapper') && $this->remoteStream;
  }

  /**
   * Load entities to option list.
   */
+8 −0
Original line number Diff line number Diff line
@@ -89,4 +89,12 @@ interface FileFieldSourcesJSONAPIInterface extends ConfigEntityInterface {
   */
  public function getBasicAuthentication();

  /**
   * Returns the remote_stream value.
   *
   * @return string
   *   The remote_stream value.
   */
  public function getRemoteStream();

}
+22 −0
Original line number Diff line number Diff line
@@ -97,6 +97,11 @@ class FileFieldSourcesJSONAPIForm extends EntityForm {
      '#title' => $this->t('Items to display'),
      '#description' => $this->t('Number of items per page for browser.'),
      '#default_value' => $config->getItemsPerPage(),
      '#states' => [
        'visible' => [
          ':input[name="basicAuthentication[value]"]' => ['checked' => FALSE],
        ],
      ],
    ];
    $form['basicAuthentication'] = [
      '#type' => 'checkbox',
@@ -104,6 +109,23 @@ class FileFieldSourcesJSONAPIForm extends EntityForm {
      '#description' => $this->t('Select if files can be accessed only with basic authentication.'),
      '#default_value' => $config->getBasicAuthentication(),
    ];
    $form['remoteStream'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Store files as remote stream (without download)'),
      '#description' => $this->t('Select if files should be stored as remote file urls, otherwise will be downloaded. <strong>This will work only if remote files are accessible thru public URL.</strong>'),
      '#default_value' => $config->getRemoteStream() && !$config->getBasicAuthentication(),
      '#states' => [
        'disabled' => [
          'input[name="basicAuthentication"]' => ['checked' => TRUE],
        ],
      ],
    ];

    if (!$this->moduleHandler->moduleExists('remote_stream_wrapper')) {
      $form['remoteStream']['#value'] = FALSE;
      $form['remoteStream']['#description'] = $this->t('For this feature you need to install <a href=":url" target="_blank">Remote Stream Wrapper</a> module.', [':url' => 'https://www.drupal.org/project/remote_stream_wrapper']);
      $form['remoteStream']['#disabled'] = TRUE;
    }

    return $form;
  }
+247 −165
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\filefield_sources_jsonapi\Plugin\FilefieldSource;

use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\filefield_sources\Plugin\FilefieldSource\Remote;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\File\FileSystem;
@@ -16,15 +17,16 @@ use Drupal\image\Entity\ImageStyle;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Html;
use Drupal\Core\File\FileSystemInterface;
use GuzzleHttp\Exception\RequestException;

/**
 * FileField source plugin to allow downloading a file from JSON Rest API.
 * FileField source plugin to allow getting a file from JSON Rest API.
 *
 * @FilefieldSource(
 *   id = "remote_jsonapi",
 *   name = @Translation("JSON API remote URL"),
 *   label = @Translation("JSON API Library"),
 *   description = @Translation("Download a file from JSON Rest API.")
 *   description = @Translation("Download (or store as remote url) file from JSON Rest API.")
 * )
 */
class RemoteJSONAPI extends Remote {
@@ -38,6 +40,88 @@ class RemoteJSONAPI extends Remote {
   */
  public static function value(array &$element, &$input, FormStateInterface $form_state) {
    if (isset($input['filefield_remote_jsonapi']['url']) && strlen($input['filefield_remote_jsonapi']['url']) > 0 && UrlHelper::isValid($input['filefield_remote_jsonapi']['url']) && $input['filefield_remote_jsonapi']['url'] != FILEFIELD_SOURCE_REMOTE_HINT_TEXT) {
      $source = $input['filefield_remote_jsonapi']['source'];
      $config = FileFieldSourcesJSONAPI::load($source);

      if (!$config->getBasicAuthentication() && $config->getRemoteStream()) {
        $uri = $input['filefield_remote_jsonapi']['url'];
        // Copy of Drupal\remote_stream_wrapper\Plugin\FilefieldSource\RemoteFileUrl::value()
        $scheme = StreamWrapperManager::getScheme($uri);

        if (!UrlHelper::isValid($uri, TRUE)) {
          $form_state->setError($element, t('Invalid Remote File URL.'));
          return;
        }

        if (!\Drupal::service('stream_wrapper_manager')->isValidScheme($scheme)) {
          // Check that the scheme is supported.
          $form_state->setError($element, t('Remote file URL with the %scheme scheme are not supported.', ['%scheme' => $scheme]));
          return;
        }

        // Check that the file url exists.
        try {
          $response = \Drupal::httpClient()->get($uri, ['headers' => ['Accept' => 'text/plain']]);
          $data = (string) $response->getBody();
          if (empty($data)) {
            return;
          }
        }
        catch (RequestException $e) {
          $form_state->setError($element, t('Unable to fetch remote file URL: %url (error code: @code).', ['%url' => $uri, '@code' => $e->getCode()]));
          return;
        }

        try {
          $files = \Drupal::entityTypeManager()
            ->getStorage('file')
            ->loadByProperties(['uri' => $uri]);
          $file = reset($files);

          if (!$file) {
            /** @var \Drupal\file\FileInterface $file */
            $file = \Drupal::entityTypeManager()
              ->getStorage('file')->create([
                'uri' => $uri,
                'uid' => \Drupal::currentUser()->id(),
              ]);

            // Validate file.
            $errors = file_validate($file, $element['#upload_validators']);
            if (!empty($errors)) {
              $message = [
                'error' => [
                  '#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()]),
                ],
                'item_list' => [
                  '#theme' => 'item_list',
                  '#items' => $errors,
                ],
              ];
              $form_state->setError($element, $message);
              return;
            }

            $file->save();
          }
        }
        catch (\Exception $e) {
          $form_state->setError($element, $e->getMessage());
          return;
        }

        if (empty($file->id())) {
          $form_state->setError($element, t('Unable to add file from URL %uri.', ['%uri' => $uri]));
          return;
        }

        if ($file) {
          if (!in_array($file->id(), $input['fids'])) {
            $input['fids'][] = $file->id();
          }
        }
      }
      else {
        /** @var \Drupal\Core\File\FileSystemInterface $fileSystem */
        $fileSystem = \Drupal::service('file_system');

@@ -66,8 +150,6 @@ class RemoteJSONAPI extends Remote {

        // Check the basicAuthentication config value and if it is checked, we get
        // the file with basic authentication.
      $source = $input['filefield_remote_jsonapi']['source'];
      $config = FileFieldSourcesJSONAPI::load($source);
        $basic_auth = $config->getBasicAuthentication();
        if ($basic_auth) {
          $myConfig = \Drupal::config('filefield_sources_jsonapi');
@@ -172,8 +254,7 @@ class RemoteJSONAPI extends Remote {
            fclose($fp);
            $transfer_success = TRUE;
          }
      }
      // If we don't have the file contents, download the actual file.
        } // If we don't have the file contents, download the actual file.
        else {
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, $url);
@@ -238,6 +319,7 @@ class RemoteJSONAPI extends Remote {
        @unlink($filepath);
      }
    }
  }

  /**
   * {@inheritdoc}