Skip to content

Instantly share code, notes, and snippets.

@greenlikeorange
Created July 3, 2015 08:16
Show Gist options
  • Save greenlikeorange/2ada4f27c96ce6c2397f to your computer and use it in GitHub Desktop.
Save greenlikeorange/2ada4f27c96ce6c2397f to your computer and use it in GitHub Desktop.
Reusable Picture Model and Picture Adapter
var Picture = require("../models/picture").Picture;
var PictureSchema = require("../models/picture").PictureSchema;
var fs = require('fs');
var mongoose = require("mongoose");
module.exports = function(modelname, MainSchema){
MainSchema.virtual('mainPicture').get(function(){
if(this.mainPicture)
return this.picturesSorted()[0];
else
return this.picturesSorted();
});
MainSchema.virtual('otherPictures').get(function() {
if (this.mainPicture) {
return this.picturesSorted().slice(1);
} else {
return this.picturesSorted();
}
});
MainSchema.virtual('mainFullPicture').get(function() {
if (this.mainPicture) {
return this.mainPicture.webPath('full');
} else {
return null;
}
});
MainSchema.virtual('mainLargePicture').get(function() {
if (this.mainPicture) {
return this.mainPicture.webPath('large');
} else {
return null;
}
});
MainSchema.virtual('mainMediumPicture').get(function() {
if (this.mainPicture) {
return this.mainPicture.webPath('medium');
} else {
return null;
}
});
MainSchema.virtual('mainSmallPicture').get(function() {
if (this.mainPicture) {
return this.mainPicture.webPath('small');
} else {
return null;
}
});
var Model = mongoose.model(modelname, MainSchema);
Model.prototype.addPicture = function(picture) {
this.createDirs();
var newLength = this.pictures.push(picture);
return this.pictures[newLength - 1];
};
Model.prototype.removePicture = function() {
//
};
Model.prototype.picturesSorted = function() {
if(!this.pictures)
return [];
else
return this.pictures.sort(PictureSchema.sortPictures);
};
Model.prototype.fsDirPath = function() {
return "" + __dirname + "/../../public" + this.webDirPath();
};
Model.prototype.webDirPath = function() {
return "/imgs/uploads/" + this._id;
};
Model.prototype.createDirs = function() {
if (!fs.existsSync(this.fsDirPath())) {
return fs.mkdirSync(this.fsDirPath());
}
};
Model.prototype.postJSON = function(){
var obj = this.toObject();
var pictures = [];
var picturesSorted = this.picturesSorted();
var paths = ['full', 'large', 'medium', 'small'];
for(var i = 0; i < picturesSorted.length; i++){
var _pic = picturesSorted[i];
var variations = [];
for (var j = 0; j < paths.length; j++) {
variations.push({
path: _pic.webPath(paths[j]),
type: paths[j],
});
}
try{
pictures = variations;
}catch (err){
console.error(err);
}
}
obj.pictures = pictures;
return obj;
};
return Model;
};
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var fs = require("fs");
var gm = require("gm");
var batch = require('batchflow');
var PictureSchema = new Schema({
type: { type: String },
index: { type: Number, require: true, min: 0 }
}, { strict: true });
PictureSchema.virtual('fullPath').get(function(){
return this.webPath('full');
});
PictureSchema.virtual('largePath').get(function(){
return this.webPath('large');
});
PictureSchema.virtual('mediumPath').get(function(){
return this.webPath('medium');
});
PictureSchema.virtual('thumbnailPath').get(function(){
return this.webPath('small');
});
PictureSchema.pre("save", function(next){
if(this.isModified("picture"))
this.generateImages(next);
else
next();
});
// Remove images when picture deleted (for some reason has to be in pre callback)
PictureSchema.pre('remove', function(next){
try {
fs.unlinkSync(this.fsPath());
fs.unlinkSync(this.fsPath('small'));
fs.unlinkSync(this.fsPath('medium'));
fs.unlinkSync(this.fsPath('large'));
// fs.rmdirSync(this.fsDirPath());
} catch(err) {
console.error(err);
}
next();
});
PictureSchema.statics.typeFromFilename = function(filename){
var split = filename.split('.');
return split[split.length - 1];
};
PictureSchema.statics.sortPictures = function(a, b){
if( a.index < b.index )
return -1;
else if( a.index > b.index )
return 1;
else
return 0;
};
// large: 1440 x 960, medium: 200 x 132, small: 128 x 84
PictureSchema.methods.generateImages = function(callback){
var that = this;
var sizes = [
{ path: this.fsPath('large'), width: 960, height: 960 },
{ path: this.fsPath('medium'), width: 250, height: 250 },
{ path: this.fsPath('small'), width: 128, height: 128 }
];
var work = batch(sizes).parallel().each( function(i, size, done){
var igm = new gm.subClass({ imageMagick: true })
var sizeAndWidth = size.width && size.height;
var resizeOption = sizeAndWidth ? '^' : null;
var resizer = igm(that.fullSizeFsPath())
.resize(size.width, size.height, resizeOption);
if( sizeAndWidth ){
resizer.quality(88);
resizer.gravity('Center');
resizer.crop(size.width, size.height);
}
resizer.write(size.path, function(err){
if(err)
done(err);
else
done();
});
});
work.error(function(err){
callback(err);
});
work.end( function(){
callback(null);
});
};
PictureSchema.methods.fullSizeFsPath = function(){
return this.parent().fsDirPath()+ "/" +this._id+ "." +this.type;
};
PictureSchema.methods.fullSizePath = function(){
return this.parent().webDirPath()+ "/" +this._id+ "." +this.type;
};
PictureSchema.methods.fsPath = function(size){
if(size)
return this.parent().fsDirPath()+ "/" +this._id+ "-" +size+ "." + this.type;
else
return this.parent().fsDirPath()+ "/" +this._id+ "." +this.type;
};
PictureSchema.methods.fsDirPath = function(){
};
PictureSchema.methods.webPath = function(size){
if( size == 'full' )
return this.fullSizePath();
else
return this.parent().webDirPath()+ "/" +this._id+ "-" +size+ "." + this.type;
};
var Picture = mongoose.model('Picture', PictureSchema);
exports.Picture = Picture;
exports.PictureSchema = PictureSchema;
var UserHandler = {};
//...... Some user handler stuff...
UserHandler.recievePictures = function(object, data, callback){
var _files = data.files && data.files.pictures;
var _file = _files;
if(_files){
if(_files.length) _file = _files[0];
var _type = _file.originalFilename.split(".").slice(-1);
var _index = 0;
if(object.pictures[0])
object.pictures[0].remove();
var picture = new Picture({ type: _type, index: _index });
var pictures = object.addPicture(picture);
temp2path(_file, pictures.fullSizeFsPath());
pictures.generateImages(function(err){
if(err)
callback(err);
object.save(callback);
});
} else {
object.save(callback);
}
};
// Router
rotuer.post("/users/:id/pictures", auth, multipathMiddleware,function(req, res, next){
var data = {files: req.files};
// It come from auth middleware
var user = req.user;
UserHandler.recievePictures(user, data, function(err, user){
if(err)
return next(err);
res.send({data: user});
})
});
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
// User Type
type: { type: String, required: true },
createdAt: { type: Date, default: Date.now, required: true },
// Informations
name: { type: String, trim: true, required: true },
email: { type: String, required: true, lowercase: true, unique: true, trim: true, match: /^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/ },
pictures: [PictureSchema]
});
var pictureAdapter = require("../lib/pictureAdapter");
var User = pictureAdapter('User', UserSchema);
module.exports = User;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment