Completed
Push — master ( 27b20f...cb95fb )
by greg
49s
created

image.js ➔ ... ➔ ???   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 27
rs 8.8571
1
import execPromise from 'child-process-promise'
2
import mkdirp from 'mkdirp'
3
import fse from 'fs-extra'
4
import limax from 'limax'
5
import Jimp from 'jimp'
6
import path from 'path'
7
import {Promise} from 'bluebird'
8
9
import {
10
  abeExtend,
11
  coreUtils,
12
  cmsData,
13
  config
14
} from '../../'
15
16
export function cropAndSaveFile(imageSize, file, newFile) {
17
  var p = new Promise((resolve) => {
18
    Jimp.read(file).then(function (lenna) {
19
      lenna.crop(0, 0, parseInt(imageSize[0]), parseInt(imageSize[1])).write(newFile)
20
    }).catch(function (err) {
21
      console.error(err)
22
    })
23
    resolve()
24
  })
25
  return p
26
}
27
28
export function smartCropAndSaveFile(imageSize, file, newFile) {
29
  var cmd = `node node_modules/smartcrop-cli/smartcrop-cli.js --width ${parseInt(imageSize[0])} --height ${parseInt(imageSize[1])} ${file} ${newFile}`
30
  var p = execPromise.exec(cmd)
31
  return p
32
}
33
34
export function cropAndSaveFiles(images, file, resp) {
35
  var length = images.length
36
  var cropedImage = 0
37
  resp.thumbs = []
38
  var p = new Promise((resolve) => {
39
    for (var i = 0; i < length; i++) {
40
      var image = images[i]
41
      var ext = path.extname(file)
42
      var newFile = file.replace(ext, `_${images[i]}${ext}`)
43
      resp.thumbs.push({
44
        name: newFile.replace(path.join(config.root, config.publish.url), ''),
45
        size: image
46
      })
47
      smartCropAndSaveFile(image.split('x'), file, newFile)
48
        .then(function (result) {
49
          if(result.stderr) {
50
            cropAndSaveFile(image.split('x'), file, newFile).then(function () {
0 ignored issues
show
Bug introduced by
The variable image is changed as part of the for loop for example by images.i on line 40. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable newFile is changed as part of the for loop for example by file.replace(ext, `_${images.i}${ext}`) on line 42. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
51
              if(++cropedImage === length) {
52
                resolve(resp)
53
              }
54
            })
55
          }
56
          else if(++cropedImage === length) {
57
            resolve(resp)
58
          }
59
        })
60
        .catch(function (err) {
61
          console.log(err)
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
62
        })
63
    }
64
  })
65
66
  return p
67
}
68
69
export function generateThumbnail(file) {
70
  var ext = path.extname(file).toLowerCase()
71
  var thumbFileName = file.replace(ext, `_thumb${ext}`)
72
  var thumbFileNameRelative = thumbFileName.replace(path.join(config.root, config.publish.url), '')
73
  var p = new Promise((resolve) => {
74
    var cropThumb = smartCropAndSaveFile([250, 250], file, thumbFileName)
75
    cropThumb.then(function (result) {
76
      var stderr = result.stderr
77
      if(thumbsList != null) {
78
        thumbsList.push({
79
          originalFile: file.replace(path.join(config.root, config.publish.url), ''),
80
          thumbFile: thumbFileNameRelative
81
        })
82
      }
83
      if(stderr) {
84
        cropAndSaveFile([250, 250], file, thumbFileName).then(function () {
85
          resolve({thumb: thumbFileNameRelative})
86
        })
87
      }
88
      else resolve({thumb: thumbFileNameRelative})
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
89
    })
90
  })
91
92
  return p
93
}
94
95
export function saveFile(req) {
96
  var p = new Promise((resolve) => {
97
    var folderFilePath = createMediaFolder(req)
98
    var resp = {success: 1}
99
    var filePath
100
    req.pipe(req.busboy)
101
    req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
102
      var ext = path.extname(filename).toLowerCase()
103
      var slug = createMediaSlug(filename, ext)
104
      var hasSentHeader = false
105
      
106
      filePath = path.join(folderFilePath, slug)
107
      resp['filePath'] = path.join('/' + config.upload.image, slug)
108
109
      var returnErr = function (msg) {
110
        hasSentHeader = true
111
        file.resume()
112
        resolve({error: 1, response: msg})
113
      }
114
115
      file.on('limit', function() {
116
        returnErr('file is too big')
117
      })
118
119
      var isValid = isValidMedia(mimetype, ext)
120
      if(isValid.error) returnErr(isValid.error)
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
121
122
      var fstream = fse.createWriteStream(filePath)
123
      fstream.on('finish', function() {
124
        if(hasSentHeader) return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
125
        if(/\.(jpg|png|gif|svg)/.test(filePath)) resp = abeExtend.hooks.instance.trigger('afterSaveImage', resp, req)
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
126
127
        var thumbPromise = generateThumbnail(filePath)
128
        thumbPromise.then(function (thumbResp) {
129
          resp.thumbnail = thumbResp.thumb
130
          if(req.query.input.indexOf('data-size') > -1){
131
            var thumbsSizes = cmsData.regex.getAttr(req.query.input, 'data-size').split(',')
132
            cropAndSaveFiles(thumbsSizes, filePath, resp).then(function (resp) {
133
              resolve(resp)
134
            })
135
          }
136
          else resolve(resp)
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
137
        })
138
      })
139
      file.pipe(fstream)
140
    })
141
  })
