Completed
Push — master ( e89f07...24a602 )
by greg
03:02
created

template.js ➔ ... ➔ ???   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
nc 2
dl 0
loc 7
rs 9.4285
nop 1
1
import fse from 'fs-extra'
2
import {Promise} from 'bluebird'
3
import path from 'path'
4
import {
5
  config,
6
  coreUtils,
7
  cmsData,
8
  abeExtend
9
} from '../../'
10
11
export function findTemplateAndPartialsInFolder (currentPath) {
12
  var res = []
13
  var files = fse.readdirSync(currentPath)
14
  for (var i in files) {
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...
15
    var currentFile = currentPath + '/' + files[i]
16
    var stats = fse.statSync(currentFile)
17
    if (stats.isFile()) {
18
      if (currentFile.indexOf('.' + config.files.templates.extension) > -1) {
19
        res.push(currentFile)
20
      }
21
    }
22
    else if (stats.isDirectory()) {
23
      res = res.concat(findTemplateAndPartialsInFolder(currentFile))
24
    }
25
  }
26
  return res
27
}
28
29
export function getTemplateAndPartials(templatesPath) {
30
  var p = new Promise((resolve) => {
31
    let templatesList = findTemplateAndPartialsInFolder(templatesPath)
32
    resolve(templatesList)
33
  })
34
35
  return p
36
}
37
38
export function addOrder(text) {
39
  var regAbe = /{{abe[\S\s].*?key=['|"]([\S\s].*?['|"| ]}})/g
40
  var matches = text.match(regAbe)
41
  var order = 0
42
  
43
  if(typeof matches !== 'undefined' && matches !== null){
44
    Array.prototype.forEach.call(matches, (match) => {
45
      if(typeof match !== 'undefined' && match !== null) {
46
        
47
        var orderAttr = cmsData.regex.getAttr(match, 'order')
48
49
        if(typeof orderAttr === 'undefined' || orderAttr === null || orderAttr === '') {
50
          var matchOrder = match.replace(/\}\}$/, ` order='${order}'}}`)
51
          text = text.replace(match, matchOrder)
52
        }
53
        order++
54
      }
55
    })
56
  }
57
  return text
58
}
59
60
export function getAbeImport(text) {
61
  var partials = []
62
  let listReg = /({{abe.*?type=[\'|\"]import.*?}})/g
63
  var match
64
  while (match = listReg.exec(text)) {
65
    partials.push(match[0])
66
  }
67
68
  return partials
69
}
70
71
export function includePartials(text) {
72
  var abeImports = getAbeImport(text)
73
74
  Array.prototype.forEach.call(abeImports, (abeImport) => {
75
    var obj = cmsData.attributes.getAll(abeImport, {})
76
77
    var file = obj.file
78
    var partial = ''
79
    file = path.join(config.root, config.partials, file)
80
    if(coreUtils.file.exist(file)) {
81
      partial = includePartials(fse.readFileSync(file, 'utf8'))
82
    }
83
    text = text.replace(cmsData.regex.escapeTextToRegex(abeImport, 'g'), partial)
84
  })
85
86
  return text
87
}
88
89
function translate(text) {
90
  var importReg = /({{abe.*type=[\'|\"]translate.*}})/g
91
92
  var matches = text.match(importReg)
93
  
94
  if(typeof matches !== 'undefined' && matches !== null) {
95
    Array.prototype.forEach.call(matches, (match) => {
96
      var splitedMatches = match.split('{{abe ')
97
98
      Array.prototype.forEach.call(splitedMatches, (splitedMatch) => {
99
        var currentMatch = `{{abe ${splitedMatch}`
100
        if(/({{abe.*type=[\'|\"]translate.*}})/.test(currentMatch)) {
101
          var locale = cmsData.regex.getAttr(currentMatch, 'locale')
102
          var source = cmsData.regex.getAttr(currentMatch, 'source')
103
104
          if (locale.indexOf('{{') === -1) {
105
            locale = `'${locale}'`
106
          }else {
107
            locale = locale.replace(/\{\{(.*?)\}\}/, '$1')
108
          }
109
110
          if (source.indexOf('{{') === -1) {
111
            source = `'${source.replace(/'/g, '\\\'')}'`
112
          }else {
113
            source = source.replace(/\{\{(.*?)\}\}/, '$1')
114
          }
115
116
          // var replace = `{{{i18nAbe ${locale} ${source}}}}`
117
          var replace = currentMatch.replace('{{abe', '{{i18nAbe')
118
          replace = replace.replace(/locale=['|"].*?['|"]/, locale)
119
          replace = replace.replace(/source=['|"].*?['|"]/, source)
120
          replace = replace.replace(/{{i18nAbe.*?}}/, `{{{i18nAbe ${locale} ${source}}}}`)
121
122
          text = text.replace(cmsData.regex.escapeTextToRegex(currentMatch, 'g'), replace)
123
        }
124
      })
125
    })
126
  }
127
128
  return text
129
}
130
131
export function getTemplate (file) {
132
  var text = ''
133
134
  // HOOKS beforeGetTemplate
135
  file = abeExtend.hooks.instance.trigger('beforeGetTemplate', file)
136
137
  file = file.replace(path.join(config.root, config.templates.url), '')
138
  file = file.replace(config.root, '')
139
  if (file.indexOf('.') > -1) {
140
    file = file.replace(/\..+$/, '')
141
  }
142
  file = path.join(config.root, config.templates.url, file + '.' + config.files.templates.extension)
143
  if(coreUtils.file.exist(file)) {
144
    text = fse.readFileSync(file, 'utf8')
145
    text = includePartials(text)
146
    text = translate(text)
147
    text = addOrder(text)
148
  }else {
149
    text = `[ ERROR ] template ${file + '.' + config.files.templates.extension} doesn't exist anymore`
150
  }
151
152
  // HOOKS afterGetTemplate
153
  text = abeExtend.hooks.instance.trigger('afterGetTemplate', text)
154
155
  return text
156
}
157
158
export function getVariablesInWhere(where) {
159
  var ar = []
160
161
  if(where.left.column.indexOf('{{') > -1) {
162
    ar.push(where.left.column.replace(/\{\{(.*?)\}\}/, '$1'))
163
  }
164
  else{
165
    ar.push(where.left.column)
166
  }
167
168
  if (where.right.value) {
169
    if (typeof where.right.value === 'string') {
170
      if(where.right.value && where.right.value.indexOf('{{') > -1) {
171
        ar.push(where.right.value.replace(/\{\{(.*?)\}\}/, '$1'))
172
      }
173
    }else {
174
      where.right.value.forEach(function (value) {
175
        if(value.column.indexOf('{{') > -1) {
176
          ar.push(value.column.replace(/\{\{(.*?)\}\}/, '$1'))
177
        }
178
      })
179
    }
180
  }
181
182
  if(where.right.column && where.right.column.indexOf('{{') > -1) {
183
    ar.push(where.right.column.replace(/\{\{(.*?)\}\}/, '$1'))
184
  }
185
186
  return ar
187
}
188
189
/**
190
 * Get columns and where.left ids of a select statement
191
 *
192
 * select title, image from ../ where template=""
193
 *
194
 * return [title, image, template]
195
 * 
196
 * @param  {Array} templatesList ["article.html", "other.html"]
0 ignored issues
show
Documentation introduced by
The parameter templatesList does not exist. Did you maybe forget to remove this comment?
Loading history...
197
 * @return {Promise}
198
 */
199
export function recurseWhereVariables (where) {
200
  var ar = []
0 ignored issues
show
Unused Code introduced by
The assignment to variable ar seems to be never used. Consider removing it.
Loading history...
201
  var arLeft
202
  var arRight
203
  switch(where.operator) {
204
  case 'AND':
205
    arLeft = recurseWhereVariables(where.left)
206
    arRight = recurseWhereVariables(where.right)
207
    return arLeft.concat(arRight)
208
    break
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
209
  case 'OR':
210
    arLeft = recurseWhereVariables(where.left)
211
    arRight = recurseWhereVariables(where.right)
212
    return arLeft.concat(arRight)
213
    break
0 ignored issues
show
Unused Code introduced by
This break statement is unnecessary and may be removed.
Loading history...
214
  default:
215
    ar = getVariablesInWhere(where)
216
    break
217
  }
218
219
  return ar
220
}
221
222
export function execRequestColumns(tpl) {
223
  var ar = []
224
  var matches = cmsData.regex.getTagAbeTypeRequest(tpl)
225
  Array.prototype.forEach.call(matches, (match) => {
226
    var obj = cmsData.attributes.getAll(match[0], {})
227
    var type = cmsData.sql.getSourceType(obj.sourceString)
228
    switch (type) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
229
    case 'request':
230
      var request = cmsData.sql.handleSqlRequest(obj.sourceString, {})
231
      if(typeof request.columns !== 'undefined' && request.columns !== null) {
232
        Array.prototype.forEach.call(request.columns, (column) => {
233
          ar.push(column)
234
        })
235
      }
236
      if(typeof request.where !== 'undefined' && request.where !== null) {
237
        ar = ar.concat(recurseWhereVariables(request.where))
238
      }
239
    }
240
  })
241
242
  return ar
243
}
244
245
export function findRequestColumns(templatesList) {
246
  var whereKeys = []
247
  var p = new Promise((resolve) => {
248
    Array.prototype.forEach.call(templatesList, (file) => {
249
      var template = fse.readFileSync(file, 'utf8')
250
      whereKeys = whereKeys.concat(execRequestColumns(template))
251
    })
252
    whereKeys = whereKeys.filter(function (item, pos) {return whereKeys.indexOf(item) == pos})
253
    resolve(whereKeys)
254
  })
255
256
  return p
257
}
258
259
export function getSelectTemplateKeys(templatesPath) {
260
  var p = new Promise((resolve, reject) => {
261
    return getTemplateAndPartials(templatesPath)
262
      .then((templatesList) => {
263
        return findRequestColumns(templatesList)
264
          .then((whereKeys) => {
265
            resolve(whereKeys)
266
          },
267
          (e) => {
268
            console.log('findRequestColumns reject')
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...
269
            reject(e)
270
          })
271
          .catch((e) => {
272
            console.error('getSelectTemplateKeys', e)
273
            reject()
274
          })
275
      },
276
      () => {
277
        console.log('getTemplateAndPartials reject')
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...
278
        reject()
279
      })
280
      .catch((e) => {
281
        console.error('getSelectTemplateKeys', e)
282
        reject()
283
      })
284
285
  })
286
287
  return p
288
}
289
290
export function getStructureAndTemplates() {
291
  var site = cmsData.revision.filePathInfos(config.root)
292
  var result = {'structure': [], 'templates': []}
293
294
  const pathStructure = path.join(site.path, config.structure.url)
295
  const pathTemplates = path.join(site.path, config.templates.url)
296
  try {
297
    let directoryStructure = fse.lstatSync(pathStructure)
298
    if (directoryStructure.isDirectory()) {
299
      result.structure = cmsData.file.getFolders(pathStructure, false)
300
    }
301
  } 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...
302
  }
303
  try {
304
    let directoryTemplate = fse.lstatSync(pathTemplates)
305
    if (directoryTemplate.isDirectory()) {
306
      let extension = '.' + config.files.templates.extension
307
      let resultTemplates = []
0 ignored issues
show
Unused Code introduced by
The variable resultTemplates seems to be never used. Consider removing it.
Loading history...
308
      let templatePaths = coreUtils.file.getFilesSync(pathTemplates, true, extension)
309
      Array.prototype.forEach.call(templatePaths, (templatePath) => {
310
        let additionalPath = path.dirname(templatePath).replace(pathTemplates,'')
311
        if(additionalPath !== '') additionalPath = additionalPath.substring(1)
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...
312
        let name = path.join(additionalPath,path.basename(templatePath,extension))
313
        let template = {'path':templatePath, 'cleanPath':templatePath, 'cleanNameNoExt':name}
314
        result.templates.push(template)
315
      })
316
    }
317
  } 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...
318
  }
319
320
  return result
321
}