/** * Build a two-dimensional array containing the contents of the method * annotations discovered in the document comment. * The format of the returned array is compatible with the generate * wsdl function * array( 'parameters' => $parameter_descriptions, * 'return' => $return_descriptor * ); * * @return array ( 2dim array containing parameter lines or null ) * @throws SCA_RuntimeException when an error in the parameter annotation */ public function getMethodAnnotations() { $i = 0; $this->reason = null; $this->annotation = array(); $this->methodAnnotations = SCA_AnnotationRules::createEmptyAnnotationArray(); $line = strtok($this->docComment, self::EOL); /* 1st line */ /* Loop round until all the doc comment has been read */ while ($line !== false) { /* Is this a 'parameter' line */ if ($this->Rule->isMethodAnnotation($line)) { /* Extract the components of the annotation into an array */ $words = SCA_AnnotationRules::parseAnnotation($line); if (SCA_AnnotationRules::enoughPieces($words) !== true) { $reason = "Invalid method annotation syntax in '{$line}' "; throw new SCA_RuntimeException($reason); } if (strcmp($words[0], SCA_AnnotationRules::PARAM) === 0) { $this->methodAnnotations[self::PARAM_ANNOTATION][$i++] = $this->setParameterValues($words); } else { if (strcmp($words[0], SCA_AnnotationRules::NAME) === 0) { $this->methodAnnotations[self::NAME_ANNOTATION] = $this->setMethodAlias($words); } else { /* Ensure that no syntax error has been detected */ if (($checkValue = $this->setReturnValues($words)) != null) { $this->methodAnnotations[self::RETRN_ANNOTATION][0] = $checkValue; } else { $reason = "Invalid return annotation syntax in '{$line}' "; throw new SCA_RuntimeException($reason); } } } } $line = strtok(self::EOL); /* next line */ } return $this->methodAnnotations; }
/** * Reflect service * * @return object SCA_ServiceDescription * @throws SCA_RuntimeException */ public function reflectService() { $reflection = $this->_getReflection(); $reader = new SCA_CommentReader($reflection->getDocComment()); $sca_name = $this->_getClassName(); /** * Check that this object is defining a service that will be * exposed to callers * [TODO] - this check needs converting to if (!local service) */ if (!$reader->isService()) { throw new SCA_RuntimeException("Class {$sca_name} does not contain an @service annotation."); } $service = new SCA_ServiceDescription(); $interface_reflection = null; if ($reader->isService()) { $service->interface_name = $reader->getServiceInterface(); // Get the ReflectionObject for any service interface $interface_reflection = $this->_getInterfaceReflection($reflection, $service->interface_name); if (is_null($interface_reflection)) { $interface_methods = null; if (!empty($service->interface_name)) { throw new SCA_RuntimeException("Service interface " . $service->interface_name . " specified by @service does not match any interface" . " implemented by {$sca_name}.php'."); } } else { $interface_methods = $interface_reflection->getMethods(); } $service->binding = $reader->getBindings(); } if (count($service->binding) == 0) { throw new SCA_RuntimeException("No valid @binding annotation could be found for '{$sca_name}.php'."); } $service->xsd_types = $this->reflectXsdTypes(); /* Filter reflected method array to show 'public' functions only */ $service_methods = SCA_Helper::filterMethods($this->_getMethods(), $reflection->getMethods(), $interface_methods); $operations = array(); $comment = null; /* Check the comment of each method to find any annotations so that * a wsdl can be generated from the .php file. */ foreach ($service_methods as $service_method) { $methodAnnotations = SCA_AnnotationRules::createEmptyAnnotationArray(); $comment = $service_method->getDocComment(); /* When the method has a doc comment .... */ if ($comment) { $method_reader = new SCA_CommentReader($comment); /* ... and the method a web service method .... */ if (!$method_reader->isWebMethod()) { continue; } /* ... decode any method annotations. */ $methodAnnotations = $method_reader->getMethodAnnotations(); if ($methodAnnotations == null) { continue; } $thisElement = 0; /* Each set of method annotations contain a set of 1 * or more parameter annotations, and 1 return * annotation. */ foreach ($methodAnnotations as $annotationSet) { // check that $annotationSet is not null to // take account of the situation where no // @return or @param annotation is specified if (!$annotationSet) { continue; } /* Clean off the dollar sign from the variable name, and do */ /* a namespace check as appropriate. */ foreach ($annotationSet as $annotation) { $is_param = strcmp($annotation['annotationType'], SCA_AnnotationRules::PARAM); if ($is_param === 0) { $has_dollar = strpos($annotation['name'], SCA_AnnotationRules::DOLLAR); if ($has_dollar === false) { throw new SCA_RuntimeException("Invalid syntax '" . $annotation['name'] . "' is not a php variable name"); } $methodAnnotations['parameters'][$thisElement]['name'] = trim($annotation['name'], SCA_AnnotationRules::DOLLAR); } /* When the array is formatted for SDO objects */ if (array_key_exists('namespace', $annotation)) { // check that the xsd is defined for the namespace $matched_xsds = $this->_matchXsds($service->xsd_types, $annotation['namespace']); if (!$matched_xsds) { /* TODO: noticed potential defect that if a method A has no @param, the @param of another method is being picked up instead and this error being thrown for method A */ throw new SCA_RuntimeException("Namespace defined in " . $annotation['annotationType'] . "not found in @types annotation: '" . $annotation['namespace'] . "'"); } } $thisElement++; // next annotation } } } /* Save the annotation set indexed by the method name. */ $operations[$service_method->getName()] = $methodAnnotations; } $service->operations = $operations; $service->binding_config = $reader->getNameValuePairs(); return $service; }