Completed
Push — master ( f48291...a65f2c )
by greg
74:59
created

src/cli/cms/data/file.js   B

Complexity

Total Complexity 47
Complexity/F 4.27

Size

Lines of Code 264
Function Count 11

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
wmc 47
c 1
b 0
f 0
nc 1
mnd 5
bc 37
fnc 11
dl 0
loc 264
rs 8.439
bpm 3.3636
cpm 4.2727
noi 6

7 Functions

Rating   Name   Duplication   Size   Complexity  
A file.js ➔ fromUrl 0 56 2
A file.js ➔ getFiles 0 16 1
A file.js ➔ get 0 15 3
A file.js ➔ getFolders 0 13 1
A file.js ➔ getFilesByType 0 19 3
B file.js ➔ getAllWithKeys 0 41 1
F file.js ➔ read 0 87 20

How to fix   Complexity   

Complexity

Complex classes like src/cli/cms/data/file.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import path from 'path'
2
import fse from 'fs-extra'
3
import moment from 'moment'
4
5
import {
6
  Hooks,
7
  coreUtils,
8
  cmsData,
9
  config
10
} from '../../'
11
12
export function getAllWithKeys(withKeys) {
13
  var files = cmsData.file.getFiles(path.join(config.root, config.data.url), true, 99, /\.json/)
14
  var filesArr = []
15
16
  files.forEach(function (file) {
17
    var cleanFile = file
18
    var json = cmsData.file.get(file.path)
19
20
    if(json.abe_meta.latest.date != null) {
21
      file.date = json.abe_meta.latest.date
22
    }
23
24
    if(json.abe_meta != null) {
25
      var date = null
26
      if (json.abe_meta.latest.date != null) {
27
        date = json.abe_meta.latest.date
28
      } else if (json.abe_meta.date != null) {
29
        date = json.abe_meta.date
30
      }
31
      cleanFile.abe_meta = {
32
        date: date,
33
        type: (json.abe_meta.type != null) ? json.abe_meta.type : null,
34
        link: (json.abe_meta.link != null) ? json.abe_meta.link : null,
35
        template: (json.abe_meta.template != null) ? json.abe_meta.template : null,
36
        status: (json.abe_meta.status != null) ? json.abe_meta.status : null,
37
        cleanName: (json.abe_meta.cleanName != null) ? json.abe_meta.cleanName : null,
38
        cleanFilename: (json.abe_meta.cleanFilename != null) ? json.abe_meta.cleanFilename : null
39
      }
40
    }
41
    Array.prototype.forEach.call(withKeys, (key) => {
42
      var keyFirst = key.split('.')[0]
43
      cleanFile[keyFirst] = json[keyFirst]
44
    })
45
    filesArr.push(cleanFile)
46
  })
47
48
  var merged = cmsData.revision.getFilesMerged(filesArr)
49
50
  Hooks.instance.trigger('afterGetAllFiles', merged)
51
  return merged
52
}
53
54
export function get(pathJson) {
55
  var json = {}
56
  pathJson = Hooks.instance.trigger('beforeGetJson', pathJson)
57
  
58
  try {
59
    var stat = fse.statSync(pathJson)
60
    if (stat) {
61
      json = fse.readJsonSync(pathJson)
62
    }
63
  }catch(e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
64
  }
65
66
  json = Hooks.instance.trigger('afterGetJson', json)
67
  return json
68
}
69
70
export function fromUrl(url) {
71
  var res = {
72
    root: '',
73
    draft: {
74
      dir: '',
75
      file: '',
76
      path: ''
77
    },
78
    publish: {
79
      dir: '',
80
      file: '',
81
      link: '',
82
      path: '',
83
      json: ''
84
    },
85
    json: {
86
      path: '',
87
      file: ''
88
    }
89
  }
90
91
  if(url != null) {
92
93
    var dir = path.dirname(url).replace(config.root, '')
94
    var filename = path.basename(url)
95
    var link = url.replace(config.root, '')
96
    link = link.replace(/^\//, '').split('/')
97
    link.shift()
98
    link = cmsData.fileAttr.delete('/' + link.join('/').replace(/\/$/, ''))
99
100
    let draft = config.draft.url
101
    let publish = config.publish.url
102
    let data = config.data.url
103
104
    res.root = config.root
105
106
    // set dir path draft/json
107
    res.draft.dir = coreUtils.file.changePath(dir, draft)
108
    res.json.dir = coreUtils.file.changePath(dir, data)
109
    res.publish.dir = coreUtils.file.changePath(dir, publish)
110
    res.publish.json = res.json.dir
111
112
    // set filename draft/json
113
    res.draft.file = filename
114
    res.publish.file = cmsData.fileAttr.delete(filename)
115
    res.publish.link = link
116
    res.json.file = filename.replace(`.${config.files.templates.extension}`, '.json')
117
    res.publish.json = path.join(res.json.dir, cmsData.fileAttr.delete(res.json.file))
118
119
    // set filename draft/json
120
    res.draft.path = path.join(res.draft.dir, res.draft.file)
121
    res.publish.path = path.join(res.publish.dir, res.publish.file)
122
    res.json.path = path.join(res.json.dir, res.json.file)
123
  }
124
  return res
125
}
126
127
export function getFolders(folder, flatten = false, level) {
128
  var arr = []
0 ignored issues
show
Unused Code introduced by
The assignment to variable arr seems to be never used. Consider removing it.
Loading history...
129
  arr = cmsData.file.read(
130
    folder.replace(/\/$/, ''), 
131
    folder.replace(/\/$/, ''), 
132
    'folders', 
133
    flatten, 
134
    /(.*?)/, 
135
    level
136
  )
137
138
  return arr
139
}
140
141
export function getFiles(folder, flatten = false, level, extensions = /(.*?)/, inversePattern = false) {
142
143
  var arr = []
0 ignored issues
show
Unused Code introduced by
The assignment to variable arr seems to be never used. Consider removing it.
Loading history...
144
  arr = cmsData.file.read(
145
    folder.replace(/\/$/, ''),
146
    folder.replace(/\/$/, ''), 
147
    'files', 
148
    flatten, 
149
    extensions, 
150
    level, 
151
    0, 
152
    inversePattern
153
  )
154
155
  return arr
156
}
157
158
export function getFilesByType(pathFile, type = null) {
159
  try {
160
    var directory = fse.lstatSync(pathFile)
161
    if (!directory.isDirectory()) {
162
      mkdirp.sync(pathFile)
0 ignored issues
show
Bug introduced by
The variable mkdirp seems to be never declared. If this is a global, consider adding a /** global: mkdirp */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
163
    }
164
  } catch (e) {
165
    mkdirp.sync(pathFile)
166
  }
167
  var files = cmsData.file.getFiles(pathFile, true, 20, new RegExp(`.${config.files.templates.extension}`))
168
169
  var result = []
170
171
  Array.prototype.forEach.call(files, (file) => {
172
    var val = cmsData.fileAttr.get(file.path).s
173
    if(type === null || val === type) result.push(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...
174
  })
175
  return result
176
}
177
178
export function read(base, dirName, type, flatten, extensions = /(.*?)/, max = 99, current = 0, inversePattern = false) {
179
  var arr = []
180
  var level = fse.readdirSync(dirName)
181
  var fileCurrentLevel = []
182
  let assets = config.files.templates.assets
183
184
  for (var i = 0; i < level.length; i++) {
185
    var pathLevel = dirName + '/' + level[i]
186
    var isFolder = true
187
    try {
188
      var directory = fse.lstatSync(pathLevel)
189
      if (!directory.isDirectory()) {
190
        isFolder = false
191
      }
192
    } catch (e) {
193
      isFolder = false
194
    }
195
    var match = (isFolder) ? true : (inversePattern) ? !extensions.test(level[i]) : extensions.test(level[i])
196
    if((type === 'files' || type === null) && match) {
197
198
      if(level[i].indexOf('.') > -1) {
199
        var extension = /(\.[\s\S]*)/.exec(level[i])[0]
200
        var cleanName = cmsData.fileAttr.delete(level[i])
201
        var cleanNameNoExt = cleanName.replace(/\..+$/, '')
202
        var fileData = cmsData.fileAttr.get(level[i])
203
204
        var date
205
        if (fileData.d) {
206
          date = fileData.d
207
        }else {
208
          var stat = fse.statSync(pathLevel)
209
          date = stat.mtime
210
        }
211
        var cleanFilePath = cmsData.fileAttr.delete(pathLevel).replace(config.root, '').replace(/^\/?.+?\//, '')
212
213
        var fileDate = moment(date)
214
        var duration = moment.duration(moment(fileDate).diff(new Date())).humanize(true)
215
216
        var filePath = pathLevel.replace(config.root, '')
217
        filePath = filePath.split('/')
218
        filePath.shift()
219
        filePath = filePath.join('/')
220
        var item = {
221
          'name': level[i],
222
          'path': pathLevel,
223
          'cleanPathName': cmsData.fileAttr.delete(pathLevel),
224
          'cleanPath': pathLevel.replace(base + '/', ''),
225
          date: date,
226
          cleanDate: fileDate.format('YYYY/MM/DD HH:MM:ss'),
227
          duration: duration,
228
          cleanName: cleanName,
229
          cleanNameNoExt: cleanNameNoExt,
230
          cleanFilePath: cleanFilePath,
231
          filePath: filePath,
232
          'type': 'file',
233
          'fileType': extension
234
        }
235
236
        if(!flatten) item['folders'] = []
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...
237
        arr.push(item)
238
        // push current file name into array to check if siblings folder are assets folder
239
        fileCurrentLevel.push(level[i].replace(/\..+$/, '') + assets)
240
      }
241
    }
242
    if(!fileCurrentLevel.includes(level[i]) && match) {
243
      if(isFolder) {
244
        if(!flatten) {
245
          var index = arr.push({'name': level[i], 'path': pathLevel, 'cleanPath': pathLevel.replace(base + '/', ''), 'folders': [], 'type': 'folder'}) - 1
246
          if(current < max){
247
            arr[index].folders = cmsData.file.read(base, pathLevel, type, flatten, extensions, max, current + 1, inversePattern)
248
          }
249
        }else {
250
          if(type === 'folders' || type === null) {
251
            arr.push({'name': level[i], 'path': pathLevel, 'cleanPath': pathLevel.replace(base + '/', ''), 'type': 'folder'})
252
          }
253
          if(current < max){
254
            Array.prototype.forEach.call(cmsData.file.read(base, pathLevel, type, flatten, extensions, max, current + 1, inversePattern), (files) => {
255
              arr.push(files)
256
            })
257
          }
258
        }
259
      }
260
    }
261
  }
262
263
  return arr
264
}