Commit 82b3569f authored by Joop Sint Jago's avatar Joop Sint Jago Committed by Joop Sint Jago
Browse files

Issue #3254557 by jamesyao, mmbk, clivesj: A custom feature needs to display...

Issue #3254557 by jamesyao, mmbk, clivesj: A custom feature needs to display the external URLs for uploaded files in the public folder
parent 87000e13
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -27,3 +27,5 @@ filebrowser:
    default_sort: 'name'
    default_sort_order: 'asc'
    langcode: 'en'
  adhocsetting:
    external_host: ''
+7 −0
Original line number Diff line number Diff line
@@ -97,3 +97,10 @@ filebrowser.settings:
            langcode:
              type: string
              label: 'Language code'
        adhocsetting:
          type: mapping
          label: 'Adhoc Settings'
          mapping:
            external_host:
              type: string
              label: 'External host'
+33 −0
Original line number Diff line number Diff line
@@ -70,6 +70,12 @@ function filebrowser_schema() {
        'size' => 'big',
        'description' => 'serialised data containing the filebrowser settings for this node',
      ],
      'external_host' => [
        'type' => 'varchar',
        'description' => "External host",
        'length' => 256,
        'not null' => FALSE,
      ],
    ],
    'primary key' => ['nid'],
  ];
@@ -159,3 +165,30 @@ function filebrowser_update_9102() {
  $active_storage = Drupal::service('config.storage');
  $active_storage->write('filebrowser.settings', $source->read('filebrowser.settings'));
}

/**
 * update database schema to include external_host
 */
function filebrowser_update_9103() {
  $external_host = [
    'type' => 'varchar',
    'description' => "External host",
    'length' => 256,
    'not null' => FALSE,
  ];
  Database::setActiveConnection();
  $schema = Database::getConnection()->schema();
  $schema->addField('filebrowser_nodes', 'external_host', $external_host);
}

/**
 * Add update active configuration to include new setting: external_host.
 */
function filebrowser_update_9104() {
  $module_path = Drupal::service('module_handler')->getModule('filebrowser')->getPath();
  $source = new FileStorage($module_path . '/config/install');
  /** @var \Drupal\Core\Config\StorageInterface $active_storage */
  $active_storage = Drupal::service('config.storage');
  $active_storage->write('filebrowser.settings', $source->read('filebrowser.settings'));
}
+1 −0
Original line number Diff line number Diff line
@@ -186,3 +186,4 @@ class FilebrowserManagedFile extends ManagedFile {
    return $return;
  }
}
+120 −72
Original line number Diff line number Diff line
@@ -5,12 +5,14 @@ namespace Drupal\filebrowser\File;
use Drupal;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\filebrowser\Events\MetadataEvent;
use Drupal\filebrowser\ServerFileList;
use Drupal\node\NodeInterface;

/**
 * Class FileDisplayList
 * Class FileDisplayList.
 *
 * @package Drupal\filebrowser
 * This class holds the list of files to be displayed on the filebrowser node.
 * These files are retrieved from the filesystem and filtered for user and node access.
@@ -28,7 +30,8 @@ class DisplayFileList extends ControllerBase {
  /**
   * List of the files ready to be passes to presentation
   * This list will appear on the node view
   * @var array $displayFiles
   *
   * @var array
   */
  protected $files;
  /**
@@ -45,7 +48,8 @@ class DisplayFileList extends ControllerBase {
  /**
   * List of files as retrieved from the server source and
   * already filters as per node and per user permissions
   * @var array $serverFileList
   *
   * @var array
   */
  protected $serverFileList;

