Conditions | 20 |
Paths | 96 |
Total Lines | 119 |
Code Lines | 53 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
67 | public function __call($name, $arguments) |
||
68 | { |
||
69 | /** @var SoapDispatcher $ct */ |
||
70 | $ct = $this->context->getDispatcher(); |
||
71 | |||
72 | /** @var SoapRequest $rq */ |
||
73 | $rq = $this->context->getRequest(); |
||
74 | |||
75 | // set the name of the method that was called |
||
76 | // the request will also update the routing input |
||
77 | $rq->setInvokedMethod($name); |
||
78 | |||
79 | // then we grab the SoapClient with the WSDL (yes, SoapClient!) |
||
80 | // and grab a list of functions. in SoapClient, that list contains the method signatures, including the parameter names. SoapServer's __getFunctions() doesn't... |
||
81 | $functions = $ct->getSoapClient()->__getFunctions(); |
||
82 | foreach ($functions as $function) { |
||
83 | // now we try to match the called method against the function signatures |
||
84 | if (preg_match('/^(?:\S+|list\([^\)]*\))\s' . preg_quote($name, '/') . '\(([^\)]*)\)$/', $function, $matches)) { |
||
85 | // we found something, so we can extract all method argument names |
||
86 | preg_match_all('/\$([\w]+)/', $matches[1], $params); |
||
87 | for ($i = 0; $i < count($params[1]); $i++) { |
||
|
|||
88 | // and replace the numeric keys from our method call args with the actual parameter names as defined in the WSDL |
||
89 | $arguments[$params[1][$i]] = $arguments[$i]; |
||
90 | unset($arguments[$i]); |
||
91 | } |
||
92 | // and while we're at it, please get us the name of the return value as well, we need it in document/literal wrapped WSDL styles |
||
93 | $returnType = ''; |
||
94 | if (preg_match('/^(\w+) /', $function, $matches)) { |
||
95 | $returnType = $matches[1]; |
||
96 | } |
||
97 | break; |
||
98 | } |
||
99 | } |
||
100 | // all that was done because PHP's SOAP extension doesn't allow us to get information about the request. In SOAP, remote methods are always defined using named parameters, but that naming gets lost as PHP calls the respective function on the server directly, and PHP doesn't have named arguments. So all we know is the values that were given for the first, second, and so on parameter. But in Agavi, we want to access parameters by their names. We made it. With an ugly hack. Thank you, Zend. |
||
101 | |||
102 | // for document/literal wrapped style services, unpack the complex type passed in by php, see http://bugs.php.net/bug.php?id=30302 - PHP produces an stdClass object with named members. |
||
103 | if ($ct->getParameter('force_document_literal_wrapped_marshalling', false)) { |
||
104 | $unpackedArguments = array(); |
||
105 | foreach ($arguments as $argument) { |
||
106 | foreach ($argument as $name => $value) { |
||
107 | $unpackedArguments[$name] = $value; |
||
108 | } |
||
109 | } |
||
110 | $arguments = $unpackedArguments; |
||
111 | } |
||
112 | |||
113 | // finally, we can populate the request with the final data and call the _real_ dispatch() method on the "normal" Dispatcher. We hand it the arguments we got in the SOAP request. Everyone's happy. |
||
114 | $rd = $rq->getRequestData(); |
||
115 | |||
116 | $rd->setParameters($arguments); |
||
117 | |||
118 | // call doDispatch on the Dispatcher |
||
119 | $response = $ct->doDispatch(); |
||
120 | $responseContent = $response->getContent(); |
||
121 | |||
122 | // repack the document/literal wrapped content if required |
||
123 | if ($ct->getParameter('force_document_literal_wrapped_marshalling', false)) { |
||
124 | // the return type is a complex type with a single element, but what's the name of that element? |
||
125 | // struct methodNameResponse { |
||
126 | // typeName returnValueName; |
||
127 | // } |
||
128 | // it may also be empty, depending on the definition (if the request/response has a void input/output): |
||
129 | // struct deleteEverything { |
||
130 | // } |
||
131 | |||
132 | // do not wrap soap faults |
||
133 | if (!($responseContent instanceof \SoapFault)) { |
||
134 | $originalResponseContent = $responseContent; |
||
135 | $wrapperFound = false; |
||
136 | foreach ($ct->getSoapClient()->__getTypes() as $type) { |
||
137 | if ($originalResponseContent !== null && preg_match('/^struct ' . preg_quote($returnType, '/') . ' \{\s*(.+)\s*\}$/s', $type, $matches)) { |
||
138 | // next: extract all the return value part names (usually just one) |
||
139 | $returnPartCount = preg_match_all('/^\s*(?P<type>\w+) (?P<name>\w+);$/m', $matches[1], $returnParts); |
||
140 | |||
141 | // we convert the response content to an array if it's exactly one return part |
||
142 | // so the code further down works without additional checks |
||
143 | // a check like !is_array() would be wrong as the return value might be an array itself already (e.g. for a list of objects) |
||
144 | if ($returnPartCount == 1) { |
||
145 | $originalResponseContent = array($originalResponseContent); |
||
146 | } |
||
147 | |||
148 | $responseContent = new \stdClass(); |
||
149 | |||
150 | // it *should* be an array with return parts as keys, but doesn't have to be (first because PHP allows this, and second because we do this a couple of lines above) |
||
151 | // so we need to iterate by hand and check for named key first, numeric offset second |
||
152 | for ($i = 0; $i < $returnPartCount; $i++) { |
||
153 | $returnPartName = $returnParts['name'][$i]; |
||
154 | |||
155 | if (array_key_exists($returnPartName, $originalResponseContent)) { |
||
156 | $returnPartValue = $originalResponseContent[$returnPartName]; |
||
157 | } elseif (array_key_exists($i, $originalResponseContent)) { |
||
158 | $returnPartValue = $originalResponseContent[$i]; |
||
159 | } else { |
||
160 | // nothing found |
||
161 | // that means the response was invalid or something... we should bail out here, so $wrapperFound won't be true and the next type is tried |
||
162 | continue 2; |
||
163 | } |
||
164 | |||
165 | $responseContent->$returnPartName = $returnPartValue; |
||
166 | } |
||
167 | |||
168 | // we set $wrapperFound only now |
||
169 | $wrapperFound = true; |
||
170 | break; |
||
171 | } elseif ($originalResponseContent === null && preg_match('/^struct ' . preg_quote($returnType, '/') . ' \{\s*\}$/s', $type, $matches)) { |
||
172 | $wrapperFound = true; |
||
173 | $responseContent = new \stdClass(); |
||
174 | break; |
||
175 | } |
||
176 | } |
||
177 | if (!$wrapperFound) { |
||
178 | $responseContent = new \SoapFault('Server', 'Failed to marshal document/literal wrapped response: no suitable type found.'); |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | |||
183 | // return the content. that's an array, or a float, or whatever, and PHP's SOAP extension will handle the response envelope creation, sending etc for us |
||
184 | return $responseContent; |
||
185 | } |
||
186 | } |
||
187 |
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: