src/Controller/Api/ApiNeosController.php line 186

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api;
  3. use App\Business\User;
  4. use App\Entity\Callback;
  5. use App\Extern\NeosException;
  6. use App\Services\CallbackService;
  7. use App\Services\UserService;
  8. use App\Services\XmlGeneratorService;
  9. use App\Utils\NeosParams;
  10. use GuzzleHttp\Client;
  11. use GuzzleHttp\Exception\BadResponseException;
  12. use GuzzleHttp\Exception\GuzzleException;
  13. use JSend\JSendResponse;
  14. use Psr\Cache\CacheItemPoolInterface;
  15. use Psr\Http\Message\ResponseInterface;
  16. use Psr\Http\Message\StreamInterface;
  17. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  18. use Symfony\Component\HttpFoundation\JsonResponse;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  22. use App\Services\ActionLoggerService;
  23. use Exception;
  24. use App\Utils\Helper;
  25. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  26. use Symfony\Component\Routing\Annotation\Route;
  27. use Symfony\Component\Security\Core\Security;
  28. use Symfony\Component\Security\Core\User\UserInterface;
  29. use FOS\RestBundle\Controller\Annotations\Put;
  30. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security as SecurityAnnotation;
  31. /**
  32.  * @package App\Controller\Api
  33.  */
  34. class ApiNeosController extends AbstractController
  35. {
  36.     const INTERNAL_CODEOPS 'ZZEBU';
  37.     public const CONTEXT_CODE_WEB_SERVICE 'WEB_SERVICE';
  38.     public const CONTEXT_CODE_ONLINE_BOOKING 'ONLINE_BOOKING';
  39.     private const NEOS_JSON_ENDPOINT '/neos/rest/enet-api/';
  40.     private const NEOS_XML_ENDPOINT '/neos/rest/enet/';
  41.     private const NEOS_PRIVATE_ENDPOINT '/neos/rest/';
  42.     private const NEOS_PRIVATE_AUTHORIZED_EVENTS = [
  43.         65000// Neos Event for RADIO
  44.     ];
  45.     private const XML "XML";
  46.     private const JSON "JSON";
  47.     private const MULTIPART "MULTIPART";
  48.     protected NeosParams $neosParams;
  49.     protected UserService $userService;
  50.     protected XmlGeneratorService $xmlGeneratorService;
  51.     protected CallbackService $callbackService;
  52.     protected Security $security;
  53.     protected ActionLoggerService $actionLoggerService;
  54.     protected CacheItemPoolInterface $cachePool;
  55.     public function __construct(
  56.         NeosParams                    $neosParams,
  57.         UserService                   $userService,
  58.         XmlGeneratorService           $xmlGeneratorService,
  59.         CallbackService               $callbackService,
  60.         Security                      $security,
  61.         ActionLoggerService           $actionLoggerService,
  62.         CacheItemPoolInterface        $cachePool
  63.     )
  64.     {
  65.         $this->neosParams $neosParams;
  66.         $this->userService $userService;
  67.         $this->xmlGeneratorService $xmlGeneratorService;
  68.         $this->callbackService $callbackService;
  69.         $this->security $security;
  70.         $this->actionLoggerService $actionLoggerService;
  71.         $this->cachePool $cachePool;
  72.     }
  73.     /**
  74.      * @param Request $request
  75.      * @Put("/api/1.0/synopsis-notifications/organizationCode/{organizationCode}", name="api_synopsis_notification", options={"expose" = true})
  76.      * @Put("/api/1.0/synopsis-notifications/organizationCode/{organizationCode}/", name="api_synopsis_notification_slash", options={"expose" = true})
  77.      * @Put("/rest/1.0/synopsis-notifications/organizationCode/{organizationCode}", name="api_synopsis_notification_old", options={"expose" = true})
  78.      * @Put("/rest/1.0/synopsis-notifications/organizationCode/{organizationCode}/", name="api_synopsis_notification_old_slash", options={"expose" = true})
  79.      * @return JsonResponse|Response
  80.      */
  81.     public function getSynopsisNotificationAction(Request $request)
  82.     {
  83.         $organizationCode $request->get('organizationCode');
  84.         $xmlData $this->callbackService->sendCallback($organizationCodeCallback::SYNOPSIS);
  85.         return $this->buildResponse($request$xmlData);
  86.     }
  87.     /**
  88.      * @param Request $request
  89.      * @Put("/api/1.0/request-notifications/organizationCode/{organizationCode}", name="api_request_notification", options={"expose" = true})
  90.      * @Put("/api/1.0/request-notifications/organizationCode/{organizationCode}/", name="api_request_notification_slash", options={"expose" = true})
  91.      * @Put("/rest/1.0/request-notifications/organizationCode/{organizationCode}", name="api_request_notification_old", options={"expose" = true})
  92.      * @Put("/rest/1.0/request-notifications/organizationCode/{organizationCode}/", name="api_request_notification_old_slash", options={"expose" = true})
  93.      * @return JsonResponse|Response
  94.      */
  95.     public function getRequestNotificationAction(Request $request)
  96.     {
  97.         $organizationCode $request->get('organizationCode');
  98.         $xmlData $this->callbackService->sendCallback($organizationCodeCallback::REQUEST);
  99.         return $this->buildResponse($request$xmlData);
  100.     }
  101.     /**
  102.      * @param Request $request
  103.      * @param $xmlData
  104.      * @return JsonResponse|Response
  105.      */
  106.     protected function buildResponse(Request $request$xmlData)
  107.     {
  108.         $format $request->get('format');
  109.         if (empty($format)) {
  110.             $format 'xml';
  111.         }
  112.         //only xml and json format are available
  113.         if ($format !== 'json' && $format !== 'xml' && $format !== 'TEXT' && $format !== 'XML') {
  114.             throw new BadRequestHttpException("only xml and json format are available");
  115.         }
  116.         if ($format === 'xml' || $format === 'XML' || $format === 'TEXT') {
  117.             $response = new Response($xmlData200, ['Content-Type' => 'text/xml; charset=UTF-8']);
  118.         } else {
  119.             $jsend = new JSendResponse('success', [Helper::convertXmlToJson($xmlData)]);
  120.             $response = new JsonResponse($jsend);
  121.         }
  122.         return $response;
  123.     }
  124.     /**
  125.      * @param Request $request
  126.      * @param UserInterface $user
  127.      * @param string $call_url_suffix
  128.      * @return JsonResponse
  129.      * @throws GuzzleException
  130.      * @throws NeosException
  131.      * @Route("/enet-rest/{version}/{call_url_suffix}", name="rest_neos_call", options={"expose" = true}, requirements={"call_url_suffix"=".+"})
  132.      */
  133.     public function callXmlNeosWebServices(Request $requestUserInterface $userstring $versionstring $call_url_suffix)
  134.     {
  135.         //date have xml format by default
  136.         $myWebServiceID $request->query->get('myWebServiceID');
  137.         $queryParams $request->query->all();
  138.         unset($queryParams["timeStamp"]);//Check if we need to remove them after
  139.         unset($queryParams["myWebServiceID"]);
  140.         unset($queryParams["footprint"]);
  141.         unset($queryParams["responseFormat"]);
  142.         $method $request->getMethod();
  143.         $parameters $request->getContent();
  144.         $call_url $this->neosParams->url ApiNeosController::NEOS_XML_ENDPOINT $version "/" $call_url_suffix;
  145.         $response $this->callNeosWS($myWebServiceID$user$method$call_url$parameters$queryParamsApiNeosController::XML);
  146.         if ((Helper::contains($call_url_suffix'synopsis') || Helper::contains($call_url_suffix'synopses')) && !empty($queryParams) && !empty($queryParams["orgCode"]) && !$this->checkIfOpscodeFamily($myWebServiceID$user$queryParams["orgCode"])) {
  147.             $xmlData $this->xmlGeneratorService->returnXMLError(['code' => Response::HTTP_UNAUTHORIZED'label' => 'Unauthorized']);
  148.             $response = new Response($xmlDataResponse::HTTP_UNAUTHORIZED);
  149.             $response->headers->set('Content-Type''application/xml');
  150.             return $response;
  151.         }
  152.         if (!$response) {
  153.             $xmlData $this->xmlGeneratorService->returnXMLError(['code' => Response::HTTP_NOT_FOUND'label' => 'Web service not found']);
  154.             $response = new Response($xmlDataResponse::HTTP_NOT_FOUND);
  155.             $response->headers->set('Content-Type''application/xml');
  156.             return $response;
  157.         }
  158.         return $response;
  159.     }
  160.     /**
  161.      * @param Request $request
  162.      * @param UserInterface $user
  163.      * @param string $call_url_suffix
  164.      * @return JsonResponse
  165.      * @throws GuzzleException
  166.      * @throws NeosException
  167.      * @Route("/enet-api/intern/{call_url_suffix}", name="api_neos_intern_call", options={"expose" = true}, requirements={"call_url_suffix"=".+"})
  168.      * @SecurityAnnotation ("is_granted('ROLE_API_NEOS_INTERN')")
  169.      */
  170.     public function callInternJsonNeosWebServices(Request $requestUserInterface $userstring $call_url_suffix)
  171.     {
  172.         //date have xml format by default
  173.         $myWebServiceID $request->query->get('myWebServiceID');
  174.         $queryParams $request->query->all();
  175.         unset($queryParams["timeStamp"]);//Check if we need to remove them after
  176.         unset($queryParams["myWebServiceID"]);
  177.         unset($queryParams["footprint"]);
  178.         unset($queryParams["responseFormat"]);
  179.         $method $request->getMethod();
  180.         $parameters json_decode($request->getContent(), true);
  181.         $call_url $this->neosParams->url ApiNeosController::NEOS_PRIVATE_ENDPOINT  $call_url_suffix;
  182.         $response $this->callNeosWS($myWebServiceID$user$method$call_url$parameters$queryParamsApiNeosController::JSON);
  183.         if ((Helper::contains($call_url_suffix'synopsis') || Helper::contains($call_url_suffix'synopses')) && !empty($queryParams) && !empty($queryParams["orgCode"]) && !$this->checkIfOpscodeFamily($myWebServiceID$user$queryParams["orgCode"])) {
  184.             $data = [
  185.                 "code" => Response::HTTP_UNAUTHORIZED,
  186.                 "label" => "Unauthorized"
  187.             ];
  188.             return new JsonResponse($dataResponse::HTTP_UNAUTHORIZED);
  189.         }
  190.         if (!$response) {
  191.             $data = [
  192.                 "code" => Response::HTTP_NOT_FOUND,
  193.                 "label" => "Web service not found"
  194.             ];
  195.             return new JsonResponse($dataResponse::HTTP_NOT_FOUND);
  196.         }
  197.         $content $response->getContent();
  198.         if($response->getContent() !== null) {
  199.             $jsonData json_decode($contenttrue);
  200.             if(isset($jsonData["event"]["no"])){
  201.                 $eventNo $jsonData["event"]["no"];
  202.                 if (in_array($eventNoApiNeosController::NEOS_PRIVATE_AUTHORIZED_EVENTS)) {
  203.                     return $response;
  204.                 } else {
  205.                     $data = [
  206.                         "code" => Response::HTTP_UNAUTHORIZED,
  207.                         "label" => "Unauthorized"
  208.                     ];
  209.                     return new JsonResponse($dataResponse::HTTP_UNAUTHORIZED);
  210.                 }
  211.             }
  212.         }
  213.         return $response;
  214.     }
  215.     /**
  216.      * @param Request $request
  217.      * @param UserInterface $user
  218.      * @param string $call_url_suffix
  219.      * @return JsonResponse
  220.      * @throws GuzzleException
  221.      * @throws NeosException
  222.      * @Route("/enet-api/{version}/{call_url_suffix}", name="api_neos_call", options={"expose" = true}, requirements={"call_url_suffix"=".+"})
  223.      */
  224.     public function callJsonNeosWebServices(Request $requestUserInterface $userstring $versionstring $call_url_suffix)
  225.     {
  226.         //date have xml format by default
  227.         $myWebServiceID $request->query->get('myWebServiceID');
  228.         $queryParams $request->query->all();
  229.         unset($queryParams["timeStamp"]);//Check if we need to remove them after
  230.         unset($queryParams["myWebServiceID"]);
  231.         unset($queryParams["footprint"]);
  232.         unset($queryParams["responseFormat"]);
  233.         $method $request->getMethod();
  234.         $call_url $this->neosParams->url ApiNeosController::NEOS_JSON_ENDPOINT $version "/" $call_url_suffix;
  235.         if (str_starts_with($request->headers->get('Content-Type'''), 'multipart/form-data')) {
  236.             $parameters $this->buildMultipartFromRequest($request);
  237.             $response $this->callNeosWS($myWebServiceID$user$method$call_url$parameters$queryParamsApiNeosController::MULTIPART);
  238.         } else {
  239.             $parameters json_decode($request->getContent(), true);
  240.             $response $this->callNeosWS($myWebServiceID$user$method$call_url$parameters$queryParamsApiNeosController::JSON);
  241.         }
  242.         if ((Helper::contains($call_url_suffix'synopsis') || Helper::contains($call_url_suffix'synopses')) && !empty($queryParams) && !empty($queryParams["orgCode"]) && !$this->checkIfOpscodeFamily($myWebServiceID$user$queryParams["orgCode"])) {
  243.             $data = [
  244.                 "code" => Response::HTTP_UNAUTHORIZED,
  245.                 "label" => "Unauthorized"
  246.             ];
  247.             return new JsonResponse($dataResponse::HTTP_UNAUTHORIZED);
  248.         }
  249.         if (!$response) {
  250.             $data = [
  251.                 "code" => Response::HTTP_NOT_FOUND,
  252.                 "label" => "Web service not found"
  253.             ];
  254.             return new JsonResponse($dataResponse::HTTP_NOT_FOUND);
  255.         }
  256.         return $response;
  257.     }
  258.     /**
  259.      * @param Request $request
  260.      * @param string $url
  261.      * @return mixed|null|ResponseInterface
  262.      * @throws AccessDeniedHttpException
  263.      * @throws NeosException
  264.      * @throws GuzzleException
  265.      */
  266.     private function callNeosWS(string $myWebServiceIDUserInterface $userstring $methodstring $url$parameters$queryParams$mode ApiNeosController::JSON)
  267.     {
  268.         if ($mode === ApiNeosController::JSON) {
  269.             $contentType 'application/json';
  270.         } elseif ($mode === ApiNeosController::MULTIPART) {
  271.             $contentType null// Guzzle sets Content-Type with boundary automatically
  272.         } else {
  273.             $contentType 'application/xml';
  274.         }
  275.         $opscode null;
  276.         $isWebServiceCall = (!empty($myWebServiceID)) ? true false;
  277.         if ($user === null) {
  278.             throw new AccessDeniedHttpException("Unknown user");
  279.         }
  280.         $client = new Client();
  281.         if ($mode === ApiNeosController::JSON || $mode === ApiNeosController::MULTIPART) {
  282.             $headers = [
  283.                 'headers' => $this->buildNeosHeaders($useris_array($parameters) && !isset($parameters[0]) ? $parameters null$contentType$isWebServiceCall$opscode)
  284.             ];
  285.         } else {
  286.             $headers = [
  287.                 'headers' => $this->buildNeosHeaders($userHelper::convertXmlToArray($parameters), $contentType$isWebServiceCall$opscode)
  288.             ];
  289.         }
  290.         $queryParams = [
  291.             "query" => $queryParams
  292.         ];
  293.         $body $this->formatBody($parameters$mode);
  294.         $options array_merge($queryParams$headers$body);
  295.         try {
  296.             $this->actionLoggerService->logActionV2('CALL_'$method$headers['headers']['ws_requestid'], $url,
  297.                 json_encode($options));
  298.             $response $client->request(
  299.                 $method,
  300.                 $url,
  301.                 $options
  302.             );
  303.             $messageToLog $response->getBody();
  304.             if ($messageToLog == null) {
  305.                 $messageToLog '';
  306.             }
  307.             $this->actionLoggerService->logActionV2('RESP_'$method$headers['headers']['ws_requestid'],
  308.                 $url$messageToLog);
  309.             return $this->formatResponse($response$mode);
  310.         } catch (Exception $e) {
  311.             $initErrorMessage ApiNeosController::extractMessageError($e);
  312.             //NEOS sends error messages even for basic calls without any issue...
  313.             $this->actionLoggerService->logActionErrorV2('_RESP'$method$headers['headers']['ws_requestid'], $url,
  314.                 $initErrorMessage);
  315.             if ($e instanceof GuzzleException) {
  316.                 if ($e->getCode() === 503) {
  317.                     throw new NeosException(
  318.                         sprintf(
  319.                             "Our NEOS service is currently unavailable due to %s.
  320.                     Please refresh the system and try again. If the problem persists, please contact websupport@eurovisionservices.com.",
  321.                             $initErrorMessage
  322.                         ), $initErrorMessage$e->getCode());
  323.                 }
  324.                 return $this->formatExceptionResponse($e$mode);
  325.             } else {
  326.                 throw new Exception($e);
  327.             }
  328.         }
  329.         return $response;
  330.     }
  331.     /**
  332.      * @param UserInterface $user
  333.      * @param array|null $body
  334.      * @param string $contentType
  335.      * @param bool|null $isWebServiceCall
  336.      * @param string|null $opscode
  337.      * @return array
  338.      */
  339.     private
  340.     function buildNeosHeaders(UserInterface $user, ?array $body, ?string $contentType 'application/json', ?bool $isWebServiceCall falsestring $opscode null): array
  341.     {
  342.         $codeOps $user->getCompanies() != null $user->getCompanies()[0] : '';
  343.         $orgCode = (!empty($opscode)) ? $opscode $codeOps;
  344.         if (!empty($body) && !empty($body['customer']) && $codeOps === ApiNeosController::INTERNAL_CODEOPS) {
  345.             $orgCode $body['customer'];
  346.         }
  347.         $headers = [
  348.             'ws_requestid' => hexdec(uniqid()),
  349.             'orgcode' => $orgCode,
  350.             'useid' => $user->getDisplayName(),
  351.             'appCode' => ($isWebServiceCall) ? ApiNeosController::CONTEXT_CODE_WEB_SERVICE ApiNeosController::CONTEXT_CODE_ONLINE_BOOKING,
  352.             'wsrequestapp' => ($isWebServiceCall) ? ApiNeosController::CONTEXT_CODE_WEB_SERVICE ApiNeosController::CONTEXT_CODE_ONLINE_BOOKING,
  353.             'ws_request_source' => ($isWebServiceCall) ? ApiNeosController::CONTEXT_CODE_WEB_SERVICE ApiNeosController::CONTEXT_CODE_ONLINE_BOOKING,
  354.             'useemail' => $user->getContactMail(),
  355.             'uselastname' => $user->getLastName(),
  356.             'usefirstname' => $user->getFirstName(),
  357.         ];
  358.         if ($contentType !== null) {
  359.             $headers['Content-Type'] = $contentType;
  360.         }
  361.         return $headers;
  362.     }
  363.     /**
  364.      * @param $ex
  365.      * @return StreamInterface
  366.      */
  367.     public
  368.     static function extractMessageError(Exception $ex): string
  369.     {
  370.         $exceptionFromNEOS $ex->getPrevious();
  371.         $exceptionToUse $ex;
  372.         if ($exceptionFromNEOS != null) {
  373.             $exceptionToUse $exceptionFromNEOS;
  374.         }
  375.         $messageError $exceptionToUse->getMessage();
  376.         if ($exceptionToUse instanceof BadResponseException) {
  377.             /** @var BadResponseException $exceptionToUse */
  378.             $messageError $exceptionToUse->getResponse()->getBody()->getContents();
  379.             if (Helper::isJSON($messageError)) {
  380.                 $errorAsArray json_decode($messageErrortrue);
  381.                 $newMessage '';
  382.                 if (array_key_exists('label'$errorAsArray)) {
  383.                     $newMessage $errorAsArray['label'] . ' ';
  384.                     unset($errorAsArray['label']);
  385.                 }
  386.                 if (array_key_exists('code'$errorAsArray)) {
  387.                     $newMessage .= '(code ' $errorAsArray['code'] . ')';
  388.                     unset($errorAsArray['code']);
  389.                 }
  390.                 foreach ($errorAsArray as $id => $value) {
  391.                     if (is_array($value)) {
  392.                         $newMessage .= ', ' $id ' = ' json_encode($value);
  393.                     } else {
  394.                         $newMessage .= ', ' $id ' = ' $value;
  395.                     }
  396.                 }
  397.                 $messageError $newMessage;
  398.             }
  399.         }
  400.         return $messageError;
  401.     }
  402.     /**
  403.      * @param $body
  404.      * @param $mode
  405.      * @return array
  406.      */
  407.     private function formatBody($body$mode)
  408.     {
  409.         if ($body === null || $body === '') { //initial check
  410.             return [];
  411.         }
  412.         if ($mode === ApiNeosController::MULTIPART) {
  413.             return [
  414.                 'multipart' => $body
  415.             ];
  416.         }
  417.         if ($mode === ApiNeosController::JSON) {
  418.             return [
  419.                 'json' => $body
  420.             ];
  421.         } else { //XML Body
  422.             return [
  423.                 'body' => $body
  424.             ];
  425.         }
  426.     }
  427.     private function buildMultipartFromRequest(Request $request): array
  428.     {
  429.         $multipart = [];
  430.         $files $request->files->all();
  431.         $firstFile = !empty($files) ? array_values($files)[0] : null;
  432.         foreach ($request->request->all() as $name => $value) {
  433.             if ($name === 'fileName' && $firstFile !== null) {
  434.                 $extension $firstFile->getClientOriginalExtension();
  435.                 if ($extension && !str_ends_with($value'.' $extension)) {
  436.                     $value .= '.' $extension;
  437.                 }
  438.             }
  439.             $multipart[] = ['name' => $name'contents' => $value];
  440.         }
  441.         foreach ($files as $name => $file) {
  442.             $multipart[] = [
  443.                 'name' => $name,
  444.                 'contents' => fopen($file->getPathname(), 'r'),
  445.                 'filename' => $file->getClientOriginalName(),
  446.                 'headers' => ['Content-Type' => $file->getMimeType()],
  447.             ];
  448.         }
  449.         return $multipart;
  450.     }
  451.     /**
  452.      * @param $response
  453.      * @param $mode
  454.      * @return JsonResponse|Response
  455.      * Workflow:
  456.      * If (Method GET and response in JSON)  OR If Mode = JSON -> Send in Json
  457.      * Else -> Body in XML : If desired response is JSON -> format XML in json before sending ELSE send XML body
  458.      */
  459.     private function formatResponse($response$mode)
  460.     {
  461.         if ($mode === ApiNeosController::JSON || $mode === ApiNeosController::MULTIPART) {
  462.             return new JsonResponse(json_decode((string)$response->getBody(), true), $response->getStatusCode());
  463.         } else {
  464.             $response = new Response($response->getBody(), $response->getStatusCode());
  465.             $response->headers->set('Content-Type''application/xml');
  466.             return $response;
  467.         }
  468.     }
  469.     /**
  470.      * @param $exception
  471.      * @param $mode
  472.      * @return false|JsonResponse|Response
  473.      * Workflow: If 404 and response in HTML -> It's Tomcat responding saying that the endpoint does not exist in JSON -> return false
  474.      * If (Method GET and response in JSON)  OR If Mode = JSON -> Send in Json
  475.      * Else -> Body in XML : If desired response is JSON -> format XML in json before sending ELSE send XML body
  476.      *
  477.      */
  478.     private
  479.     function formatExceptionResponse($exception$mode//Format response from Neos before sending to the client
  480.     {
  481.         if ($exception->getCode() === 404 && Helper::containsIgnoreCase((string)$exception->getResponse()->getBody(), '</html>')) {
  482.             return false;
  483.         }
  484.         if ($mode === ApiNeosController::JSON || $mode === ApiNeosController::MULTIPART) {
  485.             return new JsonResponse(json_decode((string)$exception->getResponse()->getBody(), true), $exception->getCode());
  486.         } else {
  487.             $response = new Response($exception->getResponse()->getBody(), $exception->getCode());
  488.             $response->headers->set('Content-Type''application/xml');
  489.             return $response;
  490.         }
  491.     }
  492.     /**
  493.      * Check if the opscode given is in the family of the user
  494.      * @param string $myWebServiceID
  495.      * @param UserInterface $user
  496.      * @param null|string $opscodeParam only used for logs
  497.      * @return mixed|null|bool
  498.      */
  499.     public function checkIfOpscodeFamily(string $myWebServiceIDUserInterface $user, ?string $opscodeParam)
  500.     {
  501.         if ($user->getCompanies()[0] == $opscodeParam) {
  502.             return true;
  503.         }
  504.         $call_url $this->neosParams->url ApiNeosController::NEOS_XML_ENDPOINT '1.0/organizations/' $user->getCompanies()[0] . '/family-destinations';
  505.         $response $this->callNeosWS($myWebServiceID$user'GET'$call_url"", [], ApiNeosController::XML);
  506.         $userOrgCodeFamilyXml simplexml_load_string($response->getContent());
  507.         if (!empty($userOrgCodeFamilyXml)) {
  508.             foreach ($userOrgCodeFamilyXml->organization as $anOrgFamily) {
  509.                 if (!empty($anOrgFamily) && !empty($anOrgFamily->code) && $anOrgFamily->code == $opscodeParam) {
  510.                     return true;
  511.                 }
  512.             }
  513.         }
  514.         return false;
  515.     }
  516. }