{"action":"created","comment":{"url":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments/64930548","id":64930548,"diff_hunk":"@@ -292,7 +302,445 @@ def whitelisted_infowindow(infowindow)\n                                                     INFOWINDOW_KEYS.include?(key) || INFOWINDOW_KEYS.include?(key.to_s)\n                                                   }\n       end\n+    end\n+\n+    # Used to migrate `wizard_properties` to `style_properties`\n+    class StylePropertiesGenerator\n+      def initialize(layer)\n+        @layer = layer\n+        @wizard_properties = @layer.options['wizard_properties']\n+        @source_type = @wizard_properties.present? ? @wizard_properties['type'] : nil\n+      end\n+\n+      def migrate(options)\n+        return nil unless @wizard_properties.present?\n+\n+        wpp = @wizard_properties['properties']\n+\n+        type = if @source_type == 'density'\n+                 wpp['geometry_type'] == 'Rectangles' ? 'squares' : 'hexabins'\n+               else\n+                 STYLE_PROPERTIES_TYPE[@source_type]\n+               end\n+        return nil unless type\n+\n+        options['cartocss_custom'] = options['tile_style_custom'] || false\n+        options['cartocss_history'] = options['tile_style_history'] || []\n+\n+        options['style_properties'] = {\n+          'autogenerated' => true,\n+          'type' => type,\n+          'properties' => wizard_properties_properties_to_style_properties_properties(wpp)\n+        }\n+\n+        merge_into_if_present(options['style_properties'], 'aggregation', generate_aggregation(wpp))\n+\n+        if SOURCE_TYPES_WITH_SQL_WRAP.include?(@source_type)\n+          options['sql_wrap'] = options['query_wrapper']\n+        end\n+\n+        if @source_type == 'cluster'\n+          options['cartocss_custom'] = true\n+        end\n+      end\n+\n+      private\n+\n+      STYLE_PROPERTIES_TYPE = {\n+        'polygon' => 'simple',\n+        'bubble' => 'simple',\n+        'choropleth' => 'simple',\n+        'category' => 'simple',\n+        'torque' => 'simple',\n+        'torque_cat' => 'simple',\n+        'cluster' => 'simple',\n+        'torque_heat' => 'heatmap'\n+      }.freeze\n+\n+      SOURCE_TYPES_WITH_SQL_WRAP = ['cluster', 'density']\n+\n+      def set_if_present(hash, key, value)\n+        # Dirty check because `false` is a valid `value`\n+        hash[key] = value unless value.nil? || value == ''\n+\n+        hash\n+      end\n+\n+      def merge_into_if_present(hash, key, hash_value)\n+        hash[key] = hash_value.merge!(hash[key] || {}) if hash_value.present?\n+\n+        hash\n+      end\n+\n+      def apply_direct_mapping(hash, original_hash, mapping)\n+        mapping.each do |source, target|\n+          set_if_present(hash, target, original_hash[source])\n+        end\n+\n+        hash\n+      end\n+\n+      def apply_default_opacity(hash)\n+        if hash['fixed'] && !hash['opacity']\n+          hash['opacity'] = 1\n+        end\n+\n+        hash\n+      end\n+\n+      PROPERTIES_DIRECT_MAPPING = {\n+        \"marker-comp-op\" => \"blending\",\n+        \"torque-blend-mode\" => \"blending\"\n+      }.freeze\n+\n+      def wizard_properties_properties_to_style_properties_properties(wizard_properties_properties)\n+        spp = {}\n+        wpp = wizard_properties_properties\n+        return spp unless wpp\n+\n+        apply_direct_mapping(spp, wpp, PROPERTIES_DIRECT_MAPPING)\n+\n+        unless wpp['geometry_type'] == 'line'\n+          merge_into_if_present(spp, 'stroke', generate_stroke(wpp))\n+        end\n+\n+        merge_into_if_present(spp, drawing_property(wpp), generate_drawing_properties(wpp))\n+\n+        merge_into_if_present(spp, 'labels', generate_labels(wpp))\n+\n+        merge_into_if_present(spp, 'animated', generate_animated(wpp))\n+\n+        set_property(spp, wpp)\n+\n+        spp\n+      end\n+\n+      def drawing_property(wpp)\n+        wpp['geometry_type'] == 'line' ? 'stroke' : 'fill'\n+      end\n+\n+      def set_property(spp, wpp)\n+        return unless wpp['property']\n+\n+        drawing_property = drawing_property(wpp)\n+\n+        destination = case @source_type\n+                      when 'bubble'\n+                        spp[drawing_property]['size']\n+                      when 'choropleth', 'category'\n+                        spp[drawing_property]['color']\n+                      when 'torque', 'torque_heat', 'torque_cat'\n+                        spp['animated']\n+                      when 'density'\n+                        spp['aggregation']['value']\n+                      else\n+                        raise \"Unsupported source type: #{@source_type}\"\n+                      end\n+\n+        destination['attribute'] = wpp['property']\n+      end\n+\n+      def generate_drawing_properties(wpp)\n+        fill = {}\n+\n+        merge_into_if_present(fill, @source_type == 'bubble' ? 'size' : 'color', generate_dimension_properties(wpp))\n+\n+        case @source_type\n+        when 'choropleth', 'category'\n+          fill['size'] = { 'fixed' => 10 }.merge(fill['size'] || {})\n+        when 'torque_heat'\n+          fill['size'] = { 'fixed' => 35 }.merge(fill['size'] || {})\n+        end\n+\n+        merge_into_if_present(fill, 'color', generate_color(wpp))\n+\n+        fill\n+      end\n+\n+      STROKE_SIZE_DIRECT_MAPPING = {\n+        \"marker-line-width\" => 'fixed'\n+      }\n+\n+      STROKE_COLOR_DIRECT_MAPPING = {\n+        \"marker-line-color\" => 'fixed',\n+        \"marker-line-opacity\" => 'opacity'\n+      }\n+\n+      def generate_stroke(wpp)\n+        stroke = {}\n+\n+        merge_into_if_present(stroke, 'size', apply_direct_mapping({}, wpp, STROKE_SIZE_DIRECT_MAPPING))\n+        merge_into_if_present(stroke, 'color', apply_direct_mapping({}, wpp, STROKE_COLOR_DIRECT_MAPPING))\n+\n+        stroke\n+      end\n+\n+      TORQUE_HEAT_COLOR_DEFAULTS = {\n+        'attribute' => 'points_agg',\n+        'range' => ['blue', 'cyan', 'lightgreen', 'yellow', 'orange', 'red'],\n+        'bins' => 6\n+      }.freeze\n+\n+      def generate_color(wpp)\n+        color = {}\n+\n+        %w(polygon marker).each do |prefix|\n+          set_if_present(color, 'fixed', wpp[\"#{prefix}-fill\"])\n+\n+          unless color['opacity']\n+            set_if_present(color, 'opacity', wpp[\"#{prefix}-opacity\"])\n+          end\n+\n+          apply_default_opacity(color)\n+        end\n+\n+        color['range'] = generate_range_from_categories(wpp['categories']) if wpp['categories'].present?\n+\n+        color.merge!(TORQUE_HEAT_COLOR_DEFAULTS) if @source_type == 'torque_heat'\n+\n+        color\n+      end\n+\n+      def generate_range_from_categories(categories)\n+        categories.map { |c| c['color'] }\n+      end\n+\n+      SIZE_DIRECT_MAPPING = {\n+        'qfunction' => 'quantification'\n+      }.freeze\n+\n+      COLOR_RANGE_SOURCE_TYPES = ['choropleth', 'density']","path":"app/controllers/carto/api/layer_presenter.rb","position":242,"original_position":242,"commit_id":"a6b3b9dfb9bd913e8924d7bf3a44785639928bc1","original_commit_id":"a6b3b9dfb9bd913e8924d7bf3a44785639928bc1","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"Freeze mutable objects assigned to constants.","created_at":"2016-05-27T16:22:48Z","updated_at":"2016-05-27T16:22:48Z","html_url":"https://github.com/CartoDB/cartodb/pull/7406#discussion_r64930548","pull_request_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406","_links":{"self":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments/64930548"},"html":{"href":"https://github.com/CartoDB/cartodb/pull/7406#discussion_r64930548"},"pull_request":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406"}}},"pull_request":{"url":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406","id":70227259,"html_url":"https://github.com/CartoDB/cartodb/pull/7406","diff_url":"https://github.com/CartoDB/cartodb/pull/7406.diff","patch_url":"https://github.com/CartoDB/cartodb/pull/7406.patch","issue_url":"https://api.github.com/repos/CartoDB/cartodb/issues/7406","number":7406,"state":"open","locked":false,"title":"7391 generate style properties on the fly based on wizard properties","user":{"login":"juanignaciosl","id":932968,"avatar_url":"https://avatars.githubusercontent.com/u/932968?v=3","gravatar_id":"","url":"https://api.github.com/users/juanignaciosl","html_url":"https://github.com/juanignaciosl","followers_url":"https://api.github.com/users/juanignaciosl/followers","following_url":"https://api.github.com/users/juanignaciosl/following{/other_user}","gists_url":"https://api.github.com/users/juanignaciosl/gists{/gist_id}","starred_url":"https://api.github.com/users/juanignaciosl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juanignaciosl/subscriptions","organizations_url":"https://api.github.com/users/juanignaciosl/orgs","repos_url":"https://api.github.com/users/juanignaciosl/repos","events_url":"https://api.github.com/users/juanignaciosl/events{/privacy}","received_events_url":"https://api.github.com/users/juanignaciosl/received_events","type":"User","site_admin":false},"body":"_ongoing_","created_at":"2016-05-16T17:04:24Z","updated_at":"2016-05-27T16:22:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e3e3da97f146faa4f8dfac3be4e5e0c8b8af3ea2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406/commits","review_comments_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406/comments","review_comment_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/issues/7406/comments","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/a6b3b9dfb9bd913e8924d7bf3a44785639928bc1","head":{"label":"CartoDB:7391-Generate_style_properties_on_the_fly_based_on_wizard_properties","ref":"7391-Generate_style_properties_on_the_fly_based_on_wizard_properties","sha":"a6b3b9dfb9bd913e8924d7bf3a44785639928bc1","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":4909355,"name":"cartodb","full_name":"CartoDB/cartodb","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/cartodb","description":"Location Intelligence & Data Visualization tool","fork":false,"url":"https://api.github.com/repos/CartoDB/cartodb","forks_url":"https://api.github.com/repos/CartoDB/cartodb/forks","keys_url":"https://api.github.com/repos/CartoDB/cartodb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/cartodb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/cartodb/teams","hooks_url":"https://api.github.com/repos/CartoDB/cartodb/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/cartodb/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/cartodb/events","assignees_url":"https://api.github.com/repos/CartoDB/cartodb/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/cartodb/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/cartodb/tags","blobs_url":"https://api.github.com/repos/CartoDB/cartodb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/cartodb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/cartodb/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/cartodb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/cartodb/languages","stargazers_url":"https://api.github.com/repos/CartoDB/cartodb/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/cartodb/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/cartodb/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/cartodb/subscription","commits_url":"https://api.github.com/repos/CartoDB/cartodb/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/cartodb/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/cartodb/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/cartodb/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/cartodb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/cartodb/merges","archive_url":"https://api.github.com/repos/CartoDB/cartodb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/cartodb/downloads","issues_url":"https://api.github.com/repos/CartoDB/cartodb/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/cartodb/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/cartodb/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/cartodb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/cartodb/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/cartodb/releases{/id}","deployments_url":"https://api.github.com/repos/CartoDB/cartodb/deployments","created_at":"2012-07-05T15:23:45Z","updated_at":"2016-05-27T04:40:33Z","pushed_at":"2016-05-27T16:22:42Z","git_url":"git://github.com/CartoDB/cartodb.git","ssh_url":"git@github.com:CartoDB/cartodb.git","clone_url":"https://github.com/CartoDB/cartodb.git","svn_url":"https://github.com/CartoDB/cartodb","homepage":"http://cartodb.com","size":387233,"stargazers_count":1142,"watchers_count":1142,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":289,"mirror_url":null,"open_issues_count":929,"forks":289,"open_issues":929,"watchers":1142,"default_branch":"master"}},"base":{"label":"CartoDB:master","ref":"master","sha":"02b6c860fa249fa01d6fd78289de033695a74875","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":4909355,"name":"cartodb","full_name":"CartoDB/cartodb","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/cartodb","description":"Location Intelligence & Data Visualization tool","fork":false,"url":"https://api.github.com/repos/CartoDB/cartodb","forks_url":"https://api.github.com/repos/CartoDB/cartodb/forks","keys_url":"https://api.github.com/repos/CartoDB/cartodb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/cartodb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/cartodb/teams","hooks_url":"https://api.github.com/repos/CartoDB/cartodb/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/cartodb/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/cartodb/events","assignees_url":"https://api.github.com/repos/CartoDB/cartodb/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/cartodb/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/cartodb/tags","blobs_url":"https://api.github.com/repos/CartoDB/cartodb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/cartodb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/cartodb/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/cartodb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/cartodb/languages","stargazers_url":"https://api.github.com/repos/CartoDB/cartodb/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/cartodb/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/cartodb/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/cartodb/subscription","commits_url":"https://api.github.com/repos/CartoDB/cartodb/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/cartodb/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/cartodb/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/cartodb/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/cartodb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/cartodb/merges","archive_url":"https://api.github.com/repos/CartoDB/cartodb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/cartodb/downloads","issues_url":"https://api.github.com/repos/CartoDB/cartodb/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/cartodb/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/cartodb/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/cartodb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/cartodb/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/cartodb/releases{/id}","deployments_url":"https://api.github.com/repos/CartoDB/cartodb/deployments","created_at":"2012-07-05T15:23:45Z","updated_at":"2016-05-27T04:40:33Z","pushed_at":"2016-05-27T16:22:42Z","git_url":"git://github.com/CartoDB/cartodb.git","ssh_url":"git@github.com:CartoDB/cartodb.git","clone_url":"https://github.com/CartoDB/cartodb.git","svn_url":"https://github.com/CartoDB/cartodb","homepage":"http://cartodb.com","size":387233,"stargazers_count":1142,"watchers_count":1142,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":289,"mirror_url":null,"open_issues_count":929,"forks":289,"open_issues":929,"watchers":1142,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406"},"html":{"href":"https://github.com/CartoDB/cartodb/pull/7406"},"issue":{"href":"https://api.github.com/repos/CartoDB/cartodb/issues/7406"},"comments":{"href":"https://api.github.com/repos/CartoDB/cartodb/issues/7406/comments"},"review_comments":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406/comments"},"review_comment":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/7406/commits"},"statuses":{"href":"https://api.github.com/repos/CartoDB/cartodb/statuses/a6b3b9dfb9bd913e8924d7bf3a44785639928bc1"}}}}
{"actor":{"display_login":"houndci-bot"}}