var/cache/review/twig/74/74516b4c622b67a997789008e076428a.php line 52

Open in your IDE?
  1. <?php
  2. use Twig\Environment;
  3. use Twig\Error\LoaderError;
  4. use Twig\Error\RuntimeError;
  5. use Twig\Extension\SandboxExtension;
  6. use Twig\Markup;
  7. use Twig\Sandbox\SecurityError;
  8. use Twig\Sandbox\SecurityNotAllowedTagError;
  9. use Twig\Sandbox\SecurityNotAllowedFilterError;
  10. use Twig\Sandbox\SecurityNotAllowedFunctionError;
  11. use Twig\Source;
  12. use Twig\Template;
  13. /* Map/page.html.twig */
  14. class __TwigTemplate_4be02f91027edecd6d364d2dec5094bd extends Template
  15. {
  16.     private $source;
  17.     private $macros = [];
  18.     public function __construct(Environment $env)
  19.     {
  20.         parent::__construct($env);
  21.         $this->source = $this->getSourceContext();
  22.         $this->blocks = [
  23.             'mainContainer' => [$this, 'block_mainContainer'],
  24.             'javascripts' => [$this, 'block_javascripts'],
  25.         ];
  26.     }
  27.     protected function doGetParent(array $context)
  28.     {
  29.         // line 1
  30.         return "grid.html.twig";
  31.     }
  32.     protected function doDisplay(array $context, array $blocks = [])
  33.     {
  34.         $macros = $this->macros;
  35.         $__internal_b91a4435ea3baf1e2b6bfda56133dace = $this->extensions["Sentry\\SentryBundle\\Tracing\\Twig\\TwigTracingExtension"];
  36.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->enter($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Map/page.html.twig"));
  37.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  38.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Map/page.html.twig"));
  39.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  40.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Map/page.html.twig"));
  41.         $this->parent = $this->loadTemplate("grid.html.twig", "Map/page.html.twig", 1);
  42.         $this->parent->display($context, array_merge($this->blocks, $blocks));
  43.         
  44.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->leave($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof);
  45.         
  46.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  47.         
  48.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  49.     }
  50.     // line 3
  51.     public function block_mainContainer($context, array $blocks = [])
  52.     {
  53.         $macros = $this->macros;
  54.         $__internal_b91a4435ea3baf1e2b6bfda56133dace = $this->extensions["Sentry\\SentryBundle\\Tracing\\Twig\\TwigTracingExtension"];
  55.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->enter($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "mainContainer"));
  56.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  57.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "mainContainer"));
  58.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  59.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "mainContainer"));
  60.         // line 4
  61.         echo "   ";
  62.         // line 5
  63.         echo "    <div id=\"map_form\"></div>
  64.     <p>
  65.         <button type=\"button\" id=\"map_refresh\" disabled>Обновить карту</button>
  66.         <button type=\"button\" id=\"map_reset\" disabled>Сбросить фильтры</button>
  67.         <span id=\"map_status\" role=\"status\" aria-live=\"polite\">Загрузка карты…</span>
  68.     </p>
  69.     <img src=\"";
  70.         // line 11
  71.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("/static/preloader.gif"), "html", null, true);
  72.         echo "\" id=\"preloader\" style=\"display: none;\" />
  73.     <div id=\"map\"
  74.          data-city-uri-idenity=\"";
  75.         // line 13
  76.         echo twig_escape_filter($this->env, (isset($context["cityUriIdentity"]) || array_key_exists("cityUriIdentity", $context) ? $context["cityUriIdentity"] : (function () { throw new RuntimeError('Variable "cityUriIdentity" does not exist.', 13, $this->source); })()), "html", null, true);
  77.         echo "\"
  78.          data-city-latitude=\"";
  79.         // line 14
  80.         echo twig_escape_filter($this->env, (isset($context["cityLatitude"]) || array_key_exists("cityLatitude", $context) ? $context["cityLatitude"] : (function () { throw new RuntimeError('Variable "cityLatitude" does not exist.', 14, $this->source); })()), "html", null, true);
  81.         echo "\"
  82.          data-city-longitude=\"";
  83.         // line 15
  84.         echo twig_escape_filter($this->env, (isset($context["cityLongitude"]) || array_key_exists("cityLongitude", $context) ? $context["cityLongitude"] : (function () { throw new RuntimeError('Variable "cityLongitude" does not exist.', 15, $this->source); })()), "html", null, true);
  85.         echo "\"
  86.          data-map-context=\"";
  87.         // line 16
  88.         echo twig_escape_filter($this->env, (isset($context["mapContext"]) || array_key_exists("mapContext", $context) ? $context["mapContext"] : (function () { throw new RuntimeError('Variable "mapContext" does not exist.', 16, $this->source); })()), "html", null, true);
  89.         echo "\"
  90.          style=\"width:100%; height:500px;\"></div>
  91. ";
  92.         
  93.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  94.         
  95.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  96.         
  97.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->leave($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof);
  98.     }
  99.     // line 20
  100.     public function block_javascripts($context, array $blocks = [])
  101.     {
  102.         $macros = $this->macros;
  103.         $__internal_b91a4435ea3baf1e2b6bfda56133dace = $this->extensions["Sentry\\SentryBundle\\Tracing\\Twig\\TwigTracingExtension"];
  104.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->enter($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
  105.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  106.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
  107.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  108.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
  109.         // line 21
  110.         echo "    <script src=\"";
  111.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("bundles/fosjsrouting/js/router.min.js"), "html", null, true);
  112.         echo "\"></script>
  113.     <script src=\"";
  114.         // line 22
  115.         echo $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("fos_js_routing_js", ["callback" => "fos.Router.setData"]);
  116.         echo "\"></script>
  117.     <script src=\"https://code.jquery.com/jquery-3.4.1.min.js\"></script>
  118.     <script src=\"https://api-maps.yandex.ru/2.1/?lang=ru_RU\" type=\"text/javascript\"></script>
  119.     <script type=\"text/javascript\">
  120.         ;var RoutingDecorator = {
  121.             generate: function (name, params) {
  122.                 const orig_name = name;
  123.                 try {
  124.                     Routing.getRoute(name)
  125.                 } catch(error) {
  126.                     name = name + '.' + '";
  127.         // line 33
  128.         echo twig_escape_filter($this->env, twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, (isset($context["app"]) || array_key_exists("app", $context) ? $context["app"] : (function () { throw new RuntimeError('Variable "app" does not exist.', 33, $this->source); })()), "request", [], "any", false, false, false, 33), "locale", [], "any", false, false, false, 33), "html", null, true);
  129.         echo "';
  130.                     try {
  131.                         Routing.getRoute(name)
  132.                     } catch(error) {
  133.                         name = orig_name;
  134.                     }
  135.                 }
  136.                 return Routing.generate(name, params);
  137.             }
  138.         };
  139.         ;(function () {
  140.             document.addEventListener('DOMContentLoaded', _ => {
  141.                 var avatarPath = '";
  142.         // line 48
  143.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("", "profile_media_avatar"), "html", null, true);
  144.         echo "';
  145.                 var photoPath = '";
  146.         // line 49
  147.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("", "profile_media"), "html", null, true);
  148.         echo "';
  149.                 var thumbPath = '";
  150.         // line 50
  151.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("", "saloon_media_thumb"), "html", null, true);
  152.         echo "';
  153.                 var mapContainer = document.querySelector('#map');
  154.                 var preloader = document.querySelector('#preloader');
  155.                 var refreshButton = document.querySelector('#map_refresh');
  156.                 var resetButton = document.querySelector('#map_reset');
  157.                 var mapStatus = document.querySelector('#map_status');
  158.                 var loading = false;
  159.                 var mapContext = mapContainer.getAttribute('data-map-context');
  160.                 var cityUriIdentity = mapContainer.getAttribute('data-city-uri-idenity');
  161.                 var cityLatitude = mapContainer.getAttribute('data-city-latitude');
  162.                 var cityLongitude = mapContainer.getAttribute('data-city-longitude');
  163.                 var formName = 'filter_map_form';
  164.                 var multipleCities = ";
  165.         // line 62
  166.         echo twig_escape_filter($this->env, (isset($context["multipleCities"]) || array_key_exists("multipleCities", $context) ? $context["multipleCities"] : (function () { throw new RuntimeError('Variable "multipleCities" does not exist.', 62, $this->source); })()), "html", null, true);
  167.         echo ";
  168.                 var routesUrl = '/js/fos_js_routes";
  169.         // line 63
  170.         echo (((isset($context["multipleCities"]) || array_key_exists("multipleCities", $context) ? $context["multipleCities"] : (function () { throw new RuntimeError('Variable "multipleCities" does not exist.', 63, $this->source); })())) ? ("_city_prefixed") : (""));
  171.         echo ".json';
  172.                 if (typeof ymaps === 'undefined') {
  173.                     mapStatus.textContent = 'Не удалось загрузить Яндекс.Карты. Перезагрузите страницу.';
  174.                     return;
  175.                 }
  176.                 var mapLoadTimeout = setTimeout(() => {
  177.                     mapStatus.textContent = 'Не удалось загрузить Яндекс.Карты. Перезагрузите страницу.';
  178.                 }, 15000);
  179.                 loadRoutes();
  180.                 var myMap, clusterer;
  181.                 ymaps.ready(function () {
  182.                     clearTimeout(mapLoadTimeout);
  183.                     myMap = new ymaps.Map('map', {
  184.                             center: [cityLatitude, cityLongitude],
  185.                             zoom: 9,
  186.                             behaviors: ['default', 'scrollZoom']
  187.                         }, {
  188.                             searchControlProvider: 'yandex#search'
  189.                         });
  190.                     clusterer = new ymaps.Clusterer({
  191.                             preset: 'islands#invertedVioletClusterIcons',//Через кластеризатор можно указать только стили кластеров,стили для меток нужно назначать каждой метке отдельно.
  192.                             groupByCoordinates: false,//Ставим true, если хотим кластеризовать только точки с одинаковыми координатами.
  193.                             //Опции кластеров указываем в кластеризаторе с префиксом \"cluster\".
  194.                             clusterDisableClickZoom: true,
  195.                             clusterHideIconOnBalloonOpen: false,
  196.                             geoObjectHideIconOnBalloonOpen: false
  197.                     });
  198.                     // Можно менять опции кластеризатора после создания.
  199.                     clusterer.options.set({
  200.                         gridSize: 80,
  201.                         clusterDisableClickZoom: true
  202.                     });
  203.                     loadForm();
  204.                     refreshButton.addEventListener('click', function () {
  205.                         if (document.querySelector('form[name=\"' + formName + '\"]')) {
  206.                             filterData();
  207.                         } else {
  208.                             loadForm();
  209.                         }
  210.                     });
  211.                     resetButton.addEventListener('click', function () {
  212.                         document.querySelector('form[name=\"' + formName + '\"]').reset();
  213.                         filterData();
  214.                     });
  215.                 });
  216.                 function loadRoutes() {
  217.                     \$.ajax({
  218.                         url:routesUrl,
  219.                         dataType: \"json\",
  220.                         async: false,
  221.                         success: function (routes) {
  222.                             Routing.setRoutingData(routes);
  223.                         },
  224.                         error: function (xhr, ajaxOptions, thrownError) {}
  225.                     });
  226.                 }
  227.                 function setFormSubmitListener() {
  228.                     document.querySelector(\"form[name=\"+formName+\"]\").addEventListener('submit', function(e){
  229.                         e.preventDefault();
  230.                         if(!clusterer)
  231.                             return;
  232.                         filterData();
  233.                         return false;
  234.                     });
  235.                 }
  236.                 function loadForm() {
  237.                     setLoading(true);
  238.                     fetch('";
  239.         // line 139
  240.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("map.form", ["city" => (isset($context["cityUriIdentity"]) || array_key_exists("cityUriIdentity", $context) ? $context["cityUriIdentity"] : (function () { throw new RuntimeError('Variable "cityUriIdentity" does not exist.', 139, $this->source); })())]), "html", null, true);
  241.         echo "', {
  242.                         mode: \"cors\",
  243.                         importance: \"low\",
  244.                         method: \"POST\",
  245.                         cache: 'no-store',
  246.                         headers: {
  247.                             \"Content-Type\": \"application/x-www-form-urlencoded\",
  248.                             \"X-Requested-With\": \"XMLHttpRequest\"
  249.                         },
  250.                         body: new URLSearchParams({mapContext: mapContext}).toString(),
  251.                     }).then(response => {
  252.                         if (!response.ok) {
  253.                             throw new Error('Cannot load map form');
  254.                         }
  255.                         return response.text();
  256.                     }).then(response => {
  257.                         document.querySelector('#map_form').innerHTML = response;
  258.                         setFormSubmitListener();
  259.                         setLoading(false);
  260.                         filterData();
  261.                     }).catch(() => {
  262.                         showError();
  263.                         setLoading(false);
  264.                     });
  265.                 }
  266.                 function setLoading(value) {
  267.                     loading = value;
  268.                     preloader.style.display = value ? 'block' : 'none';
  269.                     refreshButton.disabled = value;
  270.                     resetButton.disabled = value || !document.querySelector('form[name=\"' + formName + '\"]');
  271.                     if (value) {
  272.                         mapStatus.textContent = 'Загрузка…';
  273.                     }
  274.                 }
  275.                 function showError() {
  276.                     mapStatus.textContent = 'Не удалось обновить карту. Нажмите «Обновить карту», чтобы повторить запрос.';
  277.                 }
  278.                 function filterData() {
  279.                     if (loading) {
  280.                         return;
  281.                     }
  282.                     setLoading(true);
  283.                     var data = {};
  284.                     \$(\"form[name=\"+formName+\"]\").serializeArray().forEach((object)=>{
  285.                         //\"подгоняем\" данные под формат, ожидаемый формой при сабмите
  286.                         var fieldName = object.name.toString().replace(formName + '[', '').replace(']', '');
  287.                         var clearFieldName = fieldName.substr(0, fieldName.indexOf('['));
  288.                         if(~fieldName.indexOf('[]')) {
  289.                             checkArrayIsInFormObject(clearFieldName, data);
  290.                             data[clearFieldName].push(object.value);
  291.                         } else if(~fieldName.indexOf('[m')) {
  292.                             if(!object.value)
  293.                                 return;
  294.                             checkObjectIsInFormObject(clearFieldName, data);
  295.                             if(~fieldName.indexOf('[min]'))
  296.                                 data[clearFieldName]['min'] = object.value;
  297.                             if(~fieldName.indexOf('[max]'))
  298.                                 data[clearFieldName]['max'] = object.value;
  299.                         } else {
  300.                             data[fieldName] = object.value;
  301.                         }
  302.                     });
  303.                     \$.ajax({
  304.                         url:'";
  305.         // line 209
  306.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("map.filter", ["city" => (isset($context["cityUriIdentity"]) || array_key_exists("cityUriIdentity", $context) ? $context["cityUriIdentity"] : (function () { throw new RuntimeError('Variable "cityUriIdentity" does not exist.', 209, $this->source); })())]), "html", null, true);
  307.         echo "',
  308.                         type: \"POST\",
  309.                         dataType: \"json\",
  310.                         cache: false,
  311.                         data: {
  312.                             \"form\": JSON.stringify(data),
  313.                             \"mapContext\": mapContext,
  314.                             \"scale\": myMap.getZoom(),
  315.                         },
  316.                         async: true,
  317.                     }).then(getDetailsData).then(points => {
  318.                         updateMap(points);
  319.                         mapStatus.textContent = 'Анкеты: ' + points.profiles.length + '. Салоны: ' + points.saloons.length + '.';
  320.                     }).catch(showError).always(() => setLoading(false));
  321.                 }
  322.                 function checkArrayIsInFormObject(name, formObject) {
  323.                     if(false == formObject.hasOwnProperty(name))
  324.                         formObject[name] = [];
  325.                 }
  326.                 function checkObjectIsInFormObject(name, formObject) {
  327.                     if(false == formObject.hasOwnProperty(name))
  328.                         formObject[name] = {};
  329.                 }
  330.                 function getDetailsData(data) {
  331.                     const profilesRawData = data.profiles || [];
  332.                     const saloonsRawData = data.saloons || [];
  333.                     const profilesAllId = profilesRawData.map(_data => _data[0]).flat();
  334.                     const saloonsAllId = saloonsRawData.map(_data => _data[0]).flat();
  335.                     const profileArray = Array.isArray(profilesAllId) ? profilesAllId : [];
  336.                     const saloonIdArray = Array.isArray(saloonsAllId) ? saloonsAllId : [];
  337.                     const requestBody = {};
  338.                     requestBody.profiles = profileArray;
  339.                     requestBody.saloons = saloonIdArray;
  340.                     return fetch('";
  341.         // line 249
  342.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("map.detail", ["city" => (isset($context["cityUriIdentity"]) || array_key_exists("cityUriIdentity", $context) ? $context["cityUriIdentity"] : (function () { throw new RuntimeError('Variable "cityUriIdentity" does not exist.', 249, $this->source); })())]), "html", null, true);
  343.         echo "', {
  344.                         method: \"POST\",
  345.                         cache: 'no-store',
  346.                         headers: {
  347.                             'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  348.                             'X-Requested-With': 'XMLHttpRequest',
  349.                         },
  350.                         body: new URLSearchParams(requestBody).toString()
  351.                     })
  352.                     .then(response => {
  353.                         if (!response.ok) {
  354.                             throw new Error('Cannot load map details');
  355.                         }
  356.                         return response.json();
  357.                     });
  358.                 }
  359.                 function updateMap(points) {
  360.                     clusterer.removeAll();
  361.                     if (!points || (points.profiles.length == 0 && points.saloons.length == 0)) {
  362.                         myMap.setCenter([cityLatitude, cityLongitude], 9);
  363.                         return;
  364.                     }
  365.                     const mergedPoints = [...points.profiles, ...points.saloons];
  366.                     var getImgUrl = function(path, imgType) {
  367.                         if(path[0] == '/')
  368.                             return path;
  369.                             console.log(imgType)
  370.                             console.log(photoPath)
  371.                             console.log(thumbPath)
  372.                         var assetPackagePath = '';
  373.                         if(imgType == 'avatar')
  374.                             assetPackagePath = avatarPath;
  375.                         else if(imgType == 'photo')
  376.                             assetPackagePath = photoPath; // /media/profiles/vp/rd/vprdP4ShlKUpkOB.jpg
  377.                         else if(imgType == 'thumb')
  378.                             assetPackagePath = thumbPath; // /media/saloons/thumb///.jpg
  379.                         return `\${assetPackagePath}\${path.slice(0, 2).toLowerCase()}/\${path.slice(2, 4).toLowerCase()}/\${path}.jpg`;
  380.                     };
  381.                     var getPointData = function (point) {
  382.                         const isProfile = point[0] == 1;
  383.                         const isSaloon = point[0] == 2;
  384.                         let url = '';
  385.                         const uri = point[3];
  386.                         if(isProfile) {
  387.                             url = RoutingDecorator.generate(
  388.                                 'profile_preview.page',
  389.                                 multipleCities ? {city: cityUriIdentity, profile: uri} : {profile: uri}
  390.                             );
  391.                         } else if(isSaloon) {
  392.                             url = RoutingDecorator.generate(
  393.                                 'saloon_preview.page',
  394.                                 multipleCities ? {city: cityUriIdentity, saloon: uri} : {saloon: uri}
  395.                             );
  396.                         }
  397.                         var processProfileShowsUrl = '";
  398.         // line 312
  399.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("map.increment_profile_shows", (((isset($context["multipleCities"]) || array_key_exists("multipleCities", $context) ? $context["multipleCities"] : (function () { throw new RuntimeError('Variable "multipleCities" does not exist.', 312, $this->source); })())) ? (["city" => (isset($context["cityUriIdentity"]) || array_key_exists("cityUriIdentity", $context) ? $context["cityUriIdentity"] : (function () { throw new RuntimeError('Variable "cityUriIdentity" does not exist.', 312, $this->source); })())]) : ([]))), "html", null, true);
  400.         echo "';
  401.                         return {
  402.                             balloonContentHeader: '',
  403.                             balloonContentBody: '<p><img src=\"' + getImgUrl(point[5], isProfile ? 'avatar' : 'thumb') + '\" width=\"100\" /></p>' + '<font size=3><b><a target=\"_blank\" href=\"' + url + '\">Профиль</a></b></font>'
  404.                                 + '<img style=\"display:none;\" width=\"0\" height=\"0\" src=\"' + processProfileShowsUrl + '?id=' + (isProfile ? point[9] : null)+'\" />', //не убирать, функционально важно
  405.                             balloonContentFooter: '<font size=1>' + point[8] + ',' + point[9] + ',' + point[10] + '</strong>',
  406.                             clusterCaption: '<strong>' + (isSaloon ? 'Салон ' : '') + point[4] + '</strong>'
  407.                         };
  408.                     };
  409.                     var getPointOptions = function (index, type) {
  410.                         return {
  411.                             preset: type == 'profile' ? 'islands#violetIcon' : 'islands#redIcon'
  412.                         };
  413.                     };
  414.                     var geoObjects = [];
  415.                     for(var i = 0, len = mergedPoints.length; i < len; i++) {
  416.                         const _point = mergedPoints[i];
  417.                         geoObjects[i] = new ymaps.Placemark([_point[1], _point[2]], getPointData(_point), getPointOptions(i, _point[0] == 1));
  418.                     }
  419.                     //В кластеризатор можно добавить javascript-массив меток (не геоколлекцию) или одну метку.
  420.                     clusterer.add(geoObjects);
  421.                     myMap.geoObjects.add(clusterer);
  422.                     // Спозиционируем карту так, чтобы на ней были видны все объекты.
  423.                     if (mergedPoints.length === 1) {
  424.                         myMap.setCenter([mergedPoints[0][1], mergedPoints[0][2]], 14);
  425.                     } else {
  426.                         myMap.setBounds(clusterer.getBounds(), {
  427.                             checkZoomRange: true,
  428.                             zoomMargin: 40
  429.                         }).then(() => {
  430.                             if (myMap.getZoom() > 14) {
  431.                                 myMap.setZoom(14);
  432.                             }
  433.                         });
  434.                     }
  435.                 }
  436.             });
  437.         })();
  438.     </script>
  439. ";
  440.         
  441.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  442.         
  443.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  444.         
  445.         $__internal_b91a4435ea3baf1e2b6bfda56133dace->leave($__internal_b91a4435ea3baf1e2b6bfda56133dace_prof);
  446.     }
  447.     /**
  448.      * @codeCoverageIgnore
  449.      */
  450.     public function getTemplateName()
  451.     {
  452.         return "Map/page.html.twig";
  453.     }
  454.     /**
  455.      * @codeCoverageIgnore
  456.      */
  457.     public function isTraitable()
  458.     {
  459.         return false;
  460.     }
  461.     /**
  462.      * @codeCoverageIgnore
  463.      */
  464.     public function getDebugInfo()
  465.     {
  466.         return array (  459 => 312,  393 => 249,  350 => 209,  277 => 139,  198 => 63,  194 => 62,  179 => 50,  175 => 49,  171 => 48,  153 => 33,  139 => 22,  134 => 21,  121 => 20,  105 => 16,  101 => 15,  97 => 14,  93 => 13,  88 => 11,  80 => 5,  78 => 4,  65 => 3,  36 => 1,);
  467.     }
  468.     public function getSourceContext()
  469.     {
  470.         return new Source("{% extends 'grid.html.twig' %}
  471. {% block mainContainer %}
  472.    {# {{ form(form) }}#}
  473.     <div id=\"map_form\"></div>
  474.     <p>
  475.         <button type=\"button\" id=\"map_refresh\" disabled>Обновить карту</button>
  476.         <button type=\"button\" id=\"map_reset\" disabled>Сбросить фильтры</button>
  477.         <span id=\"map_status\" role=\"status\" aria-live=\"polite\">Загрузка карты…</span>
  478.     </p>
  479.     <img src=\"{{ asset('/static/preloader.gif') }}\" id=\"preloader\" style=\"display: none;\" />
  480.     <div id=\"map\"
  481.          data-city-uri-idenity=\"{{ cityUriIdentity }}\"
  482.          data-city-latitude=\"{{ cityLatitude }}\"
  483.          data-city-longitude=\"{{ cityLongitude }}\"
  484.          data-map-context=\"{{ mapContext }}\"
  485.          style=\"width:100%; height:500px;\"></div>
  486. {% endblock %}
  487. {% block javascripts %}
  488.     <script src=\"{{ asset('bundles/fosjsrouting/js/router.min.js') }}\"></script>
  489.     <script src=\"{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}\"></script>
  490.     <script src=\"https://code.jquery.com/jquery-3.4.1.min.js\"></script>
  491.     <script src=\"https://api-maps.yandex.ru/2.1/?lang=ru_RU\" type=\"text/javascript\"></script>
  492.     <script type=\"text/javascript\">
  493.         ;var RoutingDecorator = {
  494.             generate: function (name, params) {
  495.                 const orig_name = name;
  496.                 try {
  497.                     Routing.getRoute(name)
  498.                 } catch(error) {
  499.                     name = name + '.' + '{{ app.request.locale }}';
  500.                     try {
  501.                         Routing.getRoute(name)
  502.                     } catch(error) {
  503.                         name = orig_name;
  504.                     }
  505.                 }
  506.                 return Routing.generate(name, params);
  507.             }
  508.         };
  509.         ;(function () {
  510.             document.addEventListener('DOMContentLoaded', _ => {
  511.                 var avatarPath = '{{ asset('', 'profile_media_avatar') }}';
  512.                 var photoPath = '{{ asset('', 'profile_media') }}';
  513.                 var thumbPath = '{{ asset('', 'saloon_media_thumb') }}';
  514.                 var mapContainer = document.querySelector('#map');
  515.                 var preloader = document.querySelector('#preloader');
  516.                 var refreshButton = document.querySelector('#map_refresh');
  517.                 var resetButton = document.querySelector('#map_reset');
  518.                 var mapStatus = document.querySelector('#map_status');
  519.                 var loading = false;
  520.                 var mapContext = mapContainer.getAttribute('data-map-context');
  521.                 var cityUriIdentity = mapContainer.getAttribute('data-city-uri-idenity');
  522.                 var cityLatitude = mapContainer.getAttribute('data-city-latitude');
  523.                 var cityLongitude = mapContainer.getAttribute('data-city-longitude');
  524.                 var formName = 'filter_map_form';
  525.                 var multipleCities = {{ multipleCities }};
  526.                 var routesUrl = '/js/fos_js_routes{{ multipleCities ? '_city_prefixed' }}.json';
  527.                 if (typeof ymaps === 'undefined') {
  528.                     mapStatus.textContent = 'Не удалось загрузить Яндекс.Карты. Перезагрузите страницу.';
  529.                     return;
  530.                 }
  531.                 var mapLoadTimeout = setTimeout(() => {
  532.                     mapStatus.textContent = 'Не удалось загрузить Яндекс.Карты. Перезагрузите страницу.';
  533.                 }, 15000);
  534.                 loadRoutes();
  535.                 var myMap, clusterer;
  536.                 ymaps.ready(function () {
  537.                     clearTimeout(mapLoadTimeout);
  538.                     myMap = new ymaps.Map('map', {
  539.                             center: [cityLatitude, cityLongitude],
  540.                             zoom: 9,
  541.                             behaviors: ['default', 'scrollZoom']
  542.                         }, {
  543.                             searchControlProvider: 'yandex#search'
  544.                         });
  545.                     clusterer = new ymaps.Clusterer({
  546.                             preset: 'islands#invertedVioletClusterIcons',//Через кластеризатор можно указать только стили кластеров,стили для меток нужно назначать каждой метке отдельно.
  547.                             groupByCoordinates: false,//Ставим true, если хотим кластеризовать только точки с одинаковыми координатами.
  548.                             //Опции кластеров указываем в кластеризаторе с префиксом \"cluster\".
  549.                             clusterDisableClickZoom: true,
  550.                             clusterHideIconOnBalloonOpen: false,
  551.                             geoObjectHideIconOnBalloonOpen: false
  552.                     });
  553.                     // Можно менять опции кластеризатора после создания.
  554.                     clusterer.options.set({
  555.                         gridSize: 80,
  556.                         clusterDisableClickZoom: true
  557.                     });
  558.                     loadForm();
  559.                     refreshButton.addEventListener('click', function () {
  560.                         if (document.querySelector('form[name=\"' + formName + '\"]')) {
  561.                             filterData();
  562.                         } else {
  563.                             loadForm();
  564.                         }
  565.                     });
  566.                     resetButton.addEventListener('click', function () {
  567.                         document.querySelector('form[name=\"' + formName + '\"]').reset();
  568.                         filterData();
  569.                     });
  570.                 });
  571.                 function loadRoutes() {
  572.                     \$.ajax({
  573.                         url:routesUrl,
  574.                         dataType: \"json\",
  575.                         async: false,
  576.                         success: function (routes) {
  577.                             Routing.setRoutingData(routes);
  578.                         },
  579.                         error: function (xhr, ajaxOptions, thrownError) {}
  580.                     });
  581.                 }
  582.                 function setFormSubmitListener() {
  583.                     document.querySelector(\"form[name=\"+formName+\"]\").addEventListener('submit', function(e){
  584.                         e.preventDefault();
  585.                         if(!clusterer)
  586.                             return;
  587.                         filterData();
  588.                         return false;
  589.                     });
  590.                 }
  591.                 function loadForm() {
  592.                     setLoading(true);
  593.                     fetch('{{ path('map.form', {city: cityUriIdentity}) }}', {
  594.                         mode: \"cors\",
  595.                         importance: \"low\",
  596.                         method: \"POST\",
  597.                         cache: 'no-store',
  598.                         headers: {
  599.                             \"Content-Type\": \"application/x-www-form-urlencoded\",
  600.                             \"X-Requested-With\": \"XMLHttpRequest\"
  601.                         },
  602.                         body: new URLSearchParams({mapContext: mapContext}).toString(),
  603.                     }).then(response => {
  604.                         if (!response.ok) {
  605.                             throw new Error('Cannot load map form');
  606.                         }
  607.                         return response.text();
  608.                     }).then(response => {
  609.                         document.querySelector('#map_form').innerHTML = response;
  610.                         setFormSubmitListener();
  611.                         setLoading(false);
  612.                         filterData();
  613.                     }).catch(() => {
  614.                         showError();
  615.                         setLoading(false);
  616.                     });
  617.                 }
  618.                 function setLoading(value) {
  619.                     loading = value;
  620.                     preloader.style.display = value ? 'block' : 'none';
  621.                     refreshButton.disabled = value;
  622.                     resetButton.disabled = value || !document.querySelector('form[name=\"' + formName + '\"]');
  623.                     if (value) {
  624.                         mapStatus.textContent = 'Загрузка…';
  625.                     }
  626.                 }
  627.                 function showError() {
  628.                     mapStatus.textContent = 'Не удалось обновить карту. Нажмите «Обновить карту», чтобы повторить запрос.';
  629.                 }
  630.                 function filterData() {
  631.                     if (loading) {
  632.                         return;
  633.                     }
  634.                     setLoading(true);
  635.                     var data = {};
  636.                     \$(\"form[name=\"+formName+\"]\").serializeArray().forEach((object)=>{
  637.                         //\"подгоняем\" данные под формат, ожидаемый формой при сабмите
  638.                         var fieldName = object.name.toString().replace(formName + '[', '').replace(']', '');
  639.                         var clearFieldName = fieldName.substr(0, fieldName.indexOf('['));
  640.                         if(~fieldName.indexOf('[]')) {
  641.                             checkArrayIsInFormObject(clearFieldName, data);
  642.                             data[clearFieldName].push(object.value);
  643.                         } else if(~fieldName.indexOf('[m')) {
  644.                             if(!object.value)
  645.                                 return;
  646.                             checkObjectIsInFormObject(clearFieldName, data);
  647.                             if(~fieldName.indexOf('[min]'))
  648.                                 data[clearFieldName]['min'] = object.value;
  649.                             if(~fieldName.indexOf('[max]'))
  650.                                 data[clearFieldName]['max'] = object.value;
  651.                         } else {
  652.                             data[fieldName] = object.value;
  653.                         }
  654.                     });
  655.                     \$.ajax({
  656.                         url:'{{ path('map.filter', {city:cityUriIdentity}) }}',
  657.                         type: \"POST\",
  658.                         dataType: \"json\",
  659.                         cache: false,
  660.                         data: {
  661.                             \"form\": JSON.stringify(data),
  662.                             \"mapContext\": mapContext,
  663.                             \"scale\": myMap.getZoom(),
  664.                         },
  665.                         async: true,
  666.                     }).then(getDetailsData).then(points => {
  667.                         updateMap(points);
  668.                         mapStatus.textContent = 'Анкеты: ' + points.profiles.length + '. Салоны: ' + points.saloons.length + '.';
  669.                     }).catch(showError).always(() => setLoading(false));
  670.                 }
  671.                 function checkArrayIsInFormObject(name, formObject) {
  672.                     if(false == formObject.hasOwnProperty(name))
  673.                         formObject[name] = [];
  674.                 }
  675.                 function checkObjectIsInFormObject(name, formObject) {
  676.                     if(false == formObject.hasOwnProperty(name))
  677.                         formObject[name] = {};
  678.                 }
  679.                 function getDetailsData(data) {
  680.                     const profilesRawData = data.profiles || [];
  681.                     const saloonsRawData = data.saloons || [];
  682.                     const profilesAllId = profilesRawData.map(_data => _data[0]).flat();
  683.                     const saloonsAllId = saloonsRawData.map(_data => _data[0]).flat();
  684.                     const profileArray = Array.isArray(profilesAllId) ? profilesAllId : [];
  685.                     const saloonIdArray = Array.isArray(saloonsAllId) ? saloonsAllId : [];
  686.                     const requestBody = {};
  687.                     requestBody.profiles = profileArray;
  688.                     requestBody.saloons = saloonIdArray;
  689.                     return fetch('{{ path('map.detail', {city:cityUriIdentity}) }}', {
  690.                         method: \"POST\",
  691.                         cache: 'no-store',
  692.                         headers: {
  693.                             'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  694.                             'X-Requested-With': 'XMLHttpRequest',
  695.                         },
  696.                         body: new URLSearchParams(requestBody).toString()
  697.                     })
  698.                     .then(response => {
  699.                         if (!response.ok) {
  700.                             throw new Error('Cannot load map details');
  701.                         }
  702.                         return response.json();
  703.                     });
  704.                 }
  705.                 function updateMap(points) {
  706.                     clusterer.removeAll();
  707.                     if (!points || (points.profiles.length == 0 && points.saloons.length == 0)) {
  708.                         myMap.setCenter([cityLatitude, cityLongitude], 9);
  709.                         return;
  710.                     }
  711.                     const mergedPoints = [...points.profiles, ...points.saloons];
  712.                     var getImgUrl = function(path, imgType) {
  713.                         if(path[0] == '/')
  714.                             return path;
  715.                             console.log(imgType)
  716.                             console.log(photoPath)
  717.                             console.log(thumbPath)
  718.                         var assetPackagePath = '';
  719.                         if(imgType == 'avatar')
  720.                             assetPackagePath = avatarPath;
  721.                         else if(imgType == 'photo')
  722.                             assetPackagePath = photoPath; // /media/profiles/vp/rd/vprdP4ShlKUpkOB.jpg
  723.                         else if(imgType == 'thumb')
  724.                             assetPackagePath = thumbPath; // /media/saloons/thumb///.jpg
  725.                         return `\${assetPackagePath}\${path.slice(0, 2).toLowerCase()}/\${path.slice(2, 4).toLowerCase()}/\${path}.jpg`;
  726.                     };
  727.                     var getPointData = function (point) {
  728.                         const isProfile = point[0] == 1;
  729.                         const isSaloon = point[0] == 2;
  730.                         let url = '';
  731.                         const uri = point[3];
  732.                         if(isProfile) {
  733.                             url = RoutingDecorator.generate(
  734.                                 'profile_preview.page',
  735.                                 multipleCities ? {city: cityUriIdentity, profile: uri} : {profile: uri}
  736.                             );
  737.                         } else if(isSaloon) {
  738.                             url = RoutingDecorator.generate(
  739.                                 'saloon_preview.page',
  740.                                 multipleCities ? {city: cityUriIdentity, saloon: uri} : {saloon: uri}
  741.                             );
  742.                         }
  743.                         var processProfileShowsUrl = '{{ path('map.increment_profile_shows', multipleCities ? {city:cityUriIdentity} : {}) }}';
  744.                         return {
  745.                             balloonContentHeader: '',
  746.                             balloonContentBody: '<p><img src=\"' + getImgUrl(point[5], isProfile ? 'avatar' : 'thumb') + '\" width=\"100\" /></p>' + '<font size=3><b><a target=\"_blank\" href=\"' + url + '\">Профиль</a></b></font>'
  747.                                 + '<img style=\"display:none;\" width=\"0\" height=\"0\" src=\"' + processProfileShowsUrl + '?id=' + (isProfile ? point[9] : null)+'\" />', //не убирать, функционально важно
  748.                             balloonContentFooter: '<font size=1>' + point[8] + ',' + point[9] + ',' + point[10] + '</strong>',
  749.                             clusterCaption: '<strong>' + (isSaloon ? 'Салон ' : '') + point[4] + '</strong>'
  750.                         };
  751.                     };
  752.                     var getPointOptions = function (index, type) {
  753.                         return {
  754.                             preset: type == 'profile' ? 'islands#violetIcon' : 'islands#redIcon'
  755.                         };
  756.                     };
  757.                     var geoObjects = [];
  758.                     for(var i = 0, len = mergedPoints.length; i < len; i++) {
  759.                         const _point = mergedPoints[i];
  760.                         geoObjects[i] = new ymaps.Placemark([_point[1], _point[2]], getPointData(_point), getPointOptions(i, _point[0] == 1));
  761.                     }
  762.                     //В кластеризатор можно добавить javascript-массив меток (не геоколлекцию) или одну метку.
  763.                     clusterer.add(geoObjects);
  764.                     myMap.geoObjects.add(clusterer);
  765.                     // Спозиционируем карту так, чтобы на ней были видны все объекты.
  766.                     if (mergedPoints.length === 1) {
  767.                         myMap.setCenter([mergedPoints[0][1], mergedPoints[0][2]], 14);
  768.                     } else {
  769.                         myMap.setBounds(clusterer.getBounds(), {
  770.                             checkZoomRange: true,
  771.                             zoomMargin: 40
  772.                         }).then(() => {
  773.                             if (myMap.getZoom() > 14) {
  774.                                 myMap.setZoom(14);
  775.                             }
  776.                         });
  777.                     }
  778.                 }
  779.             });
  780.         })();
  781.     </script>
  782. {% endblock %}
  783. ", "Map/page.html.twig", "/app/templates/Map/page.html.twig");
  784.     }
  785. }