Get file and folder metadata for media items using a single network call if possible (#5046)
Co-Authored-By: Ben Thomson <ben@abweb.com.au>. Fixes #5045.
This commit is contained in:
parent
71d579b947
commit
40d8bb453e
|
|
@ -595,14 +595,14 @@ class MediaLibrary
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a library item from a path and item type.
|
* Initializes a library item from file metadata and item type.
|
||||||
* @param string $path Specifies the item path relative to the storage disk root.
|
* @param array $item Specifies the file metadata as returned by the storage adapter.
|
||||||
* @param string $itemType Specifies the item type.
|
* @param string $itemType Specifies the item type.
|
||||||
* @return mixed Returns the MediaLibraryItem object or NULL if the item is not visible.
|
* @return mixed Returns the MediaLibraryItem object or NULL if the item is not visible.
|
||||||
*/
|
*/
|
||||||
protected function initLibraryItem($path, $itemType)
|
protected function initLibraryItem($item, $itemType)
|
||||||
{
|
{
|
||||||
$relativePath = $this->getMediaRelativePath($path);
|
$relativePath = $this->getMediaRelativePath($item['path']);
|
||||||
|
|
||||||
if (!$this->isVisible($relativePath)) {
|
if (!$this->isVisible($relativePath)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -612,9 +612,11 @@ class MediaLibrary
|
||||||
* S3 doesn't allow getting the last modified timestamp for folders,
|
* S3 doesn't allow getting the last modified timestamp for folders,
|
||||||
* so this feature is disabled - folders timestamp is always NULL.
|
* so this feature is disabled - folders timestamp is always NULL.
|
||||||
*/
|
*/
|
||||||
$lastModified = $itemType == MediaLibraryItem::TYPE_FILE
|
if ($itemType === MediaLibraryItem::TYPE_FILE) {
|
||||||
? $this->getStorageDisk()->lastModified($path)
|
$lastModified = $item['timestamp'] ?? $this->getStorageDisk()->lastModified($item['path']);
|
||||||
: null;
|
} else {
|
||||||
|
$lastModified = null;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The folder size (number of items) doesn't respect filters. That
|
* The folder size (number of items) doesn't respect filters. That
|
||||||
|
|
@ -622,9 +624,11 @@ class MediaLibrary
|
||||||
* zero items for a folder that contains files not visible with a
|
* zero items for a folder that contains files not visible with a
|
||||||
* currently applied filter. -ab
|
* currently applied filter. -ab
|
||||||
*/
|
*/
|
||||||
$size = $itemType == MediaLibraryItem::TYPE_FILE
|
if ($itemType === MediaLibraryItem::TYPE_FILE) {
|
||||||
? $this->getStorageDisk()->size($path)
|
$size = $item['size'] ?? $this->getStorageDisk()->size($item['path']);
|
||||||
: $this->getFolderItemCount($path);
|
} else {
|
||||||
|
$size = $this->getFolderItemCount($item['path']);
|
||||||
|
}
|
||||||
|
|
||||||
$publicUrl = $this->getPathUrl($relativePath);
|
$publicUrl = $this->getPathUrl($relativePath);
|
||||||
|
|
||||||
|
|
@ -665,17 +669,20 @@ class MediaLibrary
|
||||||
'folders' => []
|
'folders' => []
|
||||||
];
|
];
|
||||||
|
|
||||||
$files = $this->getStorageDisk()->files($fullFolderPath);
|
$contents = $this->getStorageDisk()->listContents($fullFolderPath);
|
||||||
foreach ($files as $file) {
|
|
||||||
if ($libraryItem = $this->initLibraryItem($file, MediaLibraryItem::TYPE_FILE)) {
|
|
||||||
$result['files'][] = $libraryItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$folders = $this->getStorageDisk()->directories($fullFolderPath);
|
foreach ($contents as $content) {
|
||||||
foreach ($folders as $folder) {
|
if ($content['type'] === 'file') {
|
||||||
if ($libraryItem = $this->initLibraryItem($folder, MediaLibraryItem::TYPE_FOLDER)) {
|
$type = MediaLibraryItem::TYPE_FILE;
|
||||||
$result['folders'][] = $libraryItem;
|
$key = 'files';
|
||||||
|
} elseif ($content['type'] === 'dir') {
|
||||||
|
$type = MediaLibraryItem::TYPE_FOLDER;
|
||||||
|
$key = 'folders';
|
||||||
|
}
|
||||||
|
|
||||||
|
$libraryItem = $this->initLibraryItem($content, $type);
|
||||||
|
if (!is_null($libraryItem)) {
|
||||||
|
$result[$key][] = $libraryItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
THIS IS A TEXT DOCUMENT
|
||||||
|
|
@ -4,6 +4,12 @@ use System\Classes\MediaLibrary;
|
||||||
|
|
||||||
class MediaLibraryTest extends TestCase // @codingStandardsIgnoreLine
|
class MediaLibraryTest extends TestCase // @codingStandardsIgnoreLine
|
||||||
{
|
{
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->removeMedia();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public function invalidPathsProvider()
|
public function invalidPathsProvider()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
@ -62,4 +68,63 @@ class MediaLibraryTest extends TestCase // @codingStandardsIgnoreLine
|
||||||
$result = MediaLibrary::validatePath($path);
|
$result = MediaLibrary::validatePath($path);
|
||||||
$this->assertInternalType('string', $result);
|
$this->assertInternalType('string', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testListFolderContents()
|
||||||
|
{
|
||||||
|
$this->setUpStorage();
|
||||||
|
$this->copyMedia();
|
||||||
|
|
||||||
|
$contents = MediaLibrary::instance()->listFolderContents();
|
||||||
|
$this->assertNotEmpty($contents, 'Media library item is not discovered');
|
||||||
|
|
||||||
|
$item = reset($contents);
|
||||||
|
$this->assertAttributeEquals('file', 'type', $item, 'Media library item does not have the right type');
|
||||||
|
$this->assertAttributeEquals('/text.txt', 'path', $item, 'Media library item does not have the right path');
|
||||||
|
$this->assertAttributeNotEmpty('lastModified', $item, 'Media library item last modified is empty');
|
||||||
|
$this->assertAttributeNotEmpty('size', $item, 'Media library item size is empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setUpStorage()
|
||||||
|
{
|
||||||
|
$this->app->useStoragePath(base_path('storage/temp'));
|
||||||
|
|
||||||
|
config(['filesystems.disks.test_local' => [
|
||||||
|
'driver' => 'local',
|
||||||
|
'root' => storage_path('app'),
|
||||||
|
]]);
|
||||||
|
|
||||||
|
config(['cms.storage.media' => [
|
||||||
|
'disk' => 'test_local',
|
||||||
|
'folder' => 'media',
|
||||||
|
'path' => '/storage/app/media',
|
||||||
|
]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function copyMedia()
|
||||||
|
{
|
||||||
|
$mediaPath = storage_path('app/media');
|
||||||
|
|
||||||
|
if (!is_dir($mediaPath)) {
|
||||||
|
mkdir($mediaPath, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (glob(base_path('tests/fixtures/media/*')) as $file) {
|
||||||
|
$path = pathinfo($file);
|
||||||
|
copy($file, $mediaPath . DIRECTORY_SEPARATOR . $path['basename']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeMedia()
|
||||||
|
{
|
||||||
|
if ($this->app->storagePath() !== base_path('storage/temp')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (glob(storage_path('app/media/*')) as $file) {
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
rmdir(storage_path('app/media'));
|
||||||
|
rmdir(storage_path('app'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue