Completed
Push — master ( 3b3ae1...61dd3f )
by greg
01:50
created

src/cli/cms/data/file-attr.js   A

Size

Lines of Code 304

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
nc 1
dl 0
loc 304
rs 10
noi 8

1 Function

Rating   Name   Duplication   Size   Complexity  
A file-attr.js ➔ ??? 0 5 1
1
import fse from 'fs-extra'
2
import path from 'path'
3
import {
4
  cli
0 ignored issues
show
Unused Code introduced by
The variable cli seems to be never used. Consider removing it.
Loading history...
5
  ,FileParser
6
  ,fileUtils
7
  ,dateUnslug
8
  ,config
9
  ,Manager
10
} from '../../'
11
12
var fullAttr = '-abe-(.+?)(?=\.'
13
var captureAttr = '-abe-(.+?)(?=\.'
14
var oneAttr = ['[\\|]?', '=(.)*?(?=[\||\\]])']
15
16
/**
17
 * Class Attr
18
 * Work string to manage string attributes key/value
19
 */
20
class Attr {
21
22
  /**
23
   * @param  {String} str string to work with
24
   * @return {void}
25
   */
26
  constructor(str) {
27
    this.str = str
28
    this.val = {}
29
    this.extract()
30
  }
31
32
  /**
33
   * @return {Object} attributs extracted from string as an object
34
   */
35
  extract() {
36
    var rex = new RegExp(captureAttr + this.getExtention() + ')')
37
    if(rex.test(this.str)) {
38
      var arrAttr = this.str.match(rex)[0].replace('-abe-', '')
39
      this.val = {'s': arrAttr[0], 'd': dateUnslug(arrAttr.slice(1), this.str)}
40
    }
41
    return this.val
42
  }
43
44
  /**
45
   * @return {String} str without an attributs
46
   */
47
  remove() {
48
    return this.str.replace(new RegExp(fullAttr + this.getExtention() + ')'), '')
49
  }
50
 
51
  getExtention(){
52
    var ext = this.str.split('.')
53
    return ext[ext.length - 1]
54
  }
55
56
  /**
57
   * Insert attributs to the string
58
   * @param  {String} string composed of a status (ex: v for validate, d for draft ...) and a date
0 ignored issues
show
Documentation introduced by
The parameter string does not exist. Did you maybe forget to remove this comment?
Loading history...
59
   * @return {String} the new string with added attributs
60
   */
61
  insert(newValues) {
62
    var strWithoutAttr = this.remove()
63
    strWithoutAttr = strWithoutAttr.replace(new RegExp('\\.' + this.getExtention()), '')
64
    return strWithoutAttr + '-abe-' + newValues + '.' + this.getExtention()
65
  }
66
67
}
68
69
/**
70
 * Class FileAttr
71
 * Manage string with attributs encoded inside
72
 */
73
export default class FileAttr {
74
75
  /**
76
   * Add attributs or modify them if they already exists
77
   * @param {String} str the string to modify
78
   * @param {Object} options object with attributs to add
79
   * @return {String} the string with the new attributs
80
   */
81
  static add(str, options) {
82
    var attr = new Attr(str)
83
    return attr.insert(options)
84
  }
85
86
  /**
87
   * Remove attributs from string
88
   * @param {String} str the string to modify
89
   * @return {String} the string modified
90
   */
91
  static delete(str) {
92
    return new Attr(str).remove()
93
  }
94
95
  /**
96
   * @param  {String} str the string to get attributs from
97
   * @return {object|String} object (all the attributs) if the key is null, if not the value of the atrtibuts
98
   */
99
  static get(str) {
100
    return new Attr(str).val
101
  }
102
103
  /**
104
   * @param  {String} str the string to test attributs from
105
   * @return {boolean} true if string has attr
106
   */
107
  static test(str) {
108
    var att = new Attr(str).val
109
    return (typeof att.s !== 'undefined' && att.s !== null)
110
  }
111
112
  static getFilesRevision(urls, fileName) {
113
    var res = []
114
    var number = 1
115
    var tplUrl = FileParser.getFileDataFromUrl(fileName)
116
    fileName = fileName.split('/')
117
    fileName = fileName[fileName.length - 1]
118
    var publishDate = new Date()
119
    var json = null
120
121
    if(fileUtils.isFile(tplUrl.publish.json)) {
122
      json = FileParser.getJson(tplUrl.publish.json)
123
      if(typeof json !== 'undefined' && json !== null
124
        && typeof json[config.meta.name] !== 'undefined' && json[config.meta.name] !== null) {
125
        publishDate = new Date(json[config.meta.name].latest.date)
126
      }
127
    }
128
129
    var publishVersion = false
130
    urls.forEach(function (urlObj) {
131
      var fileData = FileAttr.get(urlObj.cleanPath)
132
      if(fileData.s === 'd' && FileAttr.delete(urlObj.cleanPath) == FileAttr.delete(fileName)) {
133
        var currentDate = new Date(urlObj.date)
134
        if(currentDate.getTime() > publishDate.getTime()) {
135
          if(!publishVersion && typeof res[res.length - 1] !== 'undefined' && res[res.length - 1] !== null) {
136
            res[res.length - 1].publishedDate = 'same'
137
          }
138
          publishVersion = true
139
          urlObj.publishedDate = 'after'
140
          
141
        }else if(currentDate.getTime() === publishDate.getTime()) {
142
          urlObj.publishedDate = 'same'
143
          publishVersion = true
144
        }else {
145
          urlObj.publishedDate = 'before'
146
        }
147
        urlObj.version = number
148
        number = number + 1
149
150
        var tplUrlObj = FileParser.getFileDataFromUrl(urlObj.path)
151
        if(fileUtils.isFile(tplUrlObj.publish.json)) {
152
          var jsonObj = FileParser.getJson(tplUrlObj.publish.json)
153
          urlObj[config.meta.name] = jsonObj[config.meta.name]
154
        }
155
        res.push(urlObj)
156
      }
157
    })
158
    return res
159
  }
160
161
  static sortByDateDesc(a, b) {
162
    var dateA = new Date(a.date)
163
    var dateB = new Date(b.date)
164
    if(dateA < dateB) {
165
      return 1
166
    }else if(dateA > dateB) {
167
      return -1
168
    }
169
    return 0
170
  }
171
172
  /**
173
   * Filter and array of file path and return the latest version of those files
174
   * @param  {Object} urls object with path to file, filename etc ...
0 ignored issues
show
Documentation introduced by
The parameter urls does not exist. Did you maybe forget to remove this comment?
Loading history...
175
   * @param  {String} type (draft|waiting|valid)
0 ignored issues
show
Documentation introduced by
The parameter type does not exist. Did you maybe forget to remove this comment?
Loading history...
176
   * @return {Object} urls object filtered
177
   */
178
  static getVersions(docPath) {
179
    var files = Manager.instance.getList()
180
    var fileWithoutExtension = docPath.replace('.' + config.files.templates.extension, '.json')
181
182
    var result = []
183
    Array.prototype.forEach.call(files, (file) => {
184
      if (file.path.indexOf(fileWithoutExtension) > -1) {
185
        result = file.revisions
186
      }
187
    })
188
    return result
189
  }
190
191
  /**
192
   * Return the revision from document html file path
193
   * if the docPath contains abe revision [status]-[date] will try to return this revision
194
   * else it will return the latest revision
195
   * or null
196
   * 
197
   * @param  {String} html path
0 ignored issues
show
Documentation introduced by
The parameter html does not exist. Did you maybe forget to remove this comment?
Loading history...
198
   * @return {Object} file revision | null
199
   */
200
  static getDocumentRevision(docPath) {
201
    var result = null
202
    var documentPath = docPath
203
    var latest = true
204
    if(FileAttr.test(documentPath)){
205
      latest = false
206
      documentPath = FileAttr.delete(documentPath)
207
    }
208
    var revisions = FileAttr.getVersions(documentPath)
209
    if (latest && revisions.length >= 0) {
210
      result = revisions[0]
211
    }else if (!latest) {
212
      Array.prototype.forEach.call(revisions, (revision) => {
213
        if (revision.html === docPath) {
214
          result = revision
215
        }
216
      })
217
      if (result === null && revisions.length >= 0) {
218
        result = revisions[0]
219
      }
220
    }
221
    return result
222
  }
223
224
  /**
225
   * Filter and array of file path and return the latest version of those files
226
   * @param  {Object} urls object with path to file, filename etc ...
227
   * @param  {String} type (draft|waiting|valid)
228
   * @return {Object} urls object filtered
229
   */
230
  static filterLatestVersion(urls, type = '') {
231
    var typeStr = ''
232
    switch(type){
233
    case 'draft': typeStr = 'd'; break
234
    default: typeStr = type[0]; break
235
    }
236
    return FileAttr.filter(urls, 'latest', typeStr)
237
  }
238
239
  /**
240
   * Filter and array of file 
241
   * @param  {[type]} urlsArr urls object with path to file, filename etc ...
242
   * @param  {[type]} filter filter to use
243
   * @param  {String} type
244
   * @return {Object} urls object filtered
245
   */
246
  static filter(urlsArr, filter, type = '') {
247
    var latest = []
248
    var result = []
249
250
251
    urlsArr.forEach(function (urlObj) {
252
253
      var realFileName = FileAttr.delete(urlObj.cleanPath)
254
      var cleanPath = urlObj.cleanPath
255
      var currentAttrDate = FileAttr.get(urlObj.cleanPath)
256
      
257
      if(currentAttrDate.s === type){
258
        if(typeof latest[realFileName] !== 'undefined' && latest[realFileName] !== null){
259
          switch(filter){
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
260
          case 'latest': 
261
            var savedAttrDate = FileAttr.get(latest[realFileName].cleanPath)
262
            var dateSavedUrl = new Date(savedAttrDate.length > 1 ? savedAttrDate : 0)
263
            var dateCurrentUrl = new Date(currentAttrDate.d.length > 1 ? currentAttrDate.d : 0)
264
            if(dateSavedUrl < dateCurrentUrl) latest[realFileName] = urlObj
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...
265
            break
266
          }
267
        }
268
        else {
269
          latest[realFileName] = urlObj
270
        }
271
      }
272
    })
273
274
    for (var prop in latest) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
275
      result.push(latest[prop])
276
    }
277
278
    return result
279
  }
280
281
  static getLatestRevision(filePath) {
282
    let draft = config.draft.url
283
    var folder = fileUtils.removeLast(filePath)
284
    var fileName = filePath.replace(folder + '/', '')
285
    folder = folder.replace(config.root, '')
286
287
    folder = FileParser.changePathEnv(path.join(config.root, folder), draft)
288
289
    var arr = FileParser.getFiles(folder, true, 0)
290
    var sameFiles = []
291
    Array.prototype.forEach.call(arr, (item) => {
292
      if(item.cleanName === fileName) {
293
        sameFiles.push(item)
294
      }
295
    })
296
297
    var latest = FileAttr.filter(sameFiles, 'latest', 'd')
298
    if(typeof latest !== 'undefined' && latest !== null
299
      && latest.length > 0) {
300
      return latest[0]
301
    }
302
    return null
303
  }
304
}
305
306