php_process 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/VERSION +1 -1
- data/examples/example_phpexcel.rb +1 -1
- data/lib/php_process.rb +18 -8
- data/lib/php_script.php +23 -2
- data/php_process.gemspec +8 -5
- data/spec/php_process_spec.rb +13 -2
- metadata +27 -16
data/Gemfile
CHANGED
@@ -2,8 +2,9 @@ source "http://rubygems.org"
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
# gem "activesupport", ">= 2.3.5"
|
5
|
-
gem "knjrbfw", ">= 0.0.31"
|
6
5
|
gem "php-serialize4ruby"
|
6
|
+
gem "wref"
|
7
|
+
gem "tsafe"
|
7
8
|
|
8
9
|
# Add dependencies to develop your gem here.
|
9
10
|
# Include everything needed to run rake, tests, features, etc.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
@@ -23,7 +23,7 @@ objPHPExcel.getProperties.setDescription("Test document for Office 2007 XLSX, ge
|
|
23
23
|
|
24
24
|
#Add some data
|
25
25
|
print "#{Time.now} Add some data\n"
|
26
|
-
objPHPExcel.setActiveSheetIndex(0)
|
26
|
+
objPHPExcel.setActiveSheetIndex(0)
|
27
27
|
objPHPExcel.getActiveSheet.SetCellValue('A1', 'Hello')
|
28
28
|
objPHPExcel.getActiveSheet.SetCellValue('B2', 'world!')
|
29
29
|
objPHPExcel.getActiveSheet.SetCellValue('C1', 'Hello')
|
data/lib/php_process.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require "
|
2
|
-
require "
|
3
|
-
require "base64"
|
1
|
+
require "wref"
|
2
|
+
require "tsafe"
|
4
3
|
require "php-serialize4ruby"
|
4
|
+
require "base64"
|
5
5
|
require "open3"
|
6
6
|
|
7
7
|
#This class starts a PHP-process and proxies various calls to it. It also spawns proxy-objects, which can you can call like they were normal Ruby-objects.
|
@@ -32,10 +32,14 @@ class Php_process
|
|
32
32
|
@args = args
|
33
33
|
@debug = @args[:debug]
|
34
34
|
@send_count = 0
|
35
|
-
|
36
|
-
@
|
37
|
-
|
38
|
-
@
|
35
|
+
|
36
|
+
@responses = Tsafe::MonHash.new
|
37
|
+
|
38
|
+
@object_ids = Tsafe::MonHash.new
|
39
|
+
@object_unset_ids = Tsafe::MonArray.new
|
40
|
+
@objects = Wref_map.new
|
41
|
+
|
42
|
+
@constant_val_cache = Tsafe::MonHash.new
|
39
43
|
|
40
44
|
#Used for 'create_func'.
|
41
45
|
@callbacks = {}
|
@@ -234,7 +238,13 @@ class Php_process
|
|
234
238
|
|
235
239
|
#Returns the value of a constant on the PHP-side.
|
236
240
|
def constant_val(name)
|
237
|
-
|
241
|
+
const_name = name.to_s
|
242
|
+
|
243
|
+
if !@constant_val_cache.key?(const_name)
|
244
|
+
@constant_val_cache[const_name] = self.send(:type => :constant_val, :name => name)
|
245
|
+
end
|
246
|
+
|
247
|
+
return @constant_val_cache[const_name]
|
238
248
|
end
|
239
249
|
|
240
250
|
#Returns various informations about boths sides memory in a hash.
|
data/lib/php_script.php
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
#!/usr/bin/env php5
|
2
2
|
<?php
|
3
3
|
|
4
|
+
//Controls the PHP-process on the PHP-side.
|
4
5
|
class php_process{
|
6
|
+
//Opens stdin and stdout for processing. Sets various helper-variables.
|
5
7
|
function __construct(){
|
6
8
|
$this->sock_stdin = fopen("php://stdin", "r");
|
7
9
|
$this->sock_stdout = fopen("php://stdout", "w");
|
@@ -10,11 +12,13 @@ class php_process{
|
|
10
12
|
$this->objects_count = 0;
|
11
13
|
$this->created_functions = array();
|
12
14
|
$this->proxy_to_func = array("call_created_func", "constant_val", "create_func", "func", "get_var", "memory_info", "object_cache_info", "object_call", "require_once_path", "set_var", "static_method_call", "unset_ids");
|
15
|
+
$this->func_specials = array("constant", "define", "die", "exit", "require", "require_once", "include", "include_once");
|
13
16
|
$this->send_count = 0;
|
14
17
|
|
15
18
|
print "php_script_ready:" . getmypid() . "\n";
|
16
19
|
}
|
17
20
|
|
21
|
+
//Starts listening in stdin for new instructions. Calls 'handle_line' for every line gotten.
|
18
22
|
function start_listening(){
|
19
23
|
while(true){
|
20
24
|
$line = fgets($this->sock_stdin, 1048576);
|
@@ -22,6 +26,7 @@ class php_process{
|
|
22
26
|
}
|
23
27
|
}
|
24
28
|
|
29
|
+
//Writes the given data to stdout. Serializes and encodes it as well and increases the 'send_count'-variable.
|
25
30
|
function send($data){
|
26
31
|
$id = $this->send_count;
|
27
32
|
$this->send_count++;
|
@@ -33,6 +38,7 @@ class php_process{
|
|
33
38
|
//return $this->read_answer($id);
|
34
39
|
}
|
35
40
|
|
41
|
+
//Handles the given instruction. It parses it and then calls the relevant method.
|
36
42
|
function handle_line($line){
|
37
43
|
$data = explode(":", $line);
|
38
44
|
$type = $data[0];
|
@@ -62,6 +68,7 @@ class php_process{
|
|
62
68
|
}
|
63
69
|
}
|
64
70
|
|
71
|
+
//Parses objects into special arrays, which again will be turned into proxy-objects on the Ruby-side. Recursivly scans arrays to do the same.
|
65
72
|
function parse_data($data){
|
66
73
|
if (is_array($data)){
|
67
74
|
foreach($data as $key => $val){
|
@@ -95,6 +102,7 @@ class php_process{
|
|
95
102
|
}
|
96
103
|
}
|
97
104
|
|
105
|
+
//Recursivly read the given data from the Ruby-side. Changing special arrays into the objects they refer to.
|
98
106
|
function read_parsed_data($data){
|
99
107
|
if (is_array($data) and array_key_exists("type", $data) and $data["type"] == "proxyobj" and array_key_exists("id", $data)){
|
100
108
|
$object = $this->objects[$data["id"]]["obj"];
|
@@ -117,12 +125,14 @@ class php_process{
|
|
117
125
|
}
|
118
126
|
}
|
119
127
|
|
128
|
+
//Answers a request ID with the given data. Writes it to stdout.
|
120
129
|
function answer($id, $data){
|
121
130
|
if (!fwrite($this->sock_stdout, "answer:" . $id . ":" . base64_encode(serialize($this->parse_data($data))) . "\n")){
|
122
131
|
throw new exception("Could not write to socket.");
|
123
132
|
}
|
124
133
|
}
|
125
134
|
|
135
|
+
//Ruby wants spawn an object. Cache it and return (Ruby will tell us when to unset it automatically).
|
126
136
|
function new_object($id, $args){
|
127
137
|
$class = $args["class"];
|
128
138
|
$new_args = $this->read_parsed_data($args["args"]);
|
@@ -133,6 +143,7 @@ class php_process{
|
|
133
143
|
$this->answer($id, $object);
|
134
144
|
}
|
135
145
|
|
146
|
+
//Ruby wants to set an instance variable on an object. Do that and answer with 'true'.
|
136
147
|
function set_var($id, $args){
|
137
148
|
$object = $this->objects[$args["id"]]["obj"];
|
138
149
|
if (!$object){
|
@@ -143,6 +154,7 @@ class php_process{
|
|
143
154
|
$this->answer($id, true);
|
144
155
|
}
|
145
156
|
|
157
|
+
//Ruby wants to read an instance variable on an object. Return the variable's value.
|
146
158
|
function get_var($id, $args){
|
147
159
|
$object = $this->objects[$args["id"]]["obj"];
|
148
160
|
if (!$object){
|
@@ -152,6 +164,7 @@ class php_process{
|
|
152
164
|
$this->answer($id, $object->$args["name"]);
|
153
165
|
}
|
154
166
|
|
167
|
+
//Ruby wants to call a method on an object. Do that and return the result.
|
155
168
|
function object_call($id, $args){
|
156
169
|
if (!array_key_exists($args["id"], $this->objects)){
|
157
170
|
throw new exception("No object by that ID: " . $args["id"]);
|
@@ -173,12 +186,12 @@ class php_process{
|
|
173
186
|
$this->answer($id, $res);
|
174
187
|
}
|
175
188
|
|
189
|
+
//Ruby wants to call a function. Do that and return the result.
|
176
190
|
function func($id, $args){
|
177
191
|
//These functions cant be called normally. Hack them with eval instead.
|
178
|
-
$specials = array("die", "exit", "require", "require_once", "include", "include_once");
|
179
192
|
$newargs = $this->read_parsed_data($args["args"]);
|
180
193
|
|
181
|
-
if (in_array($args["func_name"], $
|
194
|
+
if (in_array($args["func_name"], $this->func_specials)){
|
182
195
|
$eval_str = $args["func_name"] . "(";
|
183
196
|
$count = 0;
|
184
197
|
foreach($newargs as $key => $val){
|
@@ -203,6 +216,7 @@ class php_process{
|
|
203
216
|
$this->answer($id, $res);
|
204
217
|
}
|
205
218
|
|
219
|
+
//Ruby has given us various object-IDs to unset. Unset them from cache and return 'true'.
|
206
220
|
function unset_ids($id, $args){
|
207
221
|
foreach($args["ids"] as $obj_id){
|
208
222
|
if (!array_key_exists($obj_id, $this->objects)){
|
@@ -222,6 +236,7 @@ class php_process{
|
|
222
236
|
$this->answer($id, true);
|
223
237
|
}
|
224
238
|
|
239
|
+
//Ruby wants information about the object-cache on the PHP-side. Return that in an array.
|
225
240
|
function object_cache_info($id, $args){
|
226
241
|
$types = array();
|
227
242
|
foreach($this->objects as $key => $val){
|
@@ -238,6 +253,7 @@ class php_process{
|
|
238
253
|
));
|
239
254
|
}
|
240
255
|
|
256
|
+
//Ruby wants to call a static method. Answers with the result.
|
241
257
|
function static_method_call($id, $args){
|
242
258
|
$call_arr = array($args["class_name"], $args["method_name"]);
|
243
259
|
|
@@ -255,6 +271,7 @@ class php_process{
|
|
255
271
|
$this->answer($id, $res);
|
256
272
|
}
|
257
273
|
|
274
|
+
//Creates a function which can be used for callbacks on the Ruby-side.
|
258
275
|
function create_func($id, $args){
|
259
276
|
$cb_id = $args["callback_id"];
|
260
277
|
$func = create_function("", "global \$php_process; \$php_process->call_back_created_func(" . $cb_id . ", func_get_args());");
|
@@ -266,6 +283,7 @@ class php_process{
|
|
266
283
|
$this->answer($id, true);
|
267
284
|
}
|
268
285
|
|
286
|
+
//This function is called, when a create-function is called. It then callbacks to Ruby, where a 'Proc' will be executed.
|
269
287
|
function call_back_created_func($func_id, $args){
|
270
288
|
$this->send(array(
|
271
289
|
"type" => "call_back_created_func",
|
@@ -274,6 +292,7 @@ class php_process{
|
|
274
292
|
));
|
275
293
|
}
|
276
294
|
|
295
|
+
//Ruby wants to call a created function. Pretty much just executes that function. This is useually done for debugging callbacks.
|
277
296
|
function call_created_func($id, $args){
|
278
297
|
$func = $this->created_functions[$args["id"]]["func"];
|
279
298
|
if (!$func){
|
@@ -297,10 +316,12 @@ class php_process{
|
|
297
316
|
$this->answer($id, $res);
|
298
317
|
}
|
299
318
|
|
319
|
+
//Ruby wants to read a constant. This is not done by 'func', because of keeping caching posibility open and not wanting to eval.
|
300
320
|
function constant_val($id, $args){
|
301
321
|
$this->answer($id, constant($args["name"]));
|
302
322
|
}
|
303
323
|
|
324
|
+
//Returns various information about the object-cache.
|
304
325
|
function memory_info($id, $args){
|
305
326
|
$this->answer($id, array(
|
306
327
|
"objects" => count($this->objects),
|
data/php_process.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{php_process}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kasper Johansen"]
|
12
|
-
s.date = %q{2012-05-
|
12
|
+
s.date = %q{2012-05-22}
|
13
13
|
s.description = %q{Spawns a PHP process and proxies calls to it, making it possible to proxy objects and more.}
|
14
14
|
s.email = %q{k@spernj.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -41,16 +41,18 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.specification_version = 3
|
42
42
|
|
43
43
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
|
-
s.add_runtime_dependency(%q<knjrbfw>, [">= 0.0.31"])
|
45
44
|
s.add_runtime_dependency(%q<php-serialize4ruby>, [">= 0"])
|
45
|
+
s.add_runtime_dependency(%q<wref>, [">= 0"])
|
46
|
+
s.add_runtime_dependency(%q<tsafe>, [">= 0"])
|
46
47
|
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
47
48
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
48
49
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
49
50
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
50
51
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
51
52
|
else
|
52
|
-
s.add_dependency(%q<knjrbfw>, [">= 0.0.31"])
|
53
53
|
s.add_dependency(%q<php-serialize4ruby>, [">= 0"])
|
54
|
+
s.add_dependency(%q<wref>, [">= 0"])
|
55
|
+
s.add_dependency(%q<tsafe>, [">= 0"])
|
54
56
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
55
57
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
56
58
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
@@ -58,8 +60,9 @@ Gem::Specification.new do |s|
|
|
58
60
|
s.add_dependency(%q<rcov>, [">= 0"])
|
59
61
|
end
|
60
62
|
else
|
61
|
-
s.add_dependency(%q<knjrbfw>, [">= 0.0.31"])
|
62
63
|
s.add_dependency(%q<php-serialize4ruby>, [">= 0"])
|
64
|
+
s.add_dependency(%q<wref>, [">= 0"])
|
65
|
+
s.add_dependency(%q<tsafe>, [">= 0"])
|
63
66
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
64
67
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
65
68
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
data/spec/php_process_spec.rb
CHANGED
@@ -11,6 +11,18 @@ describe "PhpProcess" do
|
|
11
11
|
$php = Php_process.new(:debug => false, :debug_stderr => true)
|
12
12
|
|
13
13
|
|
14
|
+
#It should be able to handle constants very fast by using cache.
|
15
|
+
$php.func("define", "TEST_CONSTANT", 5)
|
16
|
+
raise "Expected 'TEST_CONSTANT'-constant to exist but it didnt." if !$php.func("defined", "TEST_CONSTANT")
|
17
|
+
|
18
|
+
Timeout.timeout(1) do
|
19
|
+
0.upto(10000) do
|
20
|
+
const = $php.constant_val("TEST_CONSTANT")
|
21
|
+
raise "Expected const to be 5 but it wasnt: #{const}." if const != 5
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
14
26
|
#Test function calls without arguments.
|
15
27
|
pid = $php.func("getmypid")
|
16
28
|
raise "Invalid PID: #{pid}" if pid.to_i <= 0
|
@@ -73,8 +85,7 @@ describe "PhpProcess" do
|
|
73
85
|
tw.close
|
74
86
|
tw = nil
|
75
87
|
|
76
|
-
|
77
|
-
|
88
|
+
|
78
89
|
#Test PHPExcel.
|
79
90
|
$php.func("require_once", "PHPExcel.php")
|
80
91
|
tw = $php.new("knj_table_writer", {
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: php_process
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Kasper Johansen
|
@@ -10,22 +10,22 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-05-
|
13
|
+
date: 2012-05-22 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
17
|
+
name: php-serialize4ruby
|
18
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0
|
23
|
+
version: "0"
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: wref
|
29
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
@@ -36,8 +36,19 @@ dependencies:
|
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
39
|
+
name: tsafe
|
40
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
41
52
|
none: false
|
42
53
|
requirements:
|
43
54
|
- - ~>
|
@@ -45,10 +56,10 @@ dependencies:
|
|
45
56
|
version: 2.8.0
|
46
57
|
type: :development
|
47
58
|
prerelease: false
|
48
|
-
version_requirements: *
|
59
|
+
version_requirements: *id004
|
49
60
|
- !ruby/object:Gem::Dependency
|
50
61
|
name: rdoc
|
51
|
-
requirement: &
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
52
63
|
none: false
|
53
64
|
requirements:
|
54
65
|
- - ~>
|
@@ -56,10 +67,10 @@ dependencies:
|
|
56
67
|
version: "3.12"
|
57
68
|
type: :development
|
58
69
|
prerelease: false
|
59
|
-
version_requirements: *
|
70
|
+
version_requirements: *id005
|
60
71
|
- !ruby/object:Gem::Dependency
|
61
72
|
name: bundler
|
62
|
-
requirement: &
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
63
74
|
none: false
|
64
75
|
requirements:
|
65
76
|
- - ">="
|
@@ -67,10 +78,10 @@ dependencies:
|
|
67
78
|
version: 1.0.0
|
68
79
|
type: :development
|
69
80
|
prerelease: false
|
70
|
-
version_requirements: *
|
81
|
+
version_requirements: *id006
|
71
82
|
- !ruby/object:Gem::Dependency
|
72
83
|
name: jeweler
|
73
|
-
requirement: &
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
74
85
|
none: false
|
75
86
|
requirements:
|
76
87
|
- - ~>
|
@@ -78,10 +89,10 @@ dependencies:
|
|
78
89
|
version: 1.8.3
|
79
90
|
type: :development
|
80
91
|
prerelease: false
|
81
|
-
version_requirements: *
|
92
|
+
version_requirements: *id007
|
82
93
|
- !ruby/object:Gem::Dependency
|
83
94
|
name: rcov
|
84
|
-
requirement: &
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
85
96
|
none: false
|
86
97
|
requirements:
|
87
98
|
- - ">="
|
@@ -89,7 +100,7 @@ dependencies:
|
|
89
100
|
version: "0"
|
90
101
|
type: :development
|
91
102
|
prerelease: false
|
92
|
-
version_requirements: *
|
103
|
+
version_requirements: *id008
|
93
104
|
description: Spawns a PHP process and proxies calls to it, making it possible to proxy objects and more.
|
94
105
|
email: k@spernj.org
|
95
106
|
executables: []
|
@@ -127,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
138
|
requirements:
|
128
139
|
- - ">="
|
129
140
|
- !ruby/object:Gem::Version
|
130
|
-
hash:
|
141
|
+
hash: 537427075948440521
|
131
142
|
segments:
|
132
143
|
- 0
|
133
144
|
version: "0"
|