/** * Extract the XML Schema Definition from the script comment * * @return array Containing the xsd types or null */ public function getXsdTypes() { $this->xsd_types_array = array(); $line = strtok($this->docComment, "\n"); while ($line !== false) { if (strpos($line, "@types") !== false) { $words = SCA_AnnotationRules::parseAnnotation($line); if (!isset($words[2])) { throw new SCA_RuntimeException('types annotation needs a namespace and schema location'); } $namespace = $words[1]; $filename = $words[2]; $filename = trim($filename); // get rid of any \r $path_info = pathinfo($filename); if ($path_info['extension'] == 'xsd') { array_push($this->xsd_types_array, array($namespace, $filename)); } } $line = strtok("\n"); //next line } return $this->xsd_types_array; }
/** * 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; }