7
7
8
8
class JsonGenerator extends AbstractGenerator
9
9
{
10
- public function getNamespace (proto \FileDescriptorProto $ proto )
10
+ /**
11
+ * Get an option from the compiler arguments or from the proto file.
12
+ *
13
+ * @param string $name
14
+ * @return string|null
15
+ */
16
+ protected function getOption ($ name )
11
17
{
12
- $ namespace = $ proto ->getPackage ();
13
- $ opts = $ proto ->getOptions ();
14
- if (isset ($ opts ['json.package ' ])) {
15
- $ namespace = $ opts ['jsonpackage ' ];
18
+ $ opt = $ this ->compiler ->getOption ($ name );
19
+
20
+ if (NULL === $ opt ) {
21
+ $ opts = $ this ->proto ->getOptions ();
22
+ if (!empty ($ opts ) && isset ($ opts ['json. ' . $ name ])) {
23
+ $ opt = $ opts ['json. ' . $ name ];
24
+ }
16
25
}
17
- if (isset ($ opts ['json.namespace ' ])) {
26
+
27
+ return $ opt ;
28
+ }
29
+
30
+
31
+ public function getNamespace (proto \FileDescriptorProto $ proto = NULL )
32
+ {
33
+ $ proto = $ proto ?: $ this ->proto ;
34
+
35
+ $ opts = $ proto ->getOptions ();
36
+ if ($ this ->compiler ->getOption ('namespace ' )) {
37
+ $ namespace = $ this ->compiler ->getOption ('namespace ' );
38
+ } else if (isset ($ opts ['json.namespace ' ])) {
18
39
$ namespace = $ opts ['json.namespace ' ];
40
+ } else if (isset ($ opts ['json.package ' ])) {
41
+ $ namespace = $ opts ['json.package ' ];
42
+ } else {
43
+ $ namespace = parent ::getNamespace ($ proto );
19
44
}
20
45
21
46
$ namespace = trim ($ namespace , '. ' );
22
47
return $ namespace ;
23
48
}
24
49
50
+
51
+ public function generate (proto \FileDescriptorProto $ proto )
52
+ {
53
+ parent ::generate ($ proto );
54
+
55
+
56
+
57
+ }
58
+
59
+ protected function buildFile (proto \FileDescriptorProto $ proto , $ fname , $ contents )
60
+ {
61
+ $ suffix = $ this ->getOption ('suffix ' ) ?: '.js ' ;
62
+ $ fname .= $ suffix ;
63
+
64
+ $ file = new \google \protobuf \compiler \CodeGeneratorResponse \File ();
65
+ $ file ->setName ($ fname );
66
+
67
+ $ s = array ();
68
+ $ s []= "// DO NOT EDIT! Generated by Protobuf-PHP protoc plugin " . Protobuf::VERSION ;
69
+ $ s []= "// Source: " . $ proto ->getName ();
70
+ $ s []= "// Date: " . gmdate ('Y-m-d H:i:s ' );
71
+ $ s []= "" ;
72
+ $ s []= "// @@protoc_insertion_point(scope_file) " ;
73
+ $ s []= "" ;
74
+ $ s []= "(function(){ " ;
75
+ $ s []= "" ;
76
+ $ s []= " /** @namespace */ " ;
77
+ $ s []= " var $ namespace = $ namespace || {}; " ;
78
+ $ s []= "" ;
79
+ $ s []= " // Make it CommonJS compatible " ;
80
+ $ s []= " if (typeof exports !== 'undefined') { " ;
81
+ $ s []= " var ProtoJson = this.ProtoJson; " ;
82
+ $ s []= " if (!ProtoJson && typeof require !== 'undefined') { " ;
83
+ $ s []= " ProtoJson = require('ProtoJson'); " ;
84
+ $ s []= " } " ;
85
+ $ s []= " $ namespace = exports; " ;
86
+ $ s []= " } else { " ;
87
+ $ s []= " this. $ namespace = $ namespace; " ;
88
+ $ s []= " } " ;
89
+ $ s []= "" ;
90
+ $ s []= $ contents ;
91
+ $ s []= "" ;
92
+ $ s []= "})(); " ;
93
+ $ s []= "" ;
94
+
95
+ $ contents = implode (PHP_EOL , $ s ) . PHP_EOL . $ contents ;
96
+ $ file ->setContent ($ contents );
97
+ return $ file ;
98
+ }
99
+
100
+ public function compileProtoFile (proto \FileDescriptorProto $ proto )
101
+ {
102
+ $ file = new \google \protobuf \compiler \CodeGeneratorResponse \File ();
103
+
104
+ $ opts = $ proto ->getOptions ();
105
+ $ name = pathinfo ($ proto ->getName (), PATHINFO_FILENAME );
106
+ $ name .= isset ($ opts ['json.suffix ' ])
107
+ ? $ opts ['json.suffix ' ]
108
+ : '.js ' ;
109
+ $ file ->setName ($ name );
110
+
111
+ $ namespace = $ this ->getNamespace ($ proto );
112
+
113
+ $ s []= "// DO NOT EDIT! Generated by Protobuf for PHP protoc plugin " . Protobuf::VERSION ;
114
+ $ s []= "// Source: " . $ proto ->getName ();
115
+ $ s []= "// Date: " . date ('Y-m-d H:i:s ' );
116
+ $ s []= "" ;
117
+
118
+ $ s []= "(function(){ " ;
119
+ $ s []= "/** @namespace */ " ;
120
+ $ s []= "var $ namespace = $ namespace || {}; " ;
121
+ $ s []= "" ;
122
+ $ s []= "// Make it CommonJS compatible " ;
123
+ $ s []= "if (typeof exports !== 'undefined') { " ;
124
+ $ s []= " var ProtoJson = this.ProtoJson; " ;
125
+ $ s []= " if (!ProtoJson && typeof require !== 'undefined') " ;
126
+ $ s []= " ProtoJson = require('ProtoJson'); " ;
127
+ $ s []= " $ namespace = exports; " ;
128
+ $ s []= "} else { " ;
129
+ $ s []= " this. $ namespace = $ namespace; " ;
130
+ $ s []= "} " ;
131
+ $ s []= "" ;
132
+
133
+
134
+ // Generate Enums
135
+ foreach ($ proto ->getEnumTypeList () as $ enum ) {
136
+ $ s []= $ this ->compileEnum ($ enum , $ namespace );
137
+ }
138
+
139
+ // Generate Messages
140
+ foreach ($ proto ->getMessageTypeList () as $ msg ) {
141
+ $ s [] = $ this ->compileMessage ($ msg , $ namespace );
142
+ }
143
+
144
+ // Collect extensions
145
+ if ($ proto ->hasExtension ()) {
146
+ foreach ($ proto ->getExtensionList () as $ field ) {
147
+ $ this ->extensions [$ field ->getExtendee ()][] = array ($ namespace , $ field );
148
+ }
149
+ }
150
+
151
+ // Dump all extensions found in this proto file
152
+ if (count ($ this ->extensions )) {
153
+ foreach ($ this ->extensions as $ extendee => $ fields ) {
154
+ foreach ($ fields as $ pair ) {
155
+ list ($ ns , $ field ) = $ pair ;
156
+ $ s []= $ this ->compileExtension ($ field , $ ns , '' );
157
+ }
158
+ }
159
+ }
160
+
161
+ $ s []= "})(); " ;
162
+
163
+ $ src = implode ("\n" , $ s );
164
+ $ file ->setContent ($ src );
165
+ return array ($ file );
166
+ }
167
+
25
168
public function compileEnum (proto \EnumDescriptorProto $ enum , $ namespace )
26
169
{
27
170
$ s []= "$ namespace. $ enum ->name = { " ;
@@ -103,73 +246,6 @@ public function compileMessage(proto\DescriptorProto $msg, $namespace)
103
246
return implode ("\n" , $ s );
104
247
}
105
248
106
- public function compileProtoFile (proto \FileDescriptorProto $ proto )
107
- {
108
- $ file = new proto \compiler \CodeGeneratorResponse \File ();
109
-
110
- $ opts = $ proto ->getOptions ();
111
- $ name = pathinfo ($ proto ->getName (), PATHINFO_FILENAME );
112
- $ name .= isset ($ opts ['json.suffix ' ])
113
- ? $ opts ['json.suffix ' ]
114
- : '.js ' ;
115
- $ file ->setName ($ name );
116
-
117
- $ namespace = $ this ->getNamespace ($ proto );
118
-
119
- $ s []= "// DO NOT EDIT! Generated by Protobuf for PHP protoc plugin " . Protobuf::VERSION ;
120
- $ s []= "// Source: " . $ proto ->getName ();
121
- $ s []= "// Date: " . date ('Y-m-d H:i:s ' );
122
- $ s []= "" ;
123
-
124
- $ s []= "(function(){ " ;
125
- $ s []= "/** @namespace */ " ;
126
- $ s []= "var $ namespace = $ namespace || {}; " ;
127
- $ s []= "" ;
128
- $ s []= "// Make it CommonJS compatible " ;
129
- $ s []= "if (typeof exports !== 'undefined') { " ;
130
- $ s []= " var ProtoJson = this.ProtoJson; " ;
131
- $ s []= " if (!ProtoJson && typeof require !== 'undefined') " ;
132
- $ s []= " ProtoJson = require('ProtoJson'); " ;
133
- $ s []= " $ namespace = exports; " ;
134
- $ s []= "} else { " ;
135
- $ s []= " this. $ namespace = $ namespace; " ;
136
- $ s []= "} " ;
137
- $ s []= "" ;
138
-
139
-
140
- // Generate Enums
141
- foreach ($ proto ->getEnumTypeList () as $ enum ) {
142
- $ s []= $ this ->compileEnum ($ enum , $ namespace );
143
- }
144
-
145
- // Generate Messages
146
- foreach ($ proto ->getMessageTypeList () as $ msg ) {
147
- $ s [] = $ this ->compileMessage ($ msg , $ namespace );
148
- }
149
-
150
- // Collect extensions
151
- if ($ proto ->hasExtension ()) {
152
- foreach ($ proto ->getExtensionList () as $ field ) {
153
- $ this ->extensions [$ field ->getExtendee ()][] = array ($ namespace , $ field );
154
- }
155
- }
156
-
157
- // Dump all extensions found in this proto file
158
- if (count ($ this ->extensions )) {
159
- foreach ($ this ->extensions as $ extendee => $ fields ) {
160
- foreach ($ fields as $ pair ) {
161
- list ($ ns , $ field ) = $ pair ;
162
- $ s []= $ this ->compileExtension ($ field , $ ns , '' );
163
- }
164
- }
165
- }
166
-
167
- $ s []= "})(); " ;
168
-
169
- $ src = implode ("\n" , $ s );
170
- $ file ->setContent ($ src );
171
- return array ($ file );
172
- }
173
249
174
250
public function generateField (proto \FieldDescriptorProto $ field )
175
251
{
@@ -179,7 +255,7 @@ public function generateField(proto\FieldDescriptorProto $field)
179
255
if (substr ($ reference , 0 , 1 ) !== '. ' ) {
180
256
throw new \RuntimeException ('Only fully qualified names are supported: ' . $ reference );
181
257
}
182
- $ reference = "' " . $ this ->normalizeReference ($ reference ) . "' " ;
258
+ $ reference = "' " . $ this ->normalizeNS ($ reference ) . "' " ;
183
259
}
184
260
185
261
$ default = 'null ' ;
@@ -192,7 +268,7 @@ public function generateField(proto\FieldDescriptorProto $field)
192
268
$ default = '" ' . addcslashes ($ field ->getDefaultValue (), '" \\' ) . '" ' ;
193
269
break ;
194
270
case Protobuf::TYPE_ENUM :
195
- $ default = $ this ->normalizeReference ($ field ->getTypeName ()) . '. ' . $ field ->getDefaultValue ();
271
+ $ default = $ this ->normalizeNS ($ field ->getTypeName ()) . '. ' . $ field ->getDefaultValue ();
196
272
break ;
197
273
default : // Numbers
198
274
$ default = $ field ->getDefaultValue ();
@@ -213,7 +289,7 @@ public function generateField(proto\FieldDescriptorProto $field)
213
289
214
290
public function generateAccessors ($ field , $ namespace )
215
291
{
216
- $ camel = $ this ->comp ->camelize (ucfirst ($ field ->getName ()));
292
+ $ camel = $ this ->compiler ->camelize (ucfirst ($ field ->getName ()));
217
293
218
294
$ s []= "/** " ;
219
295
$ s []= " * Check < $ field ->name > value " ;
@@ -316,38 +392,49 @@ public function getJsDoc(proto\FieldDescriptorProto $field)
316
392
case Protobuf::TYPE_STRING :
317
393
return 'String ' ;
318
394
case Protobuf::TYPE_MESSAGE :
319
- return $ this ->normalizeReference ($ field ->getTypeName ());
395
+ return $ this ->normalizeNS ($ field ->getTypeName ());
320
396
case Protobuf::TYPE_BYTES :
321
397
return 'String ' ;
322
398
case Protobuf::TYPE_ENUM :
323
- return 'Int ( ' . $ this ->normalizeReference ($ field ->getTypeName ()) . ') ' ;
399
+ return 'Int ( ' . $ this ->normalizeNS ($ field ->getTypeName ()) . ') ' ;
324
400
325
401
case Protobuf::TYPE_GROUP :
326
402
default :
327
403
return 'unknown ' ;
328
404
}
329
405
}
330
406
331
- public function normalizeReference ($ reference )
407
+
408
+ protected function normalizeNS ($ package )
332
409
{
333
- // Remove leading dot
334
- $ reference = ltrim ($ reference , '. ' );
335
-
336
- if (!$ this ->comp ->hasPackage ($ reference )) {
337
- $ found = false ;
338
- foreach ($ this ->comp ->getPackages () as $ package =>$ namespace ) {
339
- if (0 === strpos ($ reference , $ package .'. ' )) {
340
- $ reference = $ namespace . substr ($ reference , strlen ($ package ));
341
- $ found = true ;
342
- }
343
- }
344
- if (!$ found ) {
345
- $ this ->comp ->warning ('Non tracked package name found " ' . $ reference . '" ' );
346
- }
347
- } else {
348
- $ reference = $ this ->comp ->getPackage ($ reference );
349
- }
350
-
351
- return $ reference ;
410
+ // Remove leading dot (used in references)
411
+ $ package = ltrim ($ package , '. ' );
412
+
413
+ if ($ this ->compiler ->hasPackage ($ package )) {
414
+ return $ this ->compiler ->getPackage ($ package );
415
+ }
416
+
417
+ // Check the currently registered packages to find a root one
418
+ $ found = null ;
419
+ foreach ($ this ->compiler ->getPackages () as $ pkg =>$ ns ) {
420
+ // Keep only the longest match
421
+ if (0 === strpos ($ package , $ pkg .'. ' ) && strlen ($ found ) < strlen ($ pkg )) {
422
+ $ found = $ pkg ;
423
+ }
424
+ }
425
+
426
+ // If no matching package was found issue a warning and use the package name
427
+ if (!$ found ) {
428
+ $ this ->compiler ->warning ('Non tracked package name found " ' . $ package . '" ' );
429
+ $ namespace = $ package ;
430
+ } else {
431
+ // Complete the namespace with the remaining package
432
+ $ namespace = $ this ->compiler ->getPackage ($ found );
433
+ $ namespace .= substr ($ package , strlen ($ found ));
434
+ // Set the newly found namespace in the registry
435
+ $ this ->compiler ->setPackage ($ package , $ namespace );
436
+ }
437
+
438
+ return $ namespace ;
352
439
}
353
440
}
0 commit comments