@@ -66,7 +70,7 @@ class DisplayFileList extends ControllerBase {
  protected $storage;

  /**
   * @var \Drupal\Core\Session\AccountInterface $user
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $user;

@@ -76,27 +80,30 @@ class DisplayFileList extends ControllerBase {
  protected $filebrowser;

  /**
   * @var int $fid
   * @var int
   */
  protected $fid;

  /**
   * @var string $relativePath
   * @var string
   */
  protected $relativePath;

  /**
   * @var boolean
   * @var bool
   */
  protected $isSubDir;

  /**
   * @var string fsRoot The root directory of this filebrowser
   * @var string
   */
  protected $fsRoot;

  /**
   * {@inheritdoc}
   */
  public function __construct(NodeInterface $node, $fid) {
    $this->data = null;
    $this->data = NULL;

    $this->files = [];
    $this->node = $node;
@@ -135,22 +142,21 @@ class DisplayFileList extends ControllerBase {
   * @return mixed
   */
  protected function createFileDisplayList() {
    // file list
    // File list
    $cid = 'filebrowser/' . $this->node->id() . '/' . $this->fid;

    // you are requesting a subdir: node/23?fid=nn
    if ($this->fid) {
      $content = $this->storage->nodeContentLoadMultiple([$this->fid]);
      //debug($content[$this->fid]);
      if (empty($content[$this->fid])) {
        // There is no DB data for this fid
        // There is no DB data for this fid.
        return false;
      }
      // When accessing a subdir relativePath will be /subdir[/other sub dir]
      // When accessing a subdir relativePath will be /subdir[/other sub dir].
      $this->relativePath = $content[$this->fid]['path'];
      $this->fsRoot = $this->relativePath;
    }
    // you are requesting the basic node like: /node/23
    // you are requesting the basic node like: /node/23.
    else {
      $this->relativePath = '/';
    }
@@ -158,60 +164,63 @@ class DisplayFileList extends ControllerBase {
    $this->isSubDir = $this->relativePath != '/';
    // If this is a sub dir, check if we may access it, else redirect to root_dir.
    if ($this->isSubDir && !$this->common->canExploreSubFolders($this->node)) {
      Drupal::messenger()->addError($this->t('You\'re not allowed to browse sub folders.'));
      return false;
      Drupal::messenger()
        ->addError($this->t('You\'re not allowed to browse sub folders.'));
      return FALSE;
    }

    // full path valid?
    if ($this->fsRoot === false) {
      Drupal::messenger()->addError($this->t('Configured folder is not readable or is not a directory.'));
      return false;
    // Full path valid?
    if ($this->fsRoot === FALSE) {
      Drupal::messenger()
        ->addError($this->t('Configured folder is not readable or is not a directory.'));
      return FALSE;
    }

    // retrieve files from the system - returned list is filtered *per-node* settings
    // Retrieve files from the system - returned list is filtered *per-node* settings.
    $list = new ServerFileList($this->node, $this->relativePath);
    $this->serverFileList = $list->getList();
    // debug($this->serverFileList);

    // create DB contents and return the files for display ($result)
    // Create DB contents and return the files for display ($result)
    $result = $this->processServerFileList();
    $this->files = $result;
    $this->data['fid'] = $this->fid;

    // cache the results
    // Cache the results.
    $cache = [
      'files' => $this->files,
      'data' => $this->data,
    ];
    Drupal::cache()->set($cid, $cache, -1,['filebrowser:node:' . $this->node->id()]);
    Drupal::cache()
      ->set($cid, $cache, -1,['filebrowser:node:' . $this->node->id()]);
    return $this;
  }


  /**
   * @return mixed
   */
  protected function processServerFileList() {
    /** @var /Drupal/filebrowser/File/DisplayFile $result_file */

    $stats = ['folders_count' => 0, 'files_count' => 0, 'total_size' => 0];
    $encoding = $this->node->filebrowser->encoding;
    $encoding = $this->filebrowser->encoding;

    // get the DB_contents for this nid
    // Get the DB_contents for this nid
    // first time after node creation $db_content = NULL; there is nothing in the DB
    // If there is content it will return a filename as key, with next indexes:
    // array ('nid' => '1', 'fid' => '3', 'root' => '/', 'path' => '/',)

    $db_content = $this->storage->loadRecordsFromRoot($this->node->id(), $this->relativePath);
    // debug($db_content, 'DB CONTENT');
    // Iterate over file list from the server
    // Iterate over file list from the server.
    if (!is_null($this->serverFileList)) {
      foreach ($this->serverFileList as $key => $fs_file) {

        // Build file relative path
        // Build file relative path.
        $file_relative_path = $this->buildFileRelativePath($fs_file->filename, $encoding);

        // Build database file record if it doesn't exist
        // Build database file record if it doesn't exist.
        if (!isset($db_content[$file_relative_path])) {
          $db_content[$file_relative_path] = [
            'exists' => true,
            'exists' => TRUE,
            'nid' => $this->node->id(),
            'root' => $this->relativePath,
            'path' => $file_relative_path,
@@ -219,7 +228,7 @@ class DisplayFileList extends ControllerBase {
            'file_data' => $fs_file,
          ];
        }
        $db_content[$file_relative_path]['exists'] = true;
        $db_content[$file_relative_path]['exists'] = TRUE;
        $db_content[$file_relative_path]['display_name'] = $fs_file->filename;
        $result_file = new DisplayFile($this->node->id());
        $result_file->fileSetData($file_relative_path, $fs_file, $stats, $db_content[$file_relative_path], $this->fsRoot);
@@ -228,20 +237,20 @@ class DisplayFileList extends ControllerBase {
    }

    // The abstracted filesystem does not provide . and .. files. Therefore
    // we will create them manually
    // we will create them manually.
    if ($this->isSubDir) {
      $subDir = new DisplayFile($this->node->id());
      // Create the .. file data
      // Create the .. file data.
      $result_list['..'] = $subDir->createSubdir($this->relativePath);

      // Create the . file data
      // Create the . file data.
      $file = new DisplayFile($this->node->id());
      $result_list['.'] = $file->createUpDir($this->relativePath);

      // Set DB content for Up-directory. In this case the '/' folder
      // Set DB content for Up-directory. In this case the '/' folder.
      $this->createUpDirContent($db_content['/']);

      //set DB record for current directory (. file)
      // Set DB record for current directory (. file)
      if (!isset($db_content[$this->relativePath])) {
        $db_content[$this->relativePath] = [
          'exists' => TRUE,
@@ -250,12 +259,12 @@ class DisplayFileList extends ControllerBase {
          'path' => $this->relativePath,
        ];
      }
      $db_content[$this->relativePath]['exists'] = true;
      $db_content[$this->relativePath]['exists'] = TRUE;
      $db_content[$this->relativePath]['display_name'] = '.';

    }
    else {
      // not a sub dir so we only set the . file and / DB data
      // not a sub dir so we only set the . file and / DB data.
      if (!isset($db_content['/'])) {
        $db_content['/'] = [
          'nid' => $this->node->id(),
@@ -263,15 +272,15 @@ class DisplayFileList extends ControllerBase {
          'path' => '/',
        ];
      }
      $db_content['/']['exists'] = true;
      $db_content['/']['exists'] = TRUE;
      $db_content['/']['display_name'] = '.';

      // changes to the File System Array
      // changes to the File System Array.
      $result_file = new DisplayFile($this->node->id());
      $result_list['.'] = $result_file->createUpDir($this->relativePath);
    }
    // debug($db_content, 'END DB CONTENT');
    // Set global folder properties
    // Set global folder properties.
    $this->data['stats'] = $this->buildStatistics($result_list);
    $this->data['relative_path'] = $this->relativePath;
    $this->dbSync($db_content, $result_list, $this->data);
@@ -291,7 +300,7 @@ class DisplayFileList extends ControllerBase {
   * @param integer $subdir_fid
   */

  protected function dbSync(&$db_content, &$files, $subdir_fid = null) {
  protected function dbSync(&$db_content, &$files, $subdir_fid = NULL) {
    /** @var DisplayFile $files [$key]  */
    $to_delete = [];
    // Build the fragment to be used with folders.
@@ -314,7 +323,7 @@ class DisplayFileList extends ControllerBase {
        $files[$key]->link = $link->toRenderable();
        $files[$key]->href = $link->getUrl();

        // fire an event so modules can create metadata for this file.
        // Fire an event so modules can create metadata for this file.
        /** @var MetadataEvent $event */
        $dispatcher = Drupal::service('event_dispatcher');
        $e = new MetadataEvent($this->node->id(), $record['fid'], $files[$key], $subdir_fid, $this->filebrowser->visibleColumns);
@@ -322,22 +331,23 @@ class DisplayFileList extends ControllerBase {
      }
    }

    // A quick way to drip obsolete records
    // A quick way to drip obsolete records.
    if (count($to_delete)) {
      $this->storage->deleteFileRecords($to_delete);
    }
  }

  /** Creates links for the file list
  /**
   * Creates links for the file list.
   * @param DisplayFile $file
   * @param int $fid
   * @param string $fragment
   *
   *   for file: 'http://drupal.dev/filebrowser/download/4'
   *   for folder: 'http://drupal.dev/node/1?fid=23#fragment
   * @return Link
   * @return \Drupal\Core\Link
   */
  protected function makeLink(DisplayFile $file, $fid = null, $fragment = null) {
  protected function makeLink(DisplayFile $file, $fid = NULL, $fragment = NULL) {
    $options = ['query' => ['fid' => $fid]];
    if (isset($fragment)) {
      $options['fragment'] = $fragment;
@@ -351,8 +361,24 @@ class DisplayFileList extends ControllerBase {
      return Link::createFromRoute($name, 'entity.node.canonical', ['node' => $this->node->id()], $options);
    }
    else {
      return Link::createFromRoute($name, 'filebrowser.page_download',['fid' => $fid]);
      $settings = $this->filebrowser;
      if ($settings->downloadManager == 'server') {
        $file_uri = $this->filebrowser->folderPath . $file->relativePath;
        $stream_wrapper = \Drupal::service('stream_wrapper_manager')
          ->getViaUri($file_uri);
        $f_external_url = $stream_wrapper->getExternalUrl();
        $external_host = $settings->externalHost;
        if (!empty($external_host)) {
          $host = \Drupal::request()->getSchemeAndHttpHost();
          $f_external_url = str_replace($host, $external_host, $f_external_url);
        }
        $f_external_link = Link::fromTextAndUrl($name, Url::fromUri($f_external_url));
        if (isset($f_external_link)) {
          return $f_external_link;
        }
      }
    }
    return Link::createFromRoute($name, 'filebrowser.page_download', ['fid' => $fid]);
  }

  /**
@@ -361,14 +387,25 @@ class DisplayFileList extends ControllerBase {
   * @param \Drupal\filebrowser\File\DisplayFile $file
   * @param null|int $fid
   */
  protected function makeAnchor(DisplayFile $file, $fid = null) {
  protected function makeAnchor(DisplayFile $file, $fid = NULL) {
  }

  /**
   * @param $fs_filename
   * @param $encoding
   *
   * @return string
   */
  protected function buildFileRelativePath($fs_filename, $encoding) {
    $filename = $this->validator->encodingToFs($encoding, $fs_filename);
    return $this->relativePath . ($this->relativePath != '/' ? '/' : '') . $filename;
  }

  /**
   * @param $array
   *
   * @return void
   */
  protected function createUpDirContent(&$array){
    $parent_path = $this->parentFolder();
    $content = $this->storage->loadRecordFromPath($this->node->id(), $parent_path);
@@ -378,12 +415,16 @@ class DisplayFileList extends ControllerBase {
      }
    }
    else {
      Drupal::messenger()->addError($this->t('No content in method LoadRecordFromPath'));
      Drupal::messenger()
        ->addError($this->t('No content in method LoadRecordFromPath'));
    }
    $array['exists'] = true;
    $array['exists'] = TRUE;
    $array['display_name'] = '..';
  }

  /**
   * @return string
   */
  protected function parentFolder() {
    $array = explode('/', $this->relativePath);
    if (count($array) < 3) {
@@ -395,9 +436,15 @@ class DisplayFileList extends ControllerBase {
    }
  }

  /**
   * @param $list
   *
   * @return array
   */
  protected function buildStatistics($list) {
    //debug(array_keys($list));
    $files = 0; $folders = 0; $total_size = 0;
    $files = 0;
    $folders = 0;
    $total_size = 0;
    foreach($list as $key => $item) {
      if (in_array($key, ['.', '..'])) {
      }
@@ -419,3 +466,4 @@ class DisplayFileList extends ControllerBase {
  }

}
Loading