php_process 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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"
|