-
Notifications
You must be signed in to change notification settings - Fork 8
/
index.js
88 lines (71 loc) · 2.34 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* Execute PHP function within NodeJS application
* @package exec-php
* @version 0.0.6
*/
let fs = require('fs'),
path = require('path'),
cli = require('./lib/cli.js'),
exec = require('child_process').exec
/**
* Create exec-php object that contain user php functions.
* @param {string} file, Path to user php file.
* @param {string} bin, Path to php bin file.
* @param {function} callback, Callback function.
* @arg {mixed} error message.
* @arg {object} methods Collection of user php functions.
* @arg {string} printed string on requiring user php file.
*/
module.exports = (file, bin, callback) => {
if (!callback) {
if (typeof bin === 'function') {
callback = bin
bin = null
} else {
callback = function() {}
}
}
if (!bin) {
bin = 'php'
}
let absFile = file
let tmpPath = process.cwd()
let tmpParents = Object.values(require.cache)
.filter(m => {
if (!m.children || !m.children.length)
return
return m.children.includes(module)
})
if (tmpParents && tmpParents.length)
tmpPath = tmpParents[0].path
absFile = path.resolve(tmpPath, file)
let cacheName = `{#CACHE#}${absFile}`
if (require.cache[cacheName])
return callback.apply(this, require.cache[cacheName])
if(!fs.existsSync(absFile))
throw new Error(`File '${file}' not found.`)
let token = '{#SEPARATOR#}';
let sc = `include '${absFile}'; echo '${token}'; echo json_encode(get_defined_functions()['user']);`
let cmd = [bin, `-r "${sc}";`].join(' ')
let output = null
exec(cmd, {cwd: path.dirname(absFile)}, (err, sout, serr) => {
if (err)
return callback(err)
let souts = sout.split(token)
output = souts[0]
let funcs = JSON.parse(souts[1])
let php = {}
funcs.forEach(func => {
if (func.includes('\\'))
return
php[func] = ((file, bin, func) => {
return function() {
let args = Array.prototype.slice.call(arguments, 0)
cli.execute(file, bin, func, args)
}
})(absFile, bin, func)
})
require.cache[cacheName] = [false, php, output]
callback(false, php, output)
})
}