UNPKG

sheercms

Version:

Sheer Cliff CMS is a simple and powerful content management system (CMS) for Node JS.

413 lines (375 loc) 13.6 kB
/* The media plugin controls how media items (images, files, etc) are saved and retrieved. For example, there could be a plugin for the file system or one for Amazon S3. */ var logger = require('../../lib/logger'); var S = require('string'); var path_mod = require('path'); var fs = require('fs'); var cms = require('../../index'); var utils = require('../../lib/utilities'); var async = require("async"); var config = require("../../lib/config"); var gm = require('gm'); module.exports.init = function(server, done) { done(); }; /* callback: ( err, result {path, url} ) */ module.exports.writeMedia = function(item, group, path, size, callback) { try { //make sure the path has the root in it var root = cms.getRoot(); if (path.indexOf(root) < 0) path = path_mod.join(root, path); var contentId = item.contentId.toString(); //get the file extension var ext = path_mod.extname(path); if (ext) ext = ext.toLowerCase(); //figure out the file name var dirs = []; //top level media folder dirs.push(path_mod.join(root, 'media')); //second level media folder var type = cms.api.contentTypes.getContentTypeSync(item.typeId); var typeDir = type.mediaType || 'files'; typeDir = makePlural(typeDir.toLowerCase()); dirs.push(path_mod.join(root, 'media', typeDir)); //letter directory - last letter of the contentId var letter = contentId.substr(contentId.length - 1, 1).toLowerCase(); dirs.push(path_mod.join(dirs[1], letter)); var url = '/' + path_mod.join('media', typeDir, contentId + ext); ensureDirectories(dirs, function(err) { try { if (err) { if (callback) callback(err); } else { var newPath = path_mod.join(dirs[2], contentId + ext); var relPath = '/' + path_mod.join('media', typeDir, letter, contentId + ext); if (type.mediaType === "Image") { logger.info("Resizing and renaming '" + path + "' to '" + newPath + "'"); //get the media settings for resizing var mediaSettings = group.mediaSettings || {}; var imageMaxWidth = mediaSettings.imageWidth || config.settings.image_max_width; var imageMaxHeight = mediaSettings.imageHeight || config.settings.image_max_height; var imageQuality = mediaSettings.imageQuality || 100; var resizeMode = mediaSettings.resizeMode || 'none'; resizeImageAndMove(path, newPath, imageMaxWidth, imageMaxHeight, imageQuality, resizeMode, function(err) { if (err) { logger.error(err); if (callback) callback(err); } else { try { //create the thumbnail var tPath = path_mod.join(dirs[2], contentId + '-thumb' + ext); createThumbnail(newPath, tPath, false, function (err) { if (err) { if (callback) callback(err); } else { if (callback) callback(null, {path: relPath, url: url}); } }); } catch (e) { logger.error(e); if (callback) callback(e); } } }); } else if (item.branch === 'media') { fs.rename(path, newPath, function (err) { if (err) { logger.error(err); if (callback) callback(err); } else { if (callback) callback(null, {path: relPath, url: url}); } }); } } } catch(e) { logger.error(e); if (callback) callback(e); } }); } catch(e) { logger.error(e); if (callback) callback(e); } }; /* callback: (err) */ function resizeImageAndMove(path, newPath, maxWidth, maxHeight, quality, mode, callback) { //get the image size gm(path).size(function (err, value) { try { if (err) { callback(err); } else { var resized = false; //see if we need to resize the image if (mode === 'max' && (value.width > maxWidth || value.height > maxHeight)) { //resize down to the max width & height gm(path) .resize(maxWidth, maxHeight) .compress('JPEG') .quality(quality) .write(newPath, function (err) { callback(err); }); } else if (mode === 'crop' && (value.width > maxWidth || value.height > maxHeight)) { //crop to max gm(path) .resize(maxWidth, maxHeight, '^') .gravity('Center') .crop(maxWidth, maxHeight) .compress('JPEG') .quality(quality) .write(newPath, function (err) { callback(err); }); } else if (mode === 'stretch' && (value.width != maxWidth || value.height != maxHeight)) { //force resize to exact size gm(path) .resize(maxWidth, maxHeight, "!") .compress('JPEG') .quality(quality) .write(newPath, function (err) { callback(err); }); } else { if (quality == 100) { //don't change the image, just move it fs.rename(path, newPath, function (err) { callback(err); }); } else { //save with new quality gm(path) .compress('JPEG') .quality(quality) .write(newPath, function (err) { callback(err); }); } } } } catch(e) { logger.error(e); if (callback) callback(e); } }); } function makePlural(s) { if (s === 'image') return 'images'; else if (s === 'file') return 'files'; else if (s === 'video') return 'videos'; else if (s === 'audio') return 'audio'; else return s; } /* callback: (err) */ function createThumbnail(path, tPath, bDelete, callback) { try { gm(path) .resize(config.settings.thumbnail_width, config.settings.thumbnail_height) .write(tPath, function (err) { try { if (err) { logger.error(err); if (callback) callback(err); } else { if (bDelete == true) { //now delete the temp image fs.unlink(path, function (err) { if (err) { logger.error(err); if (callback) callback(err); } else { if (callback) callback(null); } }); } else { if (callback) callback(null); } } } catch (e) { logger.error(e); if (callback) callback(e); } }); } catch(e) { logger.error(e); if (callback) callback(e); } } /* callback: (err) */ module.exports.deleteMedia = function(item, callback) { try { //get the file path var path = item.filePath; if (!path || path.length == 0) { if (callback) callback(null); return; } path = path_mod.join(cms.getRoot(), path); var arr = []; arr.push(path); var type = cms.api.contentTypes.getContentTypeSync(item.typeId); if (!type) { var e = new Error('Content type not found: ' + item.typeId); logger.error(e); if (callback) callback(e); return; } if (type.mediaType == "Image") { //change the path to the thumbnail path var ext = path_mod.extname(path); if (ext && ext.length > 0) arr.push(path.replace(ext, "-thumb" + ext)); } async.each(arr, function (file, done) { logger.info("Deleting file: " + file); fs.exists(file, function (exists) { try { if (exists) { fs.unlink(file, function (err) { if (err) { logger.error(err); done(err); } else done(); }); } else done(); } catch(e) { logger.error(e); done(e); } }); }, function (err) { if (callback) callback(err); }); } catch(e) { logger.error(e); if (callback) callback(e); } }; module.exports.renderMedia = function(req, res, item) { try { //get the file path var path = item.filePath; if (!path || path.length == 0) throw new Error("File path not found for media item: " + item.contentId); path = path_mod.join(cms.getRoot(), path); var type = cms.api.contentTypes.getContentTypeSync(item.typeId); if (!type) { var e = new Error('Content type not found: ' + item.typeId); logger.error(e); if (callback) callback(e); return; } if (type.mediaType === "Image" && req.query.thumb) { //change the path to the thumbnail path var ext = path_mod.extname(path); if (ext && ext.length > 0) path = path.replace(ext, "-thumb" + ext); } var age = 0; if (type.mediaType === "Image" && config.settings.image_max_days) age = parseInt(config.settings.image_max_days) * 1440000; if (type.mediaType === 'Image') { var mime = 'image/'; if (item.filePath.indexOf('.gif') > 0) mime += 'gif'; else if (item.filePath.indexOf('.png') > 0) mime += 'png'; else mime += 'jpg'; res.setHeader('content-type',mime); } res.sendfile(path, {maxAge: age}); } catch(e) { logger.error(e); res.send(500, 'Error rendering the media item for this URL.'); } }; /* callback: (err, data) */ module.exports.readMedia = function(item, callback) { if (callback) { try { //get the file path var path = item.filePath; if (!path || path.length == 0) throw new Error("File path not found for media item: " + item.contentId); path = path_mod.join(cms.getRoot(), path); fs.readFile(path, callback); } catch (e) { logger.error(e); res.send(500, 'Error rendering the media item for this URL.'); } } }; /* callback: (err) */ function ensureDirectories(dirs, callback) { try { async.eachSeries(dirs, function (dir, done) { logger.info("Ensuring directory: " + dir); utils.ensureDirectoryExists(dir, function (err, created) { done(err); }); }, function (err) { if (err) { logger.error(err); if (callback) callback(err); } else { if (callback) callback(null); } }); } catch(e) { logger.error(e); if (callback) callback(e); } };