private function _add_hooks()
 {
     $this->_cache = Upfront_Cache::get_instance(Upfront_Cache::TYPE_LONG_TERM);
     if (Upfront_OutputBehavior::has_experiments()) {
         add_filter('upfront-experiments-styles-debounce_dependency_load', array($this, 'add_style_load_url'));
         add_filter('upfront-experiments-scripts-debounce_dependency_load', array($this, 'add_script_load_url'));
     } else {
         add_action('upfront-layout-applied', array($this, 'load_styles'));
         add_action('upfront-layout-applied', array($this, 'load_scripts'));
     }
     upfront_add_ajax('upfront-element-styles', array($this, 'serve_styles'));
     upfront_add_ajax_nopriv('upfront-element-styles', array($this, 'serve_styles'));
     upfront_add_ajax('upfront-element-scripts', array($this, 'serve_scripts'));
     upfront_add_ajax_nopriv('upfront-element-scripts', array($this, 'serve_scripts'));
 }
 public function get_grid($editor = false)
 {
     $override_baseline = $_SERVER['REQUEST_METHOD'] == 'POST' ? intval(!empty($_POST['baseline']) ? $_POST['baseline'] : 0) : intval(!empty($_GET['baseline']) ? $_GET['baseline'] : 0);
     $breakpoints = $this->_grid->get_breakpoints();
     $style = '';
     // Let's go with caching
     $cache = Upfront_Cache::get_instance();
     $cache_key = $cache->key('grid', array($this->_grid, $breakpoints, $editor));
     $css = $cache->get($cache_key);
     if (false !== $css) {
         return $editor ? $css : self::compress($css);
     }
     foreach ($breakpoints as $scope => $breakpoint) {
         if ($scope != 'desktop') {
             continue;
         }
         $columns = $breakpoint->get_columns();
         $column_width = $breakpoint->get_column_width();
         $baseline_grid = $override_baseline > 0 ? $override_baseline : $breakpoint->get_baseline();
         $width = $breakpoint->get_prefix(Upfront_GridBreakpoint::PREFIX_WIDTH);
         $margin_left = $breakpoint->get_prefix(Upfront_GridBreakpoint::PREFIX_MARGIN_LEFT);
         $margin_right = $breakpoint->get_prefix(Upfront_GridBreakpoint::PREFIX_MARGIN_RIGHT);
         $margin_top = $breakpoint->get_prefix(Upfront_GridBreakpoint::PREFIX_MARGIN_TOP);
         $margin_bottom = $breakpoint->get_prefix(Upfront_GridBreakpoint::PREFIX_MARGIN_BOTTOM);
         $rules = array();
         // the rules were rendered from bigger columns to smaller one, to allow CSS overriding to work properly
         for ($i = $columns; $i >= 0; $i--) {
             // main rules, e.g: .c24
             $rules[] = ".{$width}{$i}" . '{' . sprintf('width:%.3f%%;', floor(100.0 / $columns * $i * 1000) / 1000) . '}' . '';
             $rules[] = ".{$margin_left}{$i}" . '{' . sprintf('margin-left:%.3f%%;', floor(100.0 / $columns * $i * 1000) / 1000) . '}' . '';
             if ($i == $columns) {
                 continue;
             }
             // getting sub rules, e.g: .c24 .c22
             $sub_selector = array(".{$width}{$i}");
             // the classes that got 100% width/margin applied
             $max_classes_width = array();
             $max_classes_margin_left = array();
             //$max_classes_margin_right = array();
             for ($x = $columns; $x >= $i; $x--) {
                 $max_classes_width[] = implode(" .{$width}{$x}, ", $sub_selector) . " .{$width}{$x}";
                 $max_classes_margin_left[] = implode(" .{$margin_left}{$x}, ", $sub_selector) . " .{$margin_left}{$x}";
                 //$max_classes_margin_right[] = implode(" .{$margin_right}{$x}, ", $sub_selector) . " .{$margin_right}{$x}";
             }
             if (!empty($max_classes_width)) {
                 $rules[] = implode(', ', $max_classes_width) . '{' . sprintf('width:%.3f%%;', 100.0) . '}' . '';
             }
             if (!empty($max_classes_margin_left)) {
                 $rules[] = implode(', ', $max_classes_margin_left) . '{' . sprintf('margin-left:%.3f%%;', 100.0) . '}' . '';
             }
             // the smaller ones
             for ($c = $i - 1; $c > 0; $c--) {
                 $width_classes = $this->_get_width_classes($c, $i, $columns, $width, $margin_left);
                 $width_selector = array();
                 foreach ($width_classes as $width_class) {
                     $width_selector[] = implode(" {$width_class}, ", $sub_selector) . " {$width_class}";
                 }
                 //$rules[] = implode(" .{$width}{$c}, ", $sub_selector) . " .{$width}{$c}" .
                 $rules[] = implode(", ", $width_selector) . '{' . sprintf('width:%.3f%%;', floor(100.0 / $i * $c * 1000) / 1000) . '}' . '';
                 $rules[] = implode(" .{$margin_left}{$c}, ", $sub_selector) . " .{$margin_left}{$c}" . '{' . sprintf('margin-left:%.3f%%;', floor(100.0 / $i * $c * 1000) / 1000) . '}' . '';
             }
         }
         // top and bottom margin, as we don't have any maximum rows/height specified, we use 300/2000 here (max 1500/10000px for 5px baseline, depending if user has edit permission or not)
         $max_margin_top = 300;
         if ($editor) {
             $max_margin_top = 2000;
         }
         for ($i = 1; $i <= $max_margin_top; $i++) {
             $rules[] = ".{$margin_top}{$i}" . '{' . sprintf('margin-top:%dpx;', $i * $baseline_grid) . '}' . '';
         }
         if ($editor) {
             $style .= $breakpoint->get_editor_root_rule($scope, $breakpoints) . "\n";
         }
         $style .= join("\n", $rules);
     }
     $cache->set($cache_key, $style);
     // Cache stuff for laters
     return $editor ? $style : self::compress($style);
 }