| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | const path = require('path'); | 
					
						
							|  |  |  | const semver = require('semver'); | 
					
						
							|  |  |  | const async = require('async'); | 
					
						
							|  |  |  | const winston = require('winston'); | 
					
						
							|  |  |  | const nconf = require('nconf'); | 
					
						
							|  |  |  | const _ = require('lodash'); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | const meta = require('../meta'); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | module.exports = function (Plugins) { | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 	async function registerPluginAssets(pluginData, fields) { | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 		function add(dest, arr) { | 
					
						
							|  |  |  | 			dest.push.apply(dest, arr || []); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		const handlers = { | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 			staticDirs: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getStaticDirectories(pluginData, next); | 
					
						
							| 
									
										
										
										
											2016-11-19 14:24:37 -05:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 			cssFiles: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getFiles(pluginData, 'css', next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			lessFiles: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getFiles(pluginData, 'less', next); | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-08-21 17:48:58 -04:00
										 |  |  | 			acpLessFiles: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getFiles(pluginData, 'acpLess', next); | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 			clientScripts: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getScripts(pluginData, 'client', next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			acpScripts: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getScripts(pluginData, 'acp', next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			modules: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getModules(pluginData, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			soundpack: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getSoundpack(pluginData, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-05-23 21:55:23 -06:00
										 |  |  | 			languageData: function (next) { | 
					
						
							|  |  |  | 				Plugins.data.getLanguageData(pluginData, next); | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		var methods = {}; | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 		if (Array.isArray(fields)) { | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 			fields.forEach(function (field) { | 
					
						
							|  |  |  | 				methods[field] = handlers[field]; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			methods = handlers; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-11-19 14:24:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		const results = await async.parallel(methods); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Object.assign(Plugins.staticDirs, results.staticDirs || {}); | 
					
						
							|  |  |  | 		add(Plugins.cssFiles, results.cssFiles); | 
					
						
							|  |  |  | 		add(Plugins.lessFiles, results.lessFiles); | 
					
						
							|  |  |  | 		add(Plugins.acpLessFiles, results.acpLessFiles); | 
					
						
							|  |  |  | 		add(Plugins.clientScripts, results.clientScripts); | 
					
						
							|  |  |  | 		add(Plugins.acpScripts, results.acpScripts); | 
					
						
							|  |  |  | 		Object.assign(meta.js.scripts.modules, results.modules || {}); | 
					
						
							|  |  |  | 		if (results.soundpack) { | 
					
						
							|  |  |  | 			Plugins.soundpacks.push(results.soundpack); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (results.languageData) { | 
					
						
							|  |  |  | 			Plugins.languageData.languages = _.union(Plugins.languageData.languages, results.languageData.languages); | 
					
						
							|  |  |  | 			Plugins.languageData.namespaces = _.union(Plugins.languageData.namespaces, results.languageData.namespaces); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Plugins.pluginsData[pluginData.id] = pluginData; | 
					
						
							| 
									
										
										
										
											2017-05-17 17:25:41 -06:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-19 14:24:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 	Plugins.prepareForBuild = async function (targets) { | 
					
						
							|  |  |  | 		const map = { | 
					
						
							| 
									
										
										
										
											2017-05-18 01:32:20 -06:00
										 |  |  | 			'plugin static dirs': ['staticDirs'], | 
					
						
							|  |  |  | 			'requirejs modules': ['modules'], | 
					
						
							|  |  |  | 			'client js bundle': ['clientScripts'], | 
					
						
							|  |  |  | 			'admin js bundle': ['acpScripts'], | 
					
						
							|  |  |  | 			'client side styles': ['cssFiles', 'lessFiles'], | 
					
						
							| 
									
										
										
										
											2017-08-21 17:48:58 -04:00
										 |  |  | 			'admin control panel styles': ['cssFiles', 'lessFiles', 'acpLessFiles'], | 
					
						
							| 
									
										
										
										
											2017-05-18 01:32:20 -06:00
										 |  |  | 			sounds: ['soundpack'], | 
					
						
							| 
									
										
										
										
											2017-05-23 21:55:23 -06:00
										 |  |  | 			languages: ['languageData'], | 
					
						
							| 
									
										
										
										
											2017-05-18 01:32:20 -06:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		const fields = _.uniq(_.flatMap(targets, target => map[target] || [])); | 
					
						
							| 
									
										
										
										
											2019-01-12 12:28:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// clear old data before build
 | 
					
						
							| 
									
										
										
										
											2019-08-13 14:33:37 -04:00
										 |  |  | 		fields.forEach(field => { | 
					
						
							| 
									
										
										
										
											2019-01-12 12:28:53 -07:00
										 |  |  | 			switch (field) { | 
					
						
							|  |  |  | 			case 'clientScripts': | 
					
						
							|  |  |  | 			case 'acpScripts': | 
					
						
							|  |  |  | 			case 'cssFiles': | 
					
						
							|  |  |  | 			case 'lessFiles': | 
					
						
							|  |  |  | 			case 'acpLessFiles': | 
					
						
							|  |  |  | 				Plugins[field].length = 0; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case 'soundpack': | 
					
						
							|  |  |  | 				Plugins.soundpacks.length = 0; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case 'languageData': | 
					
						
							|  |  |  | 				Plugins.languageData.languages = []; | 
					
						
							|  |  |  | 				Plugins.languageData.namespaces = []; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			// do nothing for modules and staticDirs
 | 
					
						
							| 
									
										
										
										
											2017-05-18 01:32:20 -06:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		winston.verbose('[plugins] loading the following fields from plugin data: ' + fields.join(', ')); | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		const plugins = await Plugins.data.getActive(); | 
					
						
							|  |  |  | 		await Promise.all(plugins.map(p => registerPluginAssets(p, fields))); | 
					
						
							| 
									
										
										
										
											2016-11-19 14:24:37 -05:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 	const themeNamePattern = /(@.*?\/)?nodebb-theme-.*$/; | 
					
						
							| 
									
										
										
										
											2018-06-09 16:26:28 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 	Plugins.loadPlugin = async function (pluginPath) { | 
					
						
							|  |  |  | 		let pluginData; | 
					
						
							|  |  |  | 		try { | 
					
						
							|  |  |  | 			pluginData = await Plugins.data.loadPluginInfo(pluginPath); | 
					
						
							|  |  |  | 		} catch (err) { | 
					
						
							|  |  |  | 			if (err.message === '[[error:parse-error]]') { | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!themeNamePattern.test(pluginPath)) { | 
					
						
							|  |  |  | 				throw err; | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		checkVersion(pluginData); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		try { | 
					
						
							|  |  |  | 			registerHooks(pluginData); | 
					
						
							|  |  |  | 			await registerPluginAssets(pluginData, ['soundpack']); | 
					
						
							|  |  |  | 		} catch (err) { | 
					
						
							|  |  |  | 			winston.error(err.stack); | 
					
						
							|  |  |  | 			winston.verbose('[plugins] Could not load plugin : ' + pluginData.id); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!pluginData.private) { | 
					
						
							|  |  |  | 			Plugins.loadedPlugins.push({ | 
					
						
							|  |  |  | 				id: pluginData.id, | 
					
						
							|  |  |  | 				version: pluginData.version, | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		winston.verbose('[plugins] Loaded plugin: ' + pluginData.id); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-20 11:01:59 -04:00
										 |  |  | 	function checkVersion(pluginData) { | 
					
						
							|  |  |  | 		function add() { | 
					
						
							| 
									
										
										
										
											2018-10-20 14:40:48 -04:00
										 |  |  | 			if (!Plugins.versionWarning.includes(pluginData.id)) { | 
					
						
							| 
									
										
										
										
											2015-08-20 11:01:59 -04:00
										 |  |  | 				Plugins.versionWarning.push(pluginData.id); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-07 00:59:03 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (pluginData.nbbpm && pluginData.nbbpm.compatibility && semver.validRange(pluginData.nbbpm.compatibility)) { | 
					
						
							| 
									
										
										
										
											2015-08-20 10:29:58 -04:00
										 |  |  | 			if (!semver.satisfies(nconf.get('version'), pluginData.nbbpm.compatibility)) { | 
					
						
							| 
									
										
										
										
											2015-08-20 11:01:59 -04:00
										 |  |  | 				add(); | 
					
						
							| 
									
										
										
										
											2015-03-07 00:59:03 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-08-20 11:01:59 -04:00
										 |  |  | 			add(); | 
					
						
							| 
									
										
										
										
											2015-03-07 00:59:03 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 	function registerHooks(pluginData) { | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 		if (!pluginData.library) { | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 		const libraryPath = path.join(pluginData.path, pluginData.library); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 23:24:19 -05:00
										 |  |  | 		try { | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 			if (!Plugins.libraries[pluginData.id]) { | 
					
						
							| 
									
										
										
										
											2015-01-06 23:29:48 -05:00
										 |  |  | 				Plugins.requireLibrary(pluginData.id, libraryPath); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 			if (Array.isArray(pluginData.hooks)) { | 
					
						
							|  |  |  | 				pluginData.hooks.forEach(hook => Plugins.registerHook(pluginData.id, hook)); | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-02-18 01:52:56 -07:00
										 |  |  | 		} catch (err) { | 
					
						
							| 
									
										
										
										
											2015-06-02 17:35:41 -04:00
										 |  |  | 			winston.warn('[plugins] Unable to parse library for: ' + pluginData.id); | 
					
						
							| 
									
										
										
										
											2019-07-22 00:30:47 -04:00
										 |  |  | 			throw err; | 
					
						
							| 
									
										
										
										
											2015-01-12 23:24:19 -05:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-12-26 18:54:20 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-24 17:48:04 -04:00
										 |  |  | }; |