Ethereum PHP
PHP interface to Ethereum JSON-RPC API.
generate-complex-datatypes.php
Go to the documentation of this file.
1 <?php
2 
12 require_once(__DIR__ . "/generator-commons.php");
13 
21 
22 
23 
27 define('TARGET_PATH', __DIR__ . '/../src/DataType');
28 
32 $scriptName = 'scripts/'. basename(__FILE__);
33 
34 // For Tests we can disable the file generation.
35 $shouldWriteToDisc = (isset($GLOBALS['argv'][1]) && $GLOBALS['argv'][1] === '--no-file-generation') ? false : true;
36 
37 echo "### GENERATING COMPLEX DATA TYPE CLASSES ###\n";
38 //echo "# File generated " . $conf['destination'] . "\n";
39 echo "#############################################\n";
40 
41 
42 $file_header = <<<EOF
43 <?php
54 EOF;
55 
57 
58 $limit = 100;
59 foreach ($schema['objects'] as $obj_name => $params) {
60 
61  $limit--;
62  if ($limit === 0) break;
63 
65  $useStatements = [];
66 
67  $phpClass = new PhpClass();
68 
69 
70  printMe("\n\n# $obj_name");
71 
72  // Preparing params.
73  $required = $params['__required'];
74  unset($params['__required']);
75 
80  $params = reorderParams(['params' => $params, 'required' => $required]);
81 
82  // Prepare class properties.
83 
84  $phpClass->setQualifiedName('\\Ethereum\\DataType\\' . $obj_name)
85  ->setParentClassName('EthDataType')
86  ->setDescription(array(
87  'Ethereum data type ' . $obj_name .'.',
88  '',
89  "Generated by $scriptName based on resources/ethjs-schema.json.",
90  ))
91  ->setProperties(makeProperties($params))
92  ->setUseStatements($useStatements)
93  ;
94 
95  $methods = [];
96  // Add constructor.
97  $methods[] = PhpMethod::create('__construct')
98  ->setParameters(makeConstructorParams($params))
99  ->setBody(makeConstructorContent($params));
100 
101  // Add Method getTypeArray().
102  $methods[] = PhpMethod::create('getTypeArray')
103  ->setDescription('Returns a name => type array.')
104  ->setBody(makeTypeArrayBody($params))
105  ->setStatic(true)
106  ;
107 
108  // Add Method toArray().
109  $methods[] = PhpMethod::create('toArray')
110  ->setDescription('Returns array with values.')
111  ->setBody(makeToArrayBody($params));
112 
113 
114  // Add setter functions.
115  $phpClass->setMethods($methods);
116  // $phpClass->setMethods(array_merge($methods, makeSetFunctions($params)));
117 
118  $generator = new CodeGenerator([
119  'generateScalarTypeHints' => TRUE,
120  'generateReturnTypeHints' => TRUE,
121  'enableSorting' => FALSE,
122  ]);
123  $phpClassText = $generator->generate($phpClass);
124 
125  #print $file_header . $phpClassText;
126 
127  $destination_path = TARGET_PATH . '/' . ucfirst($obj_name) . '.php';
128  echo "generated file: $destination_path \n";
129  // copy($destination_path, $destination_path . '.bak');
130  if ($shouldWriteToDisc) {
131  file_put_contents($destination_path , $file_header . $phpClassText);
132  }
133  else {
134  echo "File is not written to disc, because file generation is disabled by '--no-file-generation'\n";
135  }
136 
137 }
138 
139 
140 
141 
151 function reorderParams(Array $input)
152 {
153  $params = $input;
154  $params['params'] = [];
155  // Required params first.
156  foreach ($input['params'] as $name => $type) {
157  if (in_array($name, $input['required'])) {
158  $params['params'][$name] = $type;
159  }
160  }
161  // ... then non required params.
162  foreach ($input['params'] as $name => $type) {
163  if (!in_array($name, $input['required'])) {
164  $params['params'][$name] = $type;
165  }
166  }
167 
168  return $params;
169 }
170 
171 
181 function makeConstructorParams(Array &$input)
182 {
183  $params = [];
184  // Required params first.
185  foreach ($input['params'] as $name => $type) {
186  $description = null;
187  $optionalValue = false;
188  if (!is_array($type)) {
189  $type = EthD::typeMap($type);
190  if (!in_array($name, $input['required'])) {
191  $optionalValue = true;
192  }
193  } else {
194  if (!in_array($name, $input['required'])) {
195  $optionalValue = true;
196  }
197  $subtype = EthD::typeMap($type[0]) ? EthD::typeMap($type[0]) : $type[0];
198  $type = 'array';
199  $description = 'Array of ' . $subtype;
200  }
201 
202 
203  $tmp = new PhpParameter($name);
204  $tmp->setType($type);
205  if ($description) {
206  $tmp->setTypeDescription($description);
207  }
208  if ($optionalValue) {
209  $tmp->setValue(NULL);
210  }
211  $params[] = $tmp;
212  }
213  return $params;
214 }
215 
216 
225 function makeProperties(Array $input)
226 {
227  $properties = [];
228  // Required params first.
229  foreach ($input['params'] as $name => $type) {
230  $p = new PhpProperty($name);
231  $p->setDescription("Value for '$name'.");
232  $properties[] = $p;
233  }
234 
235  return $properties;
236 }
237 
238 
247 function makeConstructorContent(Array $input)
248 {
249  $properties = '';
250  // Required params first.
251  foreach ($input['params'] as $name => $type) {
252  $properties .= '$this->' . $name . " = $$name; \n";
253  }
254 
255  return substr($properties, 0, -2);
256 }
257 
258 
268 function makeSetFunctions(array $input)
269 {
270 
271  $functions = [];
272  // Required params first.
273  foreach ($input['params'] as $name => $type) {
274 
275  // Property.
276  $prop = new PhpParameter('value');
277  $prop->setType(EthDataType::getTypeClass($type, true));
278 
279  // Method body.
280  $body = 'if (is_object($value) && is_a($value, \'' . EthDataType::getTypeClass($type, true) . "')) {\n";
281  $body .= "\t" . '$this->' . $name . ' = $value;' . "\n";
282  $body .= '}' . "\n";
283  $body .= 'else {' . "\n";
284  $body .= "\t" . '$this->' . $name . ' = new ' . EthDataType::getTypeClass($type, true) . '($value);' . "\n";
285  $body .= '}' . "\n";
286 
287  // Method.
288  $tmp = new PhpMethod('set' . ucfirst($name));
289  $tmp->addParameter($prop)
290  ->setDescription("Setter for '$name'.")
291  ->setBody($body)
292  ;
293 
294  $functions[] = $tmp;
295  }
296 
297  return $functions;
298 }
299 
300 
309 function makeTypeArrayBody(Array $input)
310 {
311  $data[] = "return array( ";
312  foreach ($input['params'] as $name => $type) {
313  if (is_array($type)) {
314  $data[] = "\t'" . $name . "' => '[" . EthD::typeMap($type[0]) . "]',";
315  } else {
316  $data[] = "\t'" . $name . "' => '" . EthD::typeMap($type) . "',";
317  }
318  }
319  $data[] = ");";
320  return implode("\n", $data);
321 }
322 
323 
332 function makeToArrayBody(Array $input)
333 {
334  $return = '$return = [];' . "\n";
335  // Required params first.
336  foreach ($input['params'] as $name => $type) {
337 
338  if (is_array($type)) {
339  $return .= '(!is_null($this->'
340  . $name
341  . ')) ? $return['
342  . "'$name'"
343  . '] = Ethereum::valueArray($this->'
344  . $name
345  . ", '"
346  . EthDataType::getTypeClass($type[0])
347  . "') : array(); \n";
348  } else {
349  $return .= '(!is_null($this->'
350  . $name
351  . ')) ? $return['
352  . "'$name'"
353  . '] = $this->'
354  . $name
355  . "->hexVal() : NULL; \n";
356  }
357 
358  }
359 
360  $return .= 'return $return;';
361 
362  return $return;
363 }
printMe($title, $content=null)
makeSetFunctions(array $input)
makeTypeArrayBody(Array $input)
getSchema()
foreach($schema['objects'] as $obj_name=> $params) reorderParams(Array $input)
makeConstructorContent(Array $input)
makeToArrayBody(Array $input)
makeProperties(Array $input)
makeConstructorParams(Array &$input)