Completed
Pull Request — master (#65)
by
unknown
02:48
created

image.js ➔ generateThumbnail   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 19
rs 9.4285

1 Function

Rating   Name   Duplication   Size   Complexity  
A image.js ➔ ... ➔ ??? 0 12 1
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(stderr) {
78
        cropAndSaveFile([250, 250], file, thumbFileName).then(function () {
79
          resolve({thumb: thumbFileNameRelative})
80
        })
81
      }
82
      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...
83
    })
84
  })
85
86
  return p
87
}
88
89
export function saveFile(req) {
90
  var p = new Promise((resolve) => {
91
    var folderFilePath = createMediaFolder(req)
92
    var resp = {success: 1}
93
    var filePath
94
    req.pipe(req.busboy)
95
    req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
96
      var ext = path.extname(filename).toLowerCase()
97
      var slug = createMediaSlug(filename, ext)
98
      var hasSentHeader = false
99
      
100
      filePath = path.join(folderFilePath, slug)
101
      resp['filePath'] = path.join('/' + config.upload.image, slug)
102
103
      var returnErr = function (msg) {
104
        hasSentHeader = true
105
        file.resume()
106
        resolve({error: 1, response: msg})
107
      }
108
109
      file.on('limit', function() {
110
        returnErr('file is too big')
111
      })
112
113
      var isValid = isValidMedia(mimetype, ext)
114
      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...
115
116
      var fstream = fse.createWriteStream(filePath)
117
      fstream.on('finish', function() {
118
        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...
119
        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...
120
121
        var thumbPromise = generateThumbnail(filePath)
122
        thumbPromise.then(function (thumbResp) {
123
          resp.thumbnail = thumbResp.thumb
124
          if(req.query.input.indexOf('data-size') > -1){
125
            var thumbsSizes = cmsData.regex.getAttr(req.query.input, 'data-size').split(',')
126
            cropAndSaveFiles(thumbsSizes, filePath, resp).then(function (resp) {
127
              resolve(resp)
128
            })
129
          }
130
          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...
131
        })
132
      })
133
      file.pipe(fstream)
134
    })
135
  })
136
137
  return p
138
}
139
140
export function isValidMedia(mimetype, ext) {
141
  var allowedExtensions = ['.gif', '.jpg', '.jpeg', '.png', '.svg', '.mp4']
142
  var allowedMimetype = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'video/mp4']
143
  var error = false
144
  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...
145
  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...
146
147
  return {error: error}
148
}
149
150
export function createMediaSlug(filename, ext) {
151
  var filenameNoExt = path.basename(filename, ext)
152
  return limax(filenameNoExt, {separateNumbers: false}) + '-' + coreUtils.random.generateUniqueIdentifier(2) + ext
153
}
154
155
export function createMediaFolder(req) {
156
  var folderWebPath = '/' + config.upload.image
157
  folderWebPath = abeExtend.hooks.instance.trigger('beforeSaveImage', folderWebPath, req)
158
  var folderFilePath = path.join(config.root, config.publish.url, folderWebPath)
159
  mkdirp.sync(folderFilePath)
160
161
  return folderFilePath
162
}
163
164
export function getThumbsList() {
165
  var thumbsList = []
166
  var pathToThumbs = path.join(config.root, config.publish.url, config.upload.image)
167
  var files = coreUtils.file.getFilesSync(pathToThumbs, true)
168
  Array.prototype.forEach.call(files, (pathFile) => {
169
    pathFile = pathFile.replace(path.join(config.root, config.publish.url), '')
170
    if(pathFile.indexOf('_thumb.') > -1){
171
      thumbsList.push({
172
        originalFile: pathFile.replace('_thumb.', '.'),
173
        thumbFile: pathFile
174
      })
175
    }
176
  })
177
178
  return thumbsList
179
}
180
181
export function getAssociatedImageFileFromThumb(name) {
182
  var rexMatchImageName = /_(thumb|\d+x\d+)/
183
  name = path.join(path.sep, name)
184
  var originalName = path.join(path.sep, name.replace(rexMatchImageName, ''))
185
  var imageList = {
186
    thumbFile: name,
187
    originalFile: originalName,
188
    thumbs: []
189
  }
190
  var pathThumb = name.split('/')
191
  pathThumb.pop()
192
  pathThumb = path.join(config.root, config.publish.url, pathThumb.join('/'))
193
194
  var files = coreUtils.file.getFilesSync(pathThumb, true)
195
  Array.prototype.forEach.call(files, (pathFile) => {
196
    pathFile = pathFile.replace(path.join(config.root, config.publish.url), '')
197
    if(pathFile !== originalName && pathFile !== name && pathFile.replace(rexMatchImageName, '') === originalName){
198
      imageList.thumbs.push(pathFile)
199
    }
200
  })
201
202
  return imageList
203
}
204