142
143
  return p
144
}
145
146
export function isValidMedia(mimetype, ext) {
147
  var allowedExtensions = ['.gif', '.jpg', '.jpeg', '.png', '.svg', '.mp4']
148
  var allowedMimetype = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'video/mp4']
149
  var error = false
150
  if (allowedMimetype.indexOf(mimetype) < 0) error = 'unauthorized file'
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
151
  else if (allowedExtensions.indexOf(ext) < 0) error = 'not a valid asset'
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
152
153
  return {error: error}
154
}
155
156
export function createMediaSlug(filename, ext) {
157
  var filenameNoExt = path.basename(filename, ext)
158
  return limax(filenameNoExt, {separateNumbers: false}) + '-' + coreUtils.random.generateUniqueIdentifier(2) + ext
159
}
160
161
export function createMediaFolder(req) {
162
  var folderWebPath = '/' + config.upload.image
163
  folderWebPath = abeExtend.hooks.instance.trigger('beforeSaveImage', folderWebPath, req)
164
  var folderFilePath = path.join(config.root, config.publish.url, folderWebPath)
165
  mkdirp.sync(folderFilePath)
166
167
  return folderFilePath
168
}
169
170
var thumbsList
171
172
export function getThumbsList() {
173
  if(thumbsList != null) return thumbsList
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
174
  thumbsList = []
175
  var pathToThumbs = path.join(config.root, config.publish.url, config.upload.image)
176
  var files = coreUtils.file.getFilesSync(pathToThumbs, true)
177
  Array.prototype.forEach.call(files, (pathFile) => {
178
    pathFile = pathFile.replace(path.join(config.root, config.publish.url), '')
179
    if(pathFile.indexOf('_thumb.') > -1){
180
      thumbsList.push({
181
        originalFile: pathFile.replace('_thumb.', '.'),
182
        thumbFile: pathFile
183
      })
184
    }
185
  })
186
187
  return thumbsList
188
}
189
190
export function getAssociatedImageFileFromThumb(name) {
191
  var rexMatchImageName = /_(thumb|\d+x\d+)/
192
  name = path.join(path.sep, name)
193
  var originalName = path.join(path.sep, name.replace(rexMatchImageName, ''))
194
  var imageList = {
195
    thumbFile: name,
196
    originalFile: originalName,
197
    thumbs: []
198
  }
199
  var pathThumb = name.split('/')
200
  pathThumb.pop()
201
  pathThumb = path.join(config.root, config.publish.url, pathThumb.join('/'))
202
203
  var files = coreUtils.file.getFilesSync(pathThumb, true)
204
  Array.prototype.forEach.call(files, (pathFile) => {
205
    pathFile = pathFile.replace(path.join(config.root, config.publish.url), '')
206
    if(pathFile !== originalName && pathFile !== name && pathFile.replace(rexMatchImageName, '') === originalName){
207
      imageList.thumbs.push(pathFile)
208
    }
209
  })
210
211
  return imageList
212
}
213