src/Controller/Panel/ChartsController.php line 542

Open in your IDE?
  1. <?php
  2. /**
  3.  * @license Silk Software House Sp. Z O.O.
  4.  */
  5. declare(strict_types=1);
  6. namespace App\Controller\Panel;
  7. use App\Annotation\ApplySettings;
  8. use App\Assembler\DataSampleAssembler;
  9. use App\Controller\Panel\Traits\FormatableTwigDataTrait;
  10. use App\DataBridge\DataAbstraction;
  11. use App\DataBridge\DataTransformers\AgeOfMaturityTransformer;
  12. use App\DataBridge\DataTransformers\TemperatureTransformer;
  13. use App\DataBridge\DataTransformers\StrengthTransformer;
  14. use App\DataBridge\Implementations\CanvasJsTransformer;
  15. use App\DataBridge\Implementations\DataTransformerInterface;
  16. use App\DataBridge\StrengthPointsAddHelper;
  17. use App\Entity\ChannelSetting;
  18. use App\Entity\Measurement;
  19. use App\Entity\Notification;
  20. use App\Entity\User;
  21. use App\Entity\UserSetting;
  22. use App\Factory\MeasurementViewFactory;
  23. use App\Helpers\DatabaseAwareTrait;
  24. use App\Helpers\MessagesTrait;
  25. use App\Helpers\SecurityAwareTrait;
  26. use App\Model\View\MeasurementView;
  27. use App\Helpers\RecipeResolver;
  28. use App\Repository\UserSettingRepository;
  29. use Exception;
  30. use Doctrine\ORM\EntityManagerInterface;
  31. use FOS\RestBundle\Controller\Annotations as Rest;
  32. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  33. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  34. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  35. use Symfony\Component\HttpFoundation\RedirectResponse;
  36. use Symfony\Component\HttpFoundation\Request;
  37. use Symfony\Component\HttpFoundation\Response;
  38. use Symfony\Contracts\Translation\TranslatorInterface;
  39. /**
  40.  *  Device list controller.
  41.  */
  42. class ChartsController extends AbstractController
  43. {
  44.     use DatabaseAwareTrait;
  45.     use FormatableTwigDataTrait;
  46.     use SecurityAwareTrait;
  47.     use MessagesTrait;
  48.     /** @var DataAbstraction */
  49.     private DataAbstraction $chartDataAbstraction;
  50.     /** @var DataSampleAssembler */
  51.     private DataSampleAssembler $dataSampleAssembler;
  52.     /** @var RecipeResolver */
  53.     private RecipeResolver $recipeResolver;
  54.     /** @var array */
  55.     private array $strengthPoints = [];
  56.     /** @var TranslatorInterface */
  57.     private TranslatorInterface $translator;
  58.     /** @var MeasurementViewFactory */
  59.     private MeasurementViewFactory $factory;
  60.     /**
  61.      * todo: refactor. base controller or trait injection
  62.      * TableController constructor.
  63.      *
  64.      * @param DataAbstraction $chartDataAbstraction
  65.      * @param DataSampleAssembler $dataSampleAssembler
  66.      * @param RecipeResolver $recipeResolver
  67.      * @param TranslatorInterface $translator
  68.      * @param EntityManagerInterface $entityManager
  69.      * @param MeasurementViewFactory $factory
  70.      */
  71.     public function __construct(
  72.         DataAbstraction $chartDataAbstraction,
  73.         DataSampleAssembler $dataSampleAssembler,
  74.         RecipeResolver $recipeResolver,
  75.         TranslatorInterface $translator,
  76.         EntityManagerInterface $entityManager,
  77.         MeasurementViewFactory $factory
  78.     ) {
  79.         $this->chartDataAbstraction $chartDataAbstraction;
  80.         $this->dataSampleAssembler $dataSampleAssembler;
  81.         $this->recipeResolver $recipeResolver;
  82.         $this->translator $translator;
  83.         $this->entityManager $entityManager;
  84.         $this->factory $factory;
  85.     }
  86.     /**
  87.      * @IsGranted("show", subject="measurement")
  88.      *
  89.      * @Rest\Get(
  90.      *     "/panel/device/measurement/{id}/chart/strength/{isRelative}",
  91.      *      name="device_measurement_chart_strength",
  92.      *      requirements={"isRelative"="(true|false)"},
  93.      *      defaults={"isRelative"=false}
  94.      *     )
  95.      * @Rest\Post(
  96.      *     "/panel/device/measurement/{id}/chart/strength/{isRelative}",
  97.      *      name="device_measurement_chart_strength_post",
  98.      *      requirements={"isRelative"="(true|false)"},
  99.      *      defaults={"isRelative"=false}
  100.      *  )
  101.      *
  102.      * @Template("panel/device-list/canvasjs_chart.html.twig")
  103.      *
  104.      * @param Measurement $measurement
  105.      * @param string|null $isRelative
  106.      *
  107.      * @return array
  108.      *
  109.      * @throws Exception
  110.      */
  111.     public function strengthChart(Measurement $measurement, ?string $isRelative null): array
  112.     {
  113.         $form $this->createAndHandleNameForm($measurement);
  114.         $relative = ('true' === $isRelative);
  115.         return [
  116.                 'formName' => $form->createView(),
  117.                 'channelNameForm' => $this->createAndHandleChannelNameForm()->createView(),
  118.                 'channelRecipeForm' => $this->createAndHandleChannelRecipeForm()->createView(),
  119.                 'device' => $this->formatDeviceData($measurement),
  120.                 'measurement_meta' => $this->formatMeasurementData($measurement),
  121.                 'measurement' => $measurement,
  122.                 'channels_meta' => $this->formatChannelsData($measurement),
  123.                 'type' => 'strength',
  124.                 'title' => $this->chartDataAbstraction->getTitle(),
  125.                 'unit' => $this->chartDataAbstraction->getUnit(),
  126.                 'legend' => $relative 'Relative time [h]' 'Real time',
  127.                 'yLabel' => 'Strength [MPa]',
  128.                 'isRelativeTimescale' => $relative 0,
  129.                 'startDate' => $measurement->getStartedAt(),
  130.             ] + $this->getFontSize();
  131.     }
  132.     /**
  133.      * @IsGranted("show", subject="measurement")
  134.      *
  135.      * @Rest\Post("/panel/device/measurement/{id}/strength-notification", name="device_measurement_strength_notification_create")
  136.      *
  137.      * @param Measurement             $measurement
  138.      * @param Request                 $request
  139.      * @param EntityManagerInterface  $entityManager
  140.      * @param TranslatorInterface     $translator
  141.      *
  142.      * @return RedirectResponse
  143.      */
  144.     public function createStrengthNotification(Measurement $measurementRequest $requestEntityManagerInterface $entityManagerTranslatorInterface $translator): RedirectResponse
  145.     {
  146.         $redirect = new RedirectResponse($request->headers->get('referer') ?: $this->generateUrl('device_measurement_chart_strength', ['id' => $measurement->getId()]));
  147.         if (!$this->isCsrfTokenValid('strength_notification'$request->request->get('token'))) {
  148.             $this->addFlash('danger'$translator->trans('Wrong CSRF token provided. Please try to perform this action again.'));
  149.             return $redirect;
  150.         }
  151.         $email trim((string) $request->request->get('email'));
  152.         if (!filter_var($emailFILTER_VALIDATE_EMAIL)) {
  153.             $this->addFlash('danger'$translator->trans('strength-notification.error.email'));
  154.             return $redirect;
  155.         }
  156.         $strengthTrigger str_replace(',''.'trim((string) $request->request->get('strengthTrigger')));
  157.         if (!is_numeric($strengthTrigger) || (float) $strengthTrigger <= 0) {
  158.             $this->addFlash('danger'$translator->trans('strength-notification.error.target'));
  159.             return $redirect;
  160.         }
  161.         $selectedChannelIds array_map('intval', (array) $request->request->get('channels', []));
  162.         if (!$measurement->getSetting() || === count($selectedChannelIds)) {
  163.             $this->addFlash('danger'$translator->trans('strength-notification.error.channels'));
  164.             return $redirect;
  165.         }
  166.         $created 0;
  167.         $duplicates 0;
  168.         $repository $entityManager->getRepository(Notification::class);
  169.         foreach ($measurement->getSetting()->getChannelSettings() as $channelSetting) {
  170.             if (!in_array($channelSetting->getId(), $selectedChannelIdstrue) || $channelSetting->isDeleted()) {
  171.                 continue;
  172.             }
  173.             $existing $repository->findOneBy([
  174.                 'user' => $this->getUser(),
  175.                 'channelSetting' => $channelSetting,
  176.                 'triggeredAt' => null,
  177.                 'strengthTrigger' => (float) $strengthTrigger,
  178.                 'email' => $email,
  179.             ]);
  180.             if ($existing) {
  181.                 ++$duplicates;
  182.                 continue;
  183.             }
  184.             $notification = (new Notification())
  185.                 ->setUser($this->getUser())
  186.                 ->setChannelSetting($channelSetting)
  187.                 ->setStrengthTrigger((float) $strengthTrigger)
  188.                 ->setEmail($email);
  189.             $entityManager->persist($notification);
  190.             ++$created;
  191.         }
  192.         if (=== $created && === $duplicates) {
  193.             $this->addFlash('danger'$translator->trans('strength-notification.error.channels'));
  194.             return $redirect;
  195.         }
  196.         if ($created 0) {
  197.             $entityManager->flush();
  198.         }
  199.         if ($created 0) {
  200.             $this->addFlash('success'$translator->trans('strength-notification.success', ['%count%' => $created]));
  201.         }
  202.         if ($duplicates 0) {
  203.             $this->addFlash('info'$translator->trans('strength-notification.duplicates', ['%count%' => $duplicates]));
  204.         }
  205.         return $redirect;
  206.     }
  207.     /**
  208.      * @IsGranted("show", subject="measurement")
  209.      *
  210.      * @Rest\Get(
  211.      *     "/panel/device/measurement/{id}/chart/maturity/{isRelative}",
  212.      *      name="device_measurement_chart_maturity",
  213.      *      requirements={"isRelative"="(true|false)"},
  214.      *      defaults={"isRelative"=false}
  215.      *     )
  216.      * @Rest\Post(
  217.      *     "/panel/device/measurement/{id}/chart/maturity/{isRelative}",
  218.      *      name="device_measurement_chart_maturity_post",
  219.      *      requirements={"isRelative"="(true|false)"},
  220.      *      defaults={"isRelative"=false}
  221.      *     )
  222.      *
  223.      * @Template("panel/device-list/canvasjs_chart.html.twig")
  224.      *
  225.      * @param Measurement $measurement
  226.      * @param string|null $isRelative
  227.      *
  228.      * @return array
  229.      *
  230.      * @throws Exception
  231.      */
  232.     public function maturityChart(Measurement $measurement, ?string $isRelative null): array
  233.     {
  234.         $form $this->createAndHandleNameForm($measurement);
  235.         $relative = ('true' === $isRelative);
  236.         return [
  237.                 'formName' => $form->createView(),
  238.                 'channelNameForm' => $this->createAndHandleChannelNameForm()->createView(),
  239.                 'channelRecipeForm' => $this->createAndHandleChannelRecipeForm()->createView(),
  240.                 'device' => $this->formatDeviceData($measurement),
  241.                 'measurement_meta' => $this->formatMeasurementData($measurement),
  242.                 'measurement' => $measurement,
  243.                 'channels_meta' => $this->formatChannelsData($measurement),
  244.                 'type' => 'maturity',
  245.                 'title' => $this->chartDataAbstraction->getTitle(),
  246.                 'unit' => $this->chartDataAbstraction->getUnit(),
  247.                 'legend' => $relative 'Relative time [h]' 'Real time',
  248.                 'yLabel' => 'Age of maturity [h]',
  249.                 'isRelativeTimescale' => $relative 0,
  250.                 'startDate' => $measurement->getStartedAt(),
  251.             ] + $this->getFontSize();
  252.     }
  253.     /**
  254.      * #AppCache()
  255.      *
  256.      * @IsGranted("show", subject="measurement")
  257.      *
  258.      * @ApplySettings()
  259.      *
  260.      * @Rest\Get(
  261.      *     "/panel/device/measurement/{id}/chart/{type}/{isRelative}/data",
  262.      *      name="device_measurement_chart_api",
  263.      *      requirements={"isRelative"="(true|false)"},
  264.      *      defaults={"isRelative"=false}
  265.      * )
  266.      *
  267.      * @param Measurement $measurement
  268.      * @param string      $type
  269.      * @param string|null $isRelative
  270.      *
  271.      * @return Response
  272.      *
  273.      * @throws Exception
  274.      */
  275.     public function chartData(Measurement $measurementstring $type, ?string $isRelative null): Response
  276.     {
  277.         $implementation $this->getValueTransformer(('true' === $isRelative), $type);
  278.         $chartDataAbstraction $this->getDataAbstraction($this->factory->create($measurement), $implementation);
  279.         try {
  280.             if (in_array($type, ['temperature''strength'], true)) {
  281.                 $dataArray $chartDataAbstraction->getDataArray();
  282.                 if ($measurement->getSetting() && $measurement->getSetting()->getIsAutomaticStrengthPointsEnabled()) {
  283.                     $usedRecipes $chartDataAbstraction->getUsedRecipes();
  284.                     $strengthPoints $this->buildAutomaticStrengthPoints($dataArray$usedRecipes);
  285.                     if ($strengthPoints) {
  286.                         $helper = (new StrengthPointsAddHelper($dataArray));
  287.                         if ('temperature' === $type) {
  288.                             $startingPointForRelativeTimePoints = ('true' === $isRelative) ? $implementation->getFirstDatePoint() : null;
  289.                             $helper->setUsedRecipe($usedRecipes);
  290.                             $helper->setFirstDateForRelativeTimesets($startingPointForRelativeTimePoints);
  291.                             $data $helper->addStrengthPoints($strengthPoints)->getJson();
  292.                         } else {
  293.                             $data $helper->addStrengthValuePoints($strengthPoints)->getJson();
  294.                         }
  295.                     } else {
  296.                         $data json_encode($dataArrayJSON_PRESERVE_ZERO_FRACTION);
  297.                     }
  298.                 } else {
  299.                     $data json_encode($dataArrayJSON_PRESERVE_ZERO_FRACTION);
  300.                 }
  301.             } else {
  302.                 $data $chartDataAbstraction->getJson();
  303.             }
  304.         } catch (Exception  $e) {
  305.             $this->addMessage($e->getMessage(), 'danger');
  306.             throw $e;
  307.         }
  308.         $data str_replace(
  309.             ['{{Channel}}''{{default recipe}}''{{CalculatedChannel}}''{{AddedChannel}}'],
  310.             [$this->translator->trans('Channel'), $this->translator->trans('Default recipe'), $this->translator->trans('calculated-channel'), $this->translator->trans('added-channel-legend')],
  311.             $data
  312.         );
  313.         if ($implementation->isError()) {
  314.             $this->addMessageArray($implementation->getMessages(), 'info');
  315.         }
  316.         $data $this->mergeInMessagesJson($data);
  317.         $response = new Response($data);
  318.         $response->headers->set('Content-Type''application/json');
  319.         return $response;
  320.     }
  321.     /**
  322.      * @IsGranted("edit", subject="measurement")
  323.      *
  324.      * @ApplySettings()
  325.      *
  326.      * @Rest\Post("/panel/device/measurement/{id}/chart/automatic-strength-points-toggle", name="device_measurement_automatic_strength_points_toggle")
  327.      * @Rest\Post("/panel/device/measurement/{id}/chart/temperature/automatic-strength-points-toggle", name="device_measurement_temperature_automatic_strength_points_toggle")
  328.      */
  329.     public function toggleAutomaticStrengthPoints(Measurement $measurementRequest $request): Response
  330.     {
  331.         if (!$this->isCsrfTokenValid('automatic_strength_points'$request->get('token'))) {
  332.             return $this->json([
  333.                 'success' => false,
  334.                 'message' => $this->translator->trans('Wrong CSRF token provided. Please try to perform this action again.'),
  335.             ], Response::HTTP_NOT_FOUND);
  336.         }
  337.         if (!$measurement->getSetting()) {
  338.             return $this->json([
  339.                 'success' => false,
  340.                 'message' => $this->translator->trans('Entity was not found.'),
  341.             ], Response::HTTP_NOT_FOUND);
  342.         }
  343.         $enabled filter_var($request->get('enabled'), FILTER_VALIDATE_BOOLEAN);
  344.         $setting $measurement->getSetting();
  345.         $setting->setIsAutomaticStrengthPointsEnabled($enabled);
  346.         $this->entityManager->persist($setting);
  347.         $this->entityManager->flush();
  348.         return $this->json([
  349.             'success' => true,
  350.             'enabled' => $setting->getIsAutomaticStrengthPointsEnabled(),
  351.             'message' => $this->translator->trans(
  352.                 $setting->getIsAutomaticStrengthPointsEnabled()
  353.                     ? 'temperature-chart.strength-points.enabled'
  354.                     'temperature-chart.strength-points.disabled'
  355.             ),
  356.         ], Response::HTTP_OK);
  357.     }
  358.     /**
  359.      * @IsGranted("edit", subject="measurement")
  360.      *
  361.      * @ApplySettings()
  362.      *
  363.      * @Rest\Post("/panel/device/measurement/{id}/chart/temperature/split-toggle", name="device_measurement_temperature_split_toggle")
  364.      */
  365.     public function toggleTemperatureSplit(Measurement $measurementRequest $request): Response
  366.     {
  367.         if (!$this->isCsrfTokenValid('temperature_split_view'$request->get('token'))) {
  368.             return $this->json([
  369.                 'success' => false,
  370.                 'message' => $this->translator->trans('Wrong CSRF token provided. Please try to perform this action again.'),
  371.             ], Response::HTTP_NOT_FOUND);
  372.         }
  373.         if (!$measurement->getSetting()) {
  374.             return $this->json([
  375.                 'success' => false,
  376.                 'message' => $this->translator->trans('Entity was not found.'),
  377.             ], Response::HTTP_NOT_FOUND);
  378.         }
  379.         $setting $measurement->getSetting();
  380.         $setting->setIsTemperatureSplitView(!$setting->getIsTemperatureSplitView());
  381.         $this->entityManager->persist($setting);
  382.         $this->entityManager->flush();
  383.         return $this->json([
  384.             'success' => true,
  385.             'enabled' => $setting->getIsTemperatureSplitView(),
  386.             'message' => $this->translator->trans(
  387.                 $setting->getIsTemperatureSplitView()
  388.                     ? 'temperature-chart.split.enabled'
  389.                     'temperature-chart.split.disabled'
  390.             ),
  391.         ], Response::HTTP_OK);
  392.     }
  393.     /**
  394.      * @Rest\Post(
  395.      *     "/panel/device/channel/{id}/diagram/{group}",
  396.      *     name="device_measurement_temperature_channel_move",
  397.      *     requirements={"group"="(1|2)"}
  398.      * )
  399.      */
  400.     public function moveTemperatureChannel(ChannelSetting $channelint $groupRequest $request): Response
  401.     {
  402.         if (!$this->isCsrfTokenValid('temperature_split_move'$request->get('token'))) {
  403.             return $this->json([
  404.                 'success' => false,
  405.                 'message' => $this->translator->trans('Wrong CSRF token provided. Please try to perform this action again.'),
  406.             ], Response::HTTP_NOT_FOUND);
  407.         }
  408.         $measurementSetting $channel->getMeasurementSetting();
  409.         $measurement $measurementSetting $measurementSetting->getMeasurement() : null;
  410.         if (!$measurement) {
  411.             return $this->json([
  412.                 'success' => false,
  413.                 'message' => $this->translator->trans('Entity was not found.'),
  414.             ], Response::HTTP_NOT_FOUND);
  415.         }
  416.         $this->denyAccessUnlessGranted('edit'$measurement);
  417.         $channel->setDiagramGroup($group);
  418.         $this->entityManager->persist($channel);
  419.         $hasSecondaryChannels false;
  420.         foreach ($measurementSetting->getChannelSettings() as $setting) {
  421.             if (!$setting->isDeleted() && === $setting->getDiagramGroup()) {
  422.                 $hasSecondaryChannels true;
  423.                 break;
  424.             }
  425.         }
  426.         $measurementSetting->setIsTemperatureSplitView($hasSecondaryChannels);
  427.         $this->entityManager->persist($measurementSetting);
  428.         $this->entityManager->flush();
  429.         return $this->json([
  430.             'success' => true,
  431.             'splitEnabled' => $measurementSetting->getIsTemperatureSplitView(),
  432.             'message' => $this->translator->trans('temperature-chart.split.moved'),
  433.         ], Response::HTTP_OK);
  434.     }
  435.     private function buildAutomaticStrengthPoints(array $dataArray, array $usedRecipes): array
  436.     {
  437.         $strengthPoints = [];
  438.         foreach ($dataArray['chartData'] ?? [] as $index => $channel) {
  439.             if (!empty($channel['isDeleted']) || empty($usedRecipes[$index])) {
  440.                 continue;
  441.             }
  442.             $fcc28 $usedRecipes[$index]->getFcc();
  443.             if (!$fcc28 || $fcc28 <= 0) {
  444.                 continue;
  445.             }
  446.             $strengthPoints[$index] = [
  447.                 round($fcc28 0.252),
  448.                 round($fcc28 0.502),
  449.                 round($fcc28 0.752),
  450.             ];
  451.         }
  452.         return $strengthPoints;
  453.     }
  454.     /**
  455.      * @IsGranted("show", subject="measurement")
  456.      *
  457.      * @ApplySettings()
  458.      *
  459.      * @Rest\Get(
  460.      *     "/panel/device/measurement/{id}/chart/temperature/{isRelative}",
  461.      *      name="device_measurement_chart_temperature",
  462.      *      requirements={"isRelative"="(true|false)"},
  463.      *      defaults={"isRelative"=false}
  464.      *     )
  465.      * @Rest\Post(
  466.      *     "/panel/device/measurement/{id}/chart/temperature/{isRelative}",
  467.      *      name="device_measurement_chart_temperature_post",
  468.      *      requirements={"isRelative"="(true|false)"},
  469.      *      defaults={"isRelative"=false}
  470.      *     )
  471.      *
  472.      * @Template("panel/device-list/canvasjs_chart.html.twig")
  473.      *
  474.      * @param Measurement $measurement
  475.      * @param string|null $isRelative
  476.      *
  477.      * @return array
  478.      *
  479.      * @throws Exception
  480.      */
  481.     public function temperatureChart(Measurement $measurement, ?string $isRelative null): array
  482.     {
  483.         $form $this->createAndHandleNameForm($measurement);
  484.         $relative = ('true' === $isRelative);
  485.         return [
  486.                 'formName' => $form->createView(),
  487.                 'channelNameForm' => $this->createAndHandleChannelNameForm()->createView(),
  488.                 'channelRecipeForm' => $this->createAndHandleChannelRecipeForm()->createView(),
  489.                 'device' => $this->formatDeviceData($measurement),
  490.                 'measurement_meta' => $this->formatMeasurementData($measurement),
  491.                 'measurement' => $measurement,
  492.                 'measurement_extended_name' => $measurement->getNameWithRelativeNumberPerDevice(),
  493.                 'channels_meta' => $this->formatChannelsData($measurement),
  494.                 'type' => 'temperature',
  495.                 'title' => $this->chartDataAbstraction->getTitle(),
  496.                 'unit' => $this->chartDataAbstraction->getUnit(),
  497.                 'legend' => $relative 'Relative time [h]' 'Real time',
  498.                 'yLabel' => 'Temperature [°C]',
  499.                 'isRelativeTimescale' => $relative 0,
  500.                 'startDate' => $measurement->getStartedAt(),
  501.             ] + $this->getFontSize();
  502.     }
  503.     /**
  504.      *
  505.      * @Rest\Put("/panel/channel/edit/{id}/{type}", name="panel_channel_edit_put")
  506.      *
  507.      * @param ChannelSetting $channel
  508.      * @param string $type
  509.      *
  510.      * @return Response
  511.      *
  512.      * @throws Exception
  513.      */
  514.     public function channelEdit(ChannelSetting $channelstring $type): Response
  515.     {
  516.         if ('name' === $type) {
  517.             $response $this->createAndHandleChannelNameForm($channel);
  518.         } elseif ('recipe' === $type) {
  519.             $response $this->createAndHandleChannelRecipeForm($channel);
  520.         } else {
  521.             throw new Exception('Invalid request type');
  522.         }
  523.         return new Response($response);
  524.     }
  525.     /**
  526.      * @param MeasurementView          $view
  527.      * @param DataTransformerInterface $implementation
  528.      *
  529.      * @return DataAbstraction
  530.      */
  531.     private function getDataAbstraction(MeasurementView $viewDataTransformerInterface $implementation): DataAbstraction
  532.     {
  533.         return $this->chartDataAbstraction
  534.             ->setImplementation($implementation)
  535.             ->setMeasurementView($view);
  536.     }
  537.     /**
  538.      * @param bool        $isRelative
  539.      * @param string|null $type
  540.      * todo : handle other transformers
  541.      *
  542.      * @return DataTransformerInterface
  543.      */
  544.     private function getValueTransformer(bool $isRelative, ?string $type null): DataTransformerInterface
  545.     {
  546.         $typeToValueTransformer = [
  547.             'default' => new TemperatureTransformer(),
  548.             'temperature' => new TemperatureTransformer(),
  549.             'maturity' => new AgeOfMaturityTransformer(),
  550.             'strength' => new StrengthTransformer(),
  551.         ];
  552.         $valueTransformer $typeToValueTransformer[$type] ?? $typeToValueTransformer['default'];
  553.         $implementation = (new CanvasJsTransformer($valueTransformer$this->recipeResolver$this->translator))
  554.             ->setRelativeTimeAxis($isRelative);
  555.         $implementation->setRelativeTimeAxis($isRelative);
  556.         return $implementation;
  557.     }
  558.     /**
  559.      * @return array
  560.      */
  561.     private function getFontSize(): array
  562.     {
  563.         /** @var User $user */
  564.         $user $this->getUser();
  565.         /** @var UserSettingRepository $userSettingRepository */
  566.         $userSettingRepository $this->getRepository(UserSetting::class);
  567.         $userSetting $userSettingRepository->getOrCreateForUser($user);
  568.         return ['fontSizeCoefficient' => ($userSetting->getFontSizeCoefficient())];
  569.     }
  570. }