0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Created Media Importer Handler package

refs https://github.com/TryGhost/Toolbox/issues/523

- We need media file imports. Media handler is one of the pre-processing parts that need to be done during the import process
- Media import handler is handling import files with following extensions: ".mp4",".webm", ".ogv", ".mp3", ".wav", ".ogg", ".m4a"
- The implementation is largely a copy-paste with class syntax adjustments from the "/core/server/data/importer/handles/image.js" module
- There are a lot of code similarities between media and image import handlers. The new "ImporterMedia" class could serve as a generic base class for file-storage-related imports
This commit is contained in:
Naz 2023-03-01 15:40:22 +08:00
parent b768e710f1
commit 9347e996f8
No known key found for this signature in database
10 changed files with 180 additions and 11 deletions

View file

@ -0,0 +1 @@
module.exports = require('./lib/ImporterMediaHandler');

View file

@ -0,0 +1,65 @@
const _ = require('lodash');
const path = require('path');
class ImporterMediaHandler {
/**
*
* @param {Object} deps dependencies
* @param {Object} deps.storage storage adapter instance
* @param {Object} deps.config config instance
* @param {object} deps.urlUtils urlUtils instance
*/
constructor(deps) {
this.storage = deps.storage;
this.config = deps.config;
this.urlUtils = deps.urlUtils;
}
type = 'media';
get extensions() {
return this.config.get('uploads').media.extensions;
}
get contentTypes() {
return this.config.get('uploads').media.contentTypes;
}
directories = ['media', 'content'];
async loadFile(files, baseDir) {
const baseDirRegex = baseDir ? new RegExp('^' + baseDir + '/') : new RegExp('');
const mediaFolderRegexes = _.map(this.storage.staticFileURLPrefix.split('/'), function (dir) {
return new RegExp('^' + dir + '/');
});
// normalize the directory structure
const mediaContentPath = this.config.getContentPath('media');
files = _.map(files, function (file) {
const noBaseDir = file.name.replace(baseDirRegex, '');
let noGhostDirs = noBaseDir;
_.each(mediaFolderRegexes, function (regex) {
noGhostDirs = noGhostDirs.replace(regex, '');
});
file.originalPath = noBaseDir;
file.name = noGhostDirs;
file.targetDir = path.join(mediaContentPath, path.dirname(noGhostDirs));
return file;
});
const self = this;
return Promise.all(files.map(function (image) {
return self.storage.getUniqueFileName(image, image.targetDir).then(function (targetFilename) {
image.newPath = self.urlUtils.urlJoin('/', self.urlUtils.getSubdir(), self.storage.staticFileURLPrefix,
path.relative(self.config.getContentPath('media'), targetFilename));
return image;
});
}));
}
}
module.exports = ImporterMediaHandler;

View file

@ -1,7 +1,7 @@
{
"name": "@tryghost/importer-media",
"name": "@tryghost/importer-handler-media",
"version": "0.0.0",
"repository": "https://github.com/TryGhost/Ghost/tree/main/packages/importer-media",
"repository": "https://github.com/TryGhost/Ghost/tree/main/packages/importer-handler-media",
"author": "Ghost Foundation",
"private": true,
"main": "index.js",

View file

@ -0,0 +1,112 @@
const assert = require('assert');
const sinon = require('sinon');
const ImporterMedia = require('../index');
describe('ImporterMediaHandler', function () {
it('creates an instance', function () {
const mediaImporter = new ImporterMedia({
storage: {},
config: {},
urlUtils: {}
});
assert.ok(mediaImporter);
assert.equal(mediaImporter.type, 'media');
});
it('returns configured extensions', function () {
const mediaImporter = new ImporterMedia({
storage: {},
config: {
get: () => ({
media: {
extensions: ['mp4']
}
})
},
urlUtils: {}
});
assert.deepEqual(mediaImporter.extensions, ['mp4']);
});
it('returns configured contentTypes', function () {
const mediaImporter = new ImporterMedia({
storage: {},
config: {
get: () => ({
media: {
contentTypes: ['video/mp4']
}
})
},
urlUtils: {}
});
assert.deepEqual(mediaImporter.contentTypes, ['video/mp4']);
});
// @NOTE: below tests need more work, they are just covering the basics
// the cases are based on a fact that the implementation was a copy
// from the image importer and the tests were adapted to the media importer
describe('loadFile', function () {
it('loads files and decorates them with newPath with subdirectory', async function () {
const mediaImporter = new ImporterMedia({
storage: {
staticFileURLPrefix: 'content/media',
getUniqueFileName: (file, targetDir) => Promise.resolve(targetDir + '/' + file.name)
},
config: {
getContentPath: sinon.stub()
.withArgs('media')
.returns('/var/www/ghost/content/media')
},
urlUtils: {
getSubdir: () => 'blog',
urlJoin: (...args) => args.join('/')
}
});
const files = [{
name: 'content/media/1.mp4'
}];
const subDir = 'blog';
await mediaImporter.loadFile(files, subDir);
assert.equal(files[0].name, '1.mp4');
assert.equal(files[0].originalPath, 'content/media/1.mp4');
assert.equal(files[0].targetDir, '/var/www/ghost/content/media');
assert.equal(files[0].newPath, '//blog/content/media/1.mp4');
});
it('loads files and decorates them with newPath with NO subdirectory', async function () {
const mediaImporter = new ImporterMedia({
storage: {
staticFileURLPrefix: 'content/media',
getUniqueFileName: (file, targetDir) => Promise.resolve(targetDir + '/' + file.name)
},
config: {
getContentPath: sinon.stub()
.withArgs('media')
.returns('/var/www/ghost/content/media')
},
urlUtils: {
getSubdir: () => 'blog',
urlJoin: (...args) => args.join('/')
}
});
const files = [{
name: 'content/media/1.mp4'
}];
await mediaImporter.loadFile(files);
assert.equal(files[0].name, '1.mp4');
assert.equal(files[0].originalPath, 'content/media/1.mp4');
assert.equal(files[0].targetDir, '/var/www/ghost/content/media');
assert.equal(files[0].newPath, '//blog/content/media/1.mp4');
});
});
});

View file

@ -1 +0,0 @@
module.exports = require('./lib/importer-media');

View file

@ -1,8 +0,0 @@
const assert = require('assert');
describe('Hello world', function () {
it('Runs a test', function () {
// TODO: Write me!
assert.ok(require('../index'));
});
});