Completed
Push — master ( 976119...75ac8d )
by greg
17s
created

src/cli/core/manager/Manager.js (35 issues)

1
//import Handlebars from 'handlebars'
2
import fse from 'fs-extra'
3
import events from 'events'
4
import path from 'path'
5
import watch from 'watch'
6
import express from 'express'
7
import bodyParser from 'body-parser'
8
import tinylr from 'tiny-lr'
9
import clc from 'cli-color'
10
import {
11
  coreUtils,
12
  cmsData,
13
  config,
14
  cmsTemplates,
15
  cmsReference,
16
  cmsMedia,
17
  cmsOperations,
18
  abeExtend
19
} from '../../'
20
21
let singleton = Symbol()
22
let singletonEnforcer = Symbol()
23
24
class Manager {
25
  constructor(enforcer) {
26
    if (enforcer != singletonEnforcer) throw 'Cannot construct Json singleton'
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...
27
  }
28
29
  static get instance() {
30
    if (!this[singleton]) {
31
      this[singleton] = new Manager(singletonEnforcer)
32
    }
33
    return this[singleton]
34
  }
35
36
  init() {
37
    this._processesRunning = {}
38
    this.events = {}
39
40
    // Compatibility for abe version < 3.2.
41
    // It's possible to reference html from any directory
42
    if (process.env.ABE_TEMPLATES_PATH) {
43
      this.pathTemplates = path.join(
44
        config.root,
45
        process.env.ABE_TEMPLATES_PATH
46
      )
47
      this.pathPartials = path.join(this.pathTemplates, 'partials')
48
    } else if (
49
      config.themes != null &&
50
      coreUtils.file.exist(
51
        path.join(
52
          config.root,
53
          config.themes.path,
54
          config.themes.name,
55
          config.themes.templates.path
56
        )
57
      )
58
    ) {
59
      this.pathTemplates = path.join(
60
        config.root,
61
        config.themes.path,
62
        config.themes.name,
63
        config.themes.templates.path
64
      )
65
      this.pathPartials = path.join(
66
        config.root,
67
        config.themes.path,
68
        config.themes.name,
69
        config.themes.partials.path
70
      )
71
    } else {
72
      // did the users of the versions < 3.2 overriden the default templates path or partials path ?
73
      if (config.templates != null && config.templates.url != null) {
74
        this.pathTemplates = path.join(config.root, config.templates.url)
75
      } else {
76
        this.pathTemplates = path.join(config.root, 'templates')
77
      }
78
      if (config.partials != null) {
79
        this.pathPartials = path.join(config.root, config.partials)
80
      } else {
81
        this.pathPartials = path.join(config.root, 'partials')
82
      }
83
    }
84
85
    this.pathAssets = this.pathTemplates
86
    if (process.env.ABE_ASSETS_PATH) {
87
      this.pathAssets = path.join(
88
        config.root,
89
        process.env.ABE_ASSETS_PATH
90
      )
91
    }
92
    this.pathPublish = path.join(config.root, config.publish.url)
93
    if (process.env.ABE_DESTINATION_PATH) {
94
      this.pathPublish = path.join(
95
        config.root,
96
        process.env.ABE_DESTINATION_PATH
97
      )
98
    }
99
100
    // config.data.url was the config prior to v3.7.0
101
    if (process.env.ABE_JSON_PATH) {
102
      this.pathData = path.join(
103
        config.root,
104
        process.env.ABE_JSON_PATH
105
      )
106
    } else if (config.data.url != null) {
107
      this.pathData = path.join(config.root, config.data.url)
108
    } else if (coreUtils.file.exist(path.join(config.root, config.data.path))) {
109
      this.pathData = path.join(config.root, config.data.path)
110
    } else {
111
      this.pathData = path.join(config.root, 'data')
112
    }
113
114
    this.pathTemplates = this.pathTemplates.replace(/\/$/, "")
115
    this.pathPartials = this.pathPartials.replace(/\/$/, "")
116
    this.pathAssets = this.pathAssets.replace(/\/$/, "")
117
    this.pathPublish = this.pathPublish.replace(/\/$/, "")
118
    this.pathData = this.pathData.replace(/\/$/, "");
119
    this.pathScripts = path.join(config.root, config.scripts.path)
120
    this.pathStructure = path.join(config.root, config.structure.url)
121
    this.pathReference = path.join(config.root, config.reference.url)
122
    this.pathLocales = path.join(config.root, 'locales')
123
124
    this.connections = []
125
    this.activities = []
126
    this._watcherActivity()
127
128
    this.updateStructureAndTemplates()
129
130
    var p = new Promise(resolve => {
131
      this.getKeysFromSelect()
132
        .then(
133
          () => {
134
            resolve()
135
          },
136
          e => {
137
            console.log('Manager.init', e)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
138
            resolve()
139
          }
140
        )
141
        .catch(e => {
142
          console.log('Manager.init', e)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
143
        })
144
    })
145
146
    return p
147
  }
148
149
  initDev() {
150
    console.log(`You are in ${process.env.NODE_ENV} mode`)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
151
    console.log(
152
      'which means every change in your themes (templates, partials and assets), reference and structure folders will dynamically update your site'
153
    )
154
    console.log("In production, this mode shouldn't be used.")
155
156
    this._watchersStart()
157
158
    var lport = process.env.LIVERELOAD_PORT || 35729
159
    this.lserver = express()
160
161
    // Launching a Livereload server
162
    this.lserver
163
      .use(bodyParser.json())
164
      .use(bodyParser.urlencoded({extended: true}))
165
      .use(tinylr.middleware({app: this.lserver}))
166
      .listen(lport, function() {
167
        console.log('Livereload listening on %d', lport)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
168
      })
169
      .on('error', function(err) {
170
        if (err.code == 'EADDRINUSE') {
171
          console.error(
172
            clc.red("can't start the Abe's watch server\n"),
173
            `This watch server has tried to listen on the port ${lport} but this server is already in use by another process...`
174
          )
175
        } else {
176
          console.error(err)
177
        }
178
      })
179
180
    process.on('SIGINT', () => {
181
      try {
182
        this.lserver.close(() => {
183
          console.log('SIGINT:Livereload server has been gracefully terminated')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
184
          process.exit(0)
0 ignored issues
show
Compatibility Debugging Code Best Practice introduced by
Use of process.exit() is discouraged as it will potentially stop the complete node.js application. Consider quitting gracefully instead by throwing an Error.
Loading history...
185
        })
186
      } catch (error) {}
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...
187
    })
188
    process.on('SIGTERM', () => {
189
      try {
190
        this.lserver.close(() => {
191
          console.log(
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
192
            'SIGTERM:Livereload server has been gracefully terminated'
193
          )
194
          process.exit(0)
0 ignored issues
show
Compatibility Debugging Code Best Practice introduced by
Use of process.exit() is discouraged as it will potentially stop the complete node.js application. Consider quitting gracefully instead by throwing an Error.
Loading history...
195
        })
196
      } catch (error) {}
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...
197
    })
198
199
    // sync assets from templates to /site
200
    cmsTemplates.assets.copy()
201
  }
202
203
  _watcherActivity() {
204
    this.events.activity = new events.EventEmitter(0)
205
206
    this.events.activity.on(
207
      'activity',
208
      function(data) {
209
        if (data.user && data.user.username) {
210
          data.user = data.user.username
211
        } else {
212
          data.user = 'admin'
213
        }
214
        this.addActivity(data)
215
        this.events.activity.emit('activity-stream', data)
216
      }.bind(this)
217
    )
218
  }
219
220
  _watchersStart() {
221
    this.events.template = new events.EventEmitter(0)
222
    this.events.structure = new events.EventEmitter(0)
223
    this.events.reference = new events.EventEmitter(0)
224
    this.events.scripts = new events.EventEmitter(0)
225
    this.events.locales = new events.EventEmitter(0)
226
227
    // watch template folder
228
    try {
229
      fse.accessSync(this.pathTemplates, fse.F_OK)
230
      this._watchTemplateFolder = watch.createMonitor(
231
        this.pathTemplates,
232
        monitor => {
233
          monitor.on('created', (f, stat) => {
0 ignored issues
show
The parameter stat is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
234
            if (f.indexOf(`.${config.files.templates.extension}`) < 0) {
235
              cmsTemplates.assets.copy()
236
              tinylr.changed(f)
237
              console.log(
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
238
                'Assets have been synchronized after this creation: ' + f
239
              )
240
            } else {
241
              this.getKeysFromSelect()
242
              this.updateStructureAndTemplates()
243
              if (typeof this.lserver != 'undefined') {
244
                tinylr.changed(f)
245
              }
246
              this.events.template.emit('update')
247
            }
248
          })
249
          monitor.on('changed', (f, curr, prev) => {
0 ignored issues
show
The parameter curr is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
The parameter prev is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
250
            if (f.indexOf(`.${config.files.templates.extension}`) < 0) {
251
              cmsTemplates.assets.copy()
252
              if (typeof this.lserver != 'undefined') {
253
                tinylr.changed(f)
254
              }
255
              console.log(
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
256
                'Assets have been synchronized after this modification: ' + f
257
              )
258
            } else {
259
              this.getKeysFromSelect()
260
              this.updateStructureAndTemplates()
261
              if (typeof this.lserver != 'undefined') {
262
                tinylr.changed(f)
263
              }
264
              this.events.template.emit('update')
265
            }
266
          })
267
          monitor.on('removed', (f, stat) => {
0 ignored issues
show
The parameter stat is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
268
            if (f.indexOf(`.${config.files.templates.extension}`) < 0) {
269
              cmsTemplates.assets.copy()
270
              if (typeof this.lserver != 'undefined') {
271
                tinylr.changed(f)
272
              }
273
              console.log(
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
274
                'Assets have been synchronized after this deletion: ' + f
275
              )
276
            } else {
277
              this.getKeysFromSelect()
278
              this.updateStructureAndTemplates()
279
              if (typeof this.lserver != 'undefined') {
280
                tinylr.changed(f)
281
              }
282
              this.events.template.emit('update')
283
            }
284
          })
285
        }
286
      )
287
    } catch (e) {
288
      console.log('the directory ' + this.pathTemplates + ' does not exist')
289
    }
290
291
    // watch partial folder
292
    try {
293
      fse.accessSync(this.pathPartials, fse.F_OK)
294
      this._watchPartialsFolder = watch.createMonitor(
295
        this.pathPartials,
296
        monitor => {
297
          monitor.on('created', f => {
298
            this.getKeysFromSelect()
299
            this.updateStructureAndTemplates()
300
            if (typeof this.lserver != 'undefined') {
301
              tinylr.changed(f)
302
            }
303
            this.events.template.emit('update')
304
          })
305
          monitor.on('changed', f => {
306
            this.getKeysFromSelect()
307
            this.updateStructureAndTemplates()
308
            if (typeof this.lserver != 'undefined') {
309
              tinylr.changed(f)
310
            }
311
            this.events.template.emit('update')
312
          })
313
          monitor.on('removed', f => {
314
            this.getKeysFromSelect()
315
            this.updateStructureAndTemplates()
316
            if (typeof this.lserver != 'undefined') {
317
              tinylr.changed(f)
318
            }
319
            this.events.template.emit('update')
320
          })
321
        }
322
      )
323
    } catch (e) {
324
      console.log('the directory ' + this.pathPartials + ' does not exist')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
325
    }
326
327
    try {
328
      fse.accessSync(this.pathStructure, fse.F_OK)
329
      this._watchStructure = watch.createMonitor(
330
        this.pathStructure,
331
        monitor => {
332
          monitor.on('created', () => {
333
            this.updateStructureAndTemplates()
334
            this.events.structure.emit('update')
335
          })
336
          monitor.on('changed', () => {
337
            this.updateStructureAndTemplates()
338
            this.events.structure.emit('update')
339
          })
340
          monitor.on('removed', () => {
341
            this.updateStructureAndTemplates()
342
            this.events.structure.emit('update')
343
          })
344
        }
345
      )
346
    } catch (e) {
347
      console.log('the directory ' + this.pathStructure + ' does not exist')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
348
    }
349
350
    try {
351
      fse.accessSync(this.pathReference, fse.F_OK)
352
      this._watchReferenceFolder = watch.createMonitor(
353
        this.pathReference,
354
        monitor => {
355
          monitor.on('created', f => {
356
            this.updateReferences(f)
357
            if (typeof this.lserver != 'undefined') {
358
              tinylr.changed(f)
359
            }
360
            this.events.reference.emit('update')
361
          })
362
          monitor.on('changed', f => {
363
            this.updateReferences(f)
364
            if (typeof this.lserver != 'undefined') {
365
              tinylr.changed(f)
366
            }
367
            this.events.reference.emit('update')
368
          })
369
          monitor.on('removed', f => {
370
            this.updateReferences()
371
            if (typeof this.lserver != 'undefined') {
372
              tinylr.changed(f)
373
            }
374
            this.events.reference.emit('update')
375
          })
376
        }
377
      )
378
    } catch (e) {
379
      console.log('the directory ' + this.pathReference + ' does not exist')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
380
    }
381
382
    try {
383
      fse.accessSync(this.pathLocales, fse.F_OK)
384
      this._watchLocalesFolder = watch.createMonitor(
385
        this.pathLocales,
386
        monitor => {
387
          monitor.on('created', f => {
388
            coreUtils.locales.instance.reloadLocales()
389
            if (typeof this.lserver != 'undefined') {
390
              tinylr.changed(f)
391
            }
392
            this.events.locales.emit('update')
393
          })
394
          monitor.on('changed', f => {
395
            coreUtils.locales.instance.reloadLocales()
396
            if (typeof this.lserver != 'undefined') {
397
              tinylr.changed(f)
398
            }
399
            this.events.locales.emit('update')
400
          })
401
          monitor.on('removed', f => {
402
            coreUtils.locales.instance.reloadLocales()
403
            if (typeof this.lserver != 'undefined') {
404
              tinylr.changed(f)
405
            }
406
            this.events.locales.emit('update')
407
          })
408
        }
409
      )
410
    } catch (e) {
411
      console.log('the directory ' + this.pathLocales + ' does not exist')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
412
    }
413
414
    try {
415
      fse.accessSync(this.pathScripts, fse.F_OK)
416
      this._watchScripts = watch.createMonitor(this.pathScripts, monitor => {
417
        monitor.on('created', () => {
418
          abeExtend.plugins.instance.updateScripts()
419
          this.events.scripts.emit('update')
420
        })
421
        monitor.on('changed', () => {
422
          abeExtend.plugins.instance.updateScripts()
423
          this.events.scripts.emit('update')
424
        })
425
        monitor.on('removed', () => {
426
          abeExtend.plugins.instance.updateScripts()
427
          this.events.scripts.emit('update')
428
        })
429
      })
430
    } catch (e) {
431
      console.log('the directory ' + this.pathScripts + ' does not exist')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
432
    }
433
  }
434
435
  getKeysFromSelect() {
436
    this._whereKeys = []
437
    var p = new Promise(resolve => {
438
      cmsTemplates.template
439
        .getTemplatesAndPartials(this.pathTemplates, this.pathPartials)
440
        .then(
441
          templatesList => {
442
            return cmsTemplates.template
443
              .getTemplatesTexts(templatesList)
444
              .then(
445
                templatesText => {
446
                  return cmsTemplates.template
447
                    .getAbeRequestWhereKeysFromTemplates(templatesText)
448
                    .then(
449
                      whereKeys => {
450
                        this._whereKeys = whereKeys
451
                        this._slugs = cmsTemplates.template.getAbeSlugFromTemplates(
452
                          templatesText
453
                        )
454
                        this._precontribution = cmsTemplates.template.getAbePrecontribFromTemplates(
455
                          templatesText
456
                        )
457
                        this.updateList()
458
                        resolve()
459
                      },
460
                      e => {
461
                        console.log(
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
462
                          'Reject: Manager.findRequestColumns',
463
                          e.stack
464
                        )
465
                      }
466
                    )
467
                    .catch(e => {
468
                      console.log('Error: Manager.findRequestColumns', e.stack)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
469
                    })
470
                },
471
                e => {
472
                  console.log('Reject: Manager.getTemplatesTexts', e.stack)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
473
                }
474
              )
475
              .catch(e => {
476
                console.log('Error: Manager.getTemplatesTexts', e.stack)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
477
              })
478
          },
479
          e => {
480
            console.log('Manager.getKeysFromSelect', e.stack)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
481
          }
482
        )
483
        .catch(e => {
484
          console.log('Manager.getKeysFromSelect', e.stack)
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
485
        })
486
    })
487
488
    return p
489
  }
490
491
  getStructureAndTemplates() {
492
    return this._structureAndTemplates
493
  }
494
495
  updateStructureAndTemplates() {
496
    this._structureAndTemplates = cmsTemplates.template.getStructureAndTemplates()
497
  }
498
499
  getThumbsList() {
500
    if (typeof this._thumbs === 'undefined' || this._thumbs === null)
501
      this._thumbs = cmsMedia.image.getThumbsList()
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...
502
    return this._thumbs
503
  }
504
505
  addThumbsToList(thumb) {
506
    if (this._thumbs) this._thumbs.push(thumb)
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...
507
  }
508
509
  getReferences() {
510
    if (typeof this._references === 'undefined' || this._references === null)
511
      this.updateReferences()
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...
512
    return this._references
513
  }
514
515
  getPrecontribution() {
516
    return this._precontribution
517
  }
518
519
  getSlugs() {
520
    return this._slugs
521
  }
522
523
  updateReferences(referenceName) {
524
    var references = cmsReference.reference.getFiles()
525
    if (referenceName && references[referenceName])
526
      this._references[referenceName] = references[referenceName]
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...
527
    else this._references = references
528
529
    return this
530
  }
531
532
  getList() {
533
    return this._list
534
  }
535
536
  getListWithStatusOnFolder(status, folder = '') {
537
    var list = []
538
    folder = path.join(Manager.instance.pathData, folder)
539
    Array.prototype.forEach.call(this._list, file => {
540
      if (
541
        typeof file[status] !== 'undefined' &&
542
        file[status] !== null &&
543
        file.path.indexOf(folder) > -1
544
      ) {
545
        list.push(file)
546
      }
547
    })
548
549
    return list
550
  }
551
552
  setList(list) {
553
    this._list = list
554
555
    return this
556
  }
557
558
  /**
559
   * return true if postUrl is found in the Manager list
560
   * @param {String} postUrl The url path of the file
561
   */
562
  postExist(postUrl) {
563
    const docPath = cmsData.utils.getDocPathFromPostUrl(postUrl)
564
    const found = coreUtils.array.find(this._list, 'path', docPath)
565
566
    if (found.length > 0) {
567
      return true
568
    }
569
    return false
570
  }
571
572
  /**
573
   * When a post is modified or created, this method is called so that the manager updates the list with the updated/new item
574
   * @param {String} revisionPath The full path to the post
575
   */
576
  updatePostInList(revisionPath) {
577
    const docPath = cmsData.utils.getDocPath(revisionPath)
578
    const found = coreUtils.array.find(this._list, 'path', docPath)
579
    const json = cmsData.file.get(revisionPath)
580
    let index
581
    let merged = {}
582
    let revision = cmsData.file.getFileObject(revisionPath)
583
    revision = cmsData.file.getAbeMeta(revision, json)
584
    Array.prototype.forEach.call(this._whereKeys, key => {
585
      var keyFirst = key.split('.')[0]
586
      revision[keyFirst] = json[keyFirst]
587
    })
588
589
    if (found.length > 0) {
590
      index = found[0]
591
      merged[docPath] = this._list[index]
592
      // If I publish, I remove the previous published versions
593
      if (revision.abe_meta.status === 'publish') {
594
        Array.prototype.forEach.call(
595
          merged[docPath].revisions,
596
          (revision, revIndex) => {
597
            if (revision.abe_meta.status === 'publish') {
598
              merged[docPath].revisions.splice(revIndex, 1)
599
            }
600
          }
601
        )
602
      }
603
      merged[docPath].revisions.push(JSON.parse(JSON.stringify(revision)))
604
      const sortedResult = cmsData.revision.sortRevisions(merged)
605
      // Does the publish version has been removed (in the case of unpublish) ?
606
      if (
607
        sortedResult[0]['publish'] &&
608
        !coreUtils.file.exist(sortedResult[0]['publish']['path'])
609
      ) {
610
        delete sortedResult[0]['publish']
611
      }
612
      this._list[index] = sortedResult[0]
613
    } else {
614
      index = this._list.length
615
      let rev = []
616
      rev.push(revision)
617
      merged = cmsData.revision.mergeRevisions(rev)
618
      const sortedResult = cmsData.revision.sortRevisions(merged)
619
      this._list.push(sortedResult[0])
620
    }
621
622
    this._list.sort(coreUtils.sort.predicatBy('date', -1))
623
    this.historize(index)
624
  }
625
626
  /**
627
   * When data.history is set, we do keep the number of revisions = history in the most recent date order
628
   * @param  {[type]} index [description]
629
   * @return {[type]}       [description]
630
   */
631
  historize(index) {
632
    if (config.data.history && config.data.history > 0) {
633
      let arStatus = []
634
      if (this._list[index].revisions.length > config.data.history) {
635
        Array.prototype.forEach.call(
636
          this._list[index].revisions,
637
          (revision, revIndex) => {
638
            if (revIndex >= config.data.history) {
639
              if (revision.abe_meta.status === 'publish') {
640
                if (arStatus.indexOf(revision.abe_meta.status) < 0) {
641
                  arStatus.push(revision.abe_meta.status)
642
                } else {
643
                  this._list[index].revisions.splice(revIndex, 1)
644
                }
645
              } else {
646
                this._list[index].revisions.splice(revIndex, 1)
647
                cmsOperations.remove.removeFile(revision.path)
648
              }
649
            } else if (arStatus.indexOf(revision.abe_meta.status) < 0) {
650
              arStatus.push(revision.abe_meta.status)
651
            }
652
          }
653
        )
654
      }
655
    }
656
  }
657
658
  /**
659
   * When a post is deleted, this method is called so that the manager updates the list with the removed item
660
   * @param {String} postUrl The URL of the post
661
   */
662
  removePostFromList(postUrl) {
663
    const docPath = cmsData.utils.getDocPathFromPostUrl(postUrl)
664
    this._list = coreUtils.array.removeByAttr(this._list, 'path', docPath)
665
  }
666
667
  /**
668
   * This method loads all posts into an array with values used in "select" statements from templates
669
   * + abe_meta data
670
   * @return {Array} Array of objects representing the posts including their revisions
671
   */
672
  updateList() {
673
    this._list = cmsData.file.getAllWithKeys(this._whereKeys)
674
    this._list.sort(coreUtils.sort.predicatBy('date', -1))
675
    console.log('Manager updated')
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
676
  }
677
678
  getPage(
679
    start = 0,
680
    length = 20,
681
    sortField = 'date',
682
    sortDir = -1,
683
    search = '',
684
    searchFields = ['abe_meta.link', 'abe_meta.template', 'name']
685
  ) {
686
    const total = this._list.length
687
    let totalFiltered = total
688
    let list = this._list.slice()
689
690
    if (search !== '') {
691
      const searches = search.split(' ')
692
      for (var i = 0; i < searches.length; i++) {
693
        list = coreUtils.array.facet(list, searchFields, searches[i])
694
      }
695
696
      totalFiltered = list.length
697
    }
698
699
    if (sortField != 'date' || sortDir != -1) {
700
      list.sort(coreUtils.sort.predicatBy(sortField, sortDir))
701
    }
702
703
    list = list.slice(start, start + length)
704
705
    return {
706
      recordsTotal: total,
707
      recordsFiltered: totalFiltered,
708
      data: list
709
    }
710
  }
711
712
  addProcess(name) {
713
    this._processesRunning[name] = true
714
  }
715
716
  removeProcess(name) {
717
    delete this._processesRunning[name]
718
  }
719
720
  isProcessRunning(name) {
721
    if (
722
      this._processesRunning[name] !== null &&
723
      this._processesRunning[name] === true
724
    ) {
725
      return true
726
    } else {
727
      return false
728
    }
729
  }
730
731
  getActivities() {
732
    return this.activities
733
  }
734
735
  addActivity(activity) {
736
    if (this.activities.length >= 50) this.activities.shift()
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...
737
738
    this.activities.push(activity)
739
  }
740
741
  getConnections() {
742
    return this.connections
743
  }
744
745
  addConnection(res) {
746
    this.connections.push(res)
747
  }
748
749
  removeConnection(res) {
750
    var i = this.connections.indexOf(res)
751
    if (i !== -1) {
752
      this.connections.splice(i, 1)
753
    }
754
  }
755
}
756
757
export default Manager